| @@ -1,5 +1,4 @@ | |||
| using GameClass.Skill; | |||
| using Preparation.Interface; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| @@ -1,5 +1,4 @@ | |||
| using GameClass.Skill; | |||
| using Preparation.Utility; | |||
| using Preparation.Utility; | |||
| using Preparation.Interface; | |||
| using System.Collections.Generic; | |||
| using System; | |||
| @@ -37,20 +36,6 @@ namespace GameClass.GameObj | |||
| return false; | |||
| } | |||
| public bool UseActiveSkill(Map map, ActiveSkillType activeSkillType) | |||
| { | |||
| if (Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| return ActiveSkillFactory.FindIActiveSkill(activeSkillType).SkillEffect(map, this); | |||
| return false; | |||
| } | |||
| public void UsePassiveSkill(Map map, PassiveSkillType passiveSkillType) | |||
| { | |||
| if (Occupation.ListOfIPassiveSkill.Contains(passiveSkillType)) | |||
| PassiveSkillFactory.FindIPassiveSkill(passiveSkillType).SkillEffect(map, this); | |||
| return; | |||
| } | |||
| public bool IsGhost() | |||
| { | |||
| return GameData.IsGhost(CharacterType); | |||
| @@ -1,5 +1,4 @@ | |||
| using GameClass.Skill; | |||
| using Preparation.Utility; | |||
| using Preparation.Utility; | |||
| using Preparation.Interface; | |||
| namespace GameClass.GameObj | |||
| @@ -40,20 +39,6 @@ namespace GameClass.GameObj | |||
| } | |||
| public int OrgTreatSpeed { get; protected set; } = GameData.basicTreatSpeed; | |||
| protected int rescueSpeed = GameData.basicRescueSpeed; | |||
| public int RescueSpeed | |||
| { | |||
| get => rescueSpeed; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| rescueSpeed = value; | |||
| } | |||
| } | |||
| } | |||
| public int OrgRescueSpeed { get; protected set; } = GameData.basicRescueSpeed; | |||
| public int MaxGamingAddiction { get; protected set; } | |||
| private int gamingAddiction; | |||
| public int GamingAddiction | |||
| @@ -59,7 +59,6 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| if (IsResetting) return PlayerStateType.IsDeceased; | |||
| if (IsMoving) return PlayerStateType.IsMoving; | |||
| return playerState; | |||
| } | |||
| @@ -214,6 +213,21 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| private int timeOfOpeningOrLocking; | |||
| public int TimeOfOpeningOrLocking | |||
| { | |||
| get => timeOfOpeningOrLocking; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| timeOfOpeningOrLocking = value; | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 进行一次攻击 | |||
| /// </summary> | |||
| @@ -1,227 +0,0 @@ | |||
| using GameClass.GameObj; | |||
| using System.Threading; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| using Timothy.FrameRateTask; | |||
| namespace GameClass.Skill | |||
| { | |||
| public class BecomeVampire : IActiveSkill // 化身吸血鬼 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.Vampire += 0.5; | |||
| Debugger.Output(player, "becomes vampire!"); | |||
| }, | |||
| () => | |||
| { | |||
| double tempVam = player.Vampire - 0.5; | |||
| player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; | |||
| }); | |||
| } | |||
| } | |||
| public class BeginToCharge : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.Vampire += 0.5; | |||
| Debugger.Output(player, "becomes vampire!"); | |||
| }, | |||
| () => | |||
| { | |||
| double tempVam = player.Vampire - 0.5; | |||
| player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; | |||
| }); | |||
| } | |||
| } | |||
| public class BecomeInvisible : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 6; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.IsInvisible = true; | |||
| Debugger.Output(player, "uses atombomb!"); | |||
| }, | |||
| () => | |||
| { player.IsInvisible = false; }); | |||
| } | |||
| } | |||
| public class NuclearWeapon : IActiveSkill // 核武器 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 7; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.AtomBomb; | |||
| Debugger.Output(player, "uses atombomb!"); | |||
| }, | |||
| () => | |||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| } | |||
| public class UseKnife : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 2; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.FlyingKnife; | |||
| Debugger.Output(player, "uses flyingknife!"); | |||
| }, | |||
| () => | |||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| } | |||
| public class SuperFast : IActiveSkill // 3倍速 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 4; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||
| { | |||
| player.AddMoveSpeed(this.DurationTime, 3.0); | |||
| Debugger.Output(player, "moves very fast!"); | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| } | |||
| public class NoCommonSkill : IActiveSkill // 这种情况不该发生,定义着以防意外 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Map map, Character player) | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| public static class ActiveSkillFactory | |||
| { | |||
| public static bool SkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) | |||
| { | |||
| lock (activeSkill.ActiveSkillLock) | |||
| { | |||
| ActiveSkillType activeSkillType = FindActiveSkillType(activeSkill); | |||
| if (player.TimeUntilActiveSkillAvailable[activeSkillType] == 0) | |||
| { | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, activeSkill.SkillCD); | |||
| new Thread | |||
| (() => | |||
| { | |||
| startSkill(); | |||
| new FrameRateTaskExecutor<int>( | |||
| () => !player.IsResetting, | |||
| () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(activeSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| } | |||
| .Start(); | |||
| endSkill(); | |||
| Debugger.Output(player, "return to normal."); | |||
| new FrameRateTaskExecutor<int>( | |||
| () => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsResetting, | |||
| () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| } | |||
| .Start(); | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0); | |||
| Debugger.Output(player, "CommonSkill is ready."); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| Debugger.Output(player, "CommonSkill is cooling down!"); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| public static IActiveSkill? FindIActiveSkill(ActiveSkillType activeSkillType) | |||
| { | |||
| switch (activeSkillType) | |||
| { | |||
| case ActiveSkillType.BecomeInvisible: | |||
| return new BecomeInvisible(); | |||
| default: | |||
| return null; | |||
| } | |||
| } | |||
| public static ActiveSkillType FindActiveSkillType(IActiveSkill ActiveSkill) | |||
| { | |||
| switch (ActiveSkill) | |||
| { | |||
| case BecomeInvisible: | |||
| return ActiveSkillType.BecomeInvisible; | |||
| case UseKnife: | |||
| return ActiveSkillType.UseKnife; | |||
| case BeginToCharge: | |||
| return ActiveSkillType.BeginToCharge; | |||
| default: | |||
| return ActiveSkillType.Null; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| using Preparation.Utility; | |||
| using GameClass.GameObj; | |||
| using System.Collections.Generic; | |||
| namespace GameClass.Skill | |||
| { | |||
| public interface ISkill | |||
| { | |||
| } | |||
| public interface IPassiveSkill : ISkill | |||
| { | |||
| public void SkillEffect(Map map, Character player); | |||
| } | |||
| public interface IActiveSkill : ISkill | |||
| { | |||
| public int SkillCD { get; } | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public object ActiveSkillLock { get; } | |||
| public bool SkillEffect(Map map, Character player); | |||
| } | |||
| } | |||
| @@ -1,161 +0,0 @@ | |||
| using System; | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Timothy.FrameRateTask; | |||
| namespace GameClass.Skill // 被动技能开局时就释放,持续到游戏结束 | |||
| { | |||
| public class RecoverAfterBattle : IPassiveSkill // 脱战回血,普通子弹 | |||
| { | |||
| public void SkillEffect(Map map, Character player) | |||
| { | |||
| const int recoverDegree = 5; // 每帧回复血量 | |||
| int nowHP = player.HP; | |||
| int lastHP = nowHP; | |||
| long waitTime = 0; | |||
| const long interval = 10000; // 每隔interval时间不受伤害,角色即开始回血 | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => true, | |||
| () => | |||
| { | |||
| lastHP = nowHP; // lastHP等于上一帧的HP | |||
| nowHP = player.HP; // nowHP更新为这一帧的HP | |||
| if (lastHP > nowHP) // 这一帧扣血了 | |||
| { | |||
| waitTime = 0; | |||
| } | |||
| else if (waitTime < interval) | |||
| { | |||
| waitTime += GameData.frameDuration; | |||
| } | |||
| if (waitTime >= interval) // 回复时,每帧(50ms)回复5,即1s回复100。 | |||
| player.TryAddHp(recoverDegree); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: GameData.gameDuration | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| } | |||
| public class SpeedUpWhenLeavingGrass : IPassiveSkill // 3倍速 | |||
| { | |||
| public void SkillEffect(Map map, Character player) | |||
| { | |||
| PlaceType nowPlace = map.GetPlaceType(player.Position); | |||
| PlaceType lastPlace = nowPlace; | |||
| bool speedup = false; | |||
| const int SpeedUpTime = 2000; // 加速时间:2s | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => true, | |||
| () => | |||
| { | |||
| lastPlace = nowPlace; | |||
| nowPlace = map.GetPlaceType(player.Position); | |||
| if ((lastPlace == PlaceType.Grass) && nowPlace == PlaceType.Null) | |||
| { | |||
| if (!speedup) | |||
| { | |||
| new Thread(() => | |||
| { | |||
| speedup = true; | |||
| player.AddMoveSpeed(SpeedUpTime, 3.0); | |||
| speedup = false; | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| } | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: GameData.gameDuration | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| } | |||
| public class Vampire : IPassiveSkill // 被动就是吸血,普通子弹 | |||
| { | |||
| public void SkillEffect(Map map, Character player) | |||
| { | |||
| player.OriVampire = 0.5; | |||
| player.Vampire = player.OriVampire; | |||
| } | |||
| } | |||
| public class NoPassiveSkill : IPassiveSkill // 没技能,这种情况不应该发生,先定义着以防意外 | |||
| { | |||
| public void SkillEffect(Map map, Character player) | |||
| { | |||
| } | |||
| } | |||
| public static class PassiveSkillFactory | |||
| { | |||
| public static IPassiveSkill? FindIPassiveSkill(PassiveSkillType passiveSkillType) | |||
| { | |||
| switch (passiveSkillType) | |||
| { | |||
| default: | |||
| return null; | |||
| } | |||
| } | |||
| public static PassiveSkillType FindpassiveSkillType(IPassiveSkill passiveSkill) | |||
| { | |||
| switch (passiveSkill) | |||
| { | |||
| default: | |||
| return PassiveSkillType.Null; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -28,7 +28,7 @@ namespace Gaming | |||
| if (player.PlayerState == PlayerStateType.IsRescuing || player.PlayerState == PlayerStateType.IsRescued | |||
| || player.PlayerState == PlayerStateType.IsFixing || player.PlayerState == PlayerStateType.IsMoving | |||
| || player.PlayerState == PlayerStateType.IsTreated || player.PlayerState == PlayerStateType.IsTreating | |||
| || player.PlayerState == PlayerStateType.IsRummagingInTheDrawer || player.PlayerState == PlayerStateType.IsLockingTheDoor | |||
| || player.PlayerState == PlayerStateType.IsRummagingInTheChest || player.PlayerState == PlayerStateType.IsLockingTheDoor | |||
| || player.PlayerState == PlayerStateType.IsClimbingThroughWindows) | |||
| { | |||
| player.PlayerState = PlayerStateType.Null; | |||
| @@ -150,7 +150,7 @@ namespace Gaming | |||
| finally | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | |||
| } | |||
| }, | |||
| timeInterval: GameData.checkInterval, | |||
| @@ -179,11 +179,17 @@ namespace Gaming | |||
| propManager.StartProducing(); | |||
| // 开始游戏 | |||
| if (!gameMap.Timer.StartGame(milliSeconds)) | |||
| return false; | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| if (!gameMap.Timer.StartGame(milliSeconds)) | |||
| return; | |||
| EndGame(); // 游戏结束时要做的事 | |||
| EndGame(); // 游戏结束时要做的事 | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return true; | |||
| } | |||
| @@ -333,7 +339,7 @@ namespace Gaming | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| if (player != null) | |||
| { | |||
| return skillManager.UseActiveSkill(this.GameMap, player, activeSkillType); | |||
| return skillManager.UseActiveSkill(player, activeSkillType); | |||
| } | |||
| else | |||
| return false; | |||
| @@ -348,7 +354,7 @@ namespace Gaming | |||
| { | |||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||
| { | |||
| skillManager.UseAllPassiveSkill(this.GameMap, player); | |||
| skillManager.UseAllPassiveSkill(player); | |||
| } | |||
| } | |||
| finally | |||
| @@ -439,10 +445,10 @@ namespace Gaming | |||
| teamList.Add(new Team()); | |||
| } | |||
| skillManager = new SkillManager(); | |||
| attackManager = new AttackManager(gameMap); | |||
| actionManager = new ActionManager(gameMap); | |||
| propManager = new PropManager(gameMap); | |||
| skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,29 +0,0 @@ | |||
| using System; | |||
| using Preparation.Utility; | |||
| using GameClass.GameObj; | |||
| using System.Reflection; | |||
| using GameClass.Skill; | |||
| namespace Gaming | |||
| { | |||
| public partial class Game | |||
| { | |||
| readonly SkillManager skillManager; | |||
| private class SkillManager | |||
| { | |||
| public bool UseActiveSkill(Map gamemap, Character character, ActiveSkillType activeSkillType) | |||
| { | |||
| return character.UseActiveSkill(gamemap, activeSkillType); | |||
| } | |||
| public void UsePassiveSkill(Map gamemap, Character character, PassiveSkillType passiveSkillType) | |||
| { | |||
| character.UsePassiveSkill(gamemap, passiveSkillType); | |||
| } | |||
| public void UseAllPassiveSkill(Map gamemap, Character character) | |||
| { | |||
| foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill) | |||
| character.UsePassiveSkill(gamemap, passiveSkill); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,238 @@ | |||
| using GameClass.GameObj; | |||
| using System.Threading; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| using Timothy.FrameRateTask; | |||
| namespace Gaming | |||
| { | |||
| public partial class Game | |||
| { | |||
| private partial class SkillManager | |||
| { | |||
| public interface IActiveSkill | |||
| { | |||
| public int SkillCD { get; } | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public object ActiveSkillLock { get; } | |||
| public bool SkillEffect(Character player); | |||
| } | |||
| public class BecomeVampire : IActiveSkill // 化身吸血鬼 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.Vampire += 0.5; | |||
| Debugger.Output(player, "becomes vampire!"); | |||
| }, | |||
| () => | |||
| { | |||
| double tempVam = player.Vampire - 0.5; | |||
| player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; | |||
| }); | |||
| } | |||
| } | |||
| private IActiveSkill becomeVampire = new BecomeVampire(); | |||
| public class BeginToCharge : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | |||
| public int DurationTime => GameData.commonSkillTime; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.Vampire += 0.5; | |||
| Debugger.Output(player, "becomes vampire!"); | |||
| }, | |||
| () => | |||
| { | |||
| double tempVam = player.Vampire - 0.5; | |||
| player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; | |||
| }); | |||
| } | |||
| } | |||
| private IActiveSkill beginToCharge = new BeginToCharge(); | |||
| public class BecomeInvisible : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 6; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.IsInvisible = true; | |||
| Debugger.Output(player, "become invisible!"); | |||
| }, | |||
| () => | |||
| { player.IsInvisible = false; }); | |||
| } | |||
| } | |||
| private IActiveSkill becomeInvisible = new BecomeInvisible(); | |||
| public class NuclearWeapon : IActiveSkill // 核武器 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 7; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.AtomBomb; | |||
| Debugger.Output(player, "uses atombomb!"); | |||
| }, | |||
| () => | |||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| } | |||
| private IActiveSkill nuclearWeapon = new NuclearWeapon(); | |||
| public class UseKnife : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD / 3 * 2; | |||
| public int DurationTime => GameData.commonSkillTime / 10; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.BulletOfPlayer = BulletType.FlyingKnife; | |||
| Debugger.Output(player, "uses flyingknife!"); | |||
| }, | |||
| () => | |||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||
| } | |||
| } | |||
| private IActiveSkill useKnife = new UseKnife(); | |||
| public class SuperFast : IActiveSkill // 3倍速 | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => GameData.commonSkillTime / 10 * 4; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool SkillEffect(Character player) | |||
| { | |||
| return ActiveSkillEffect(this, player, () => | |||
| { | |||
| player.AddMoveSpeed(this.DurationTime, 3.0); | |||
| Debugger.Output(player, "moves very fast!"); | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| } | |||
| private IActiveSkill superFast = new SuperFast(); | |||
| public IActiveSkill? FindIActiveSkill(ActiveSkillType activeSkillType) | |||
| { | |||
| switch (activeSkillType) | |||
| { | |||
| case ActiveSkillType.BecomeInvisible: | |||
| return this.becomeInvisible; | |||
| default: | |||
| return null; | |||
| } | |||
| } | |||
| public static ActiveSkillType FindActiveSkillType(IActiveSkill ActiveSkill) | |||
| { | |||
| switch (ActiveSkill) | |||
| { | |||
| case BecomeInvisible: | |||
| return ActiveSkillType.BecomeInvisible; | |||
| case UseKnife: | |||
| return ActiveSkillType.UseKnife; | |||
| case BeginToCharge: | |||
| return ActiveSkillType.BeginToCharge; | |||
| default: | |||
| return ActiveSkillType.Null; | |||
| } | |||
| } | |||
| public static bool ActiveSkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) | |||
| { | |||
| lock (activeSkill.ActiveSkillLock) | |||
| { | |||
| ActiveSkillType activeSkillType = FindActiveSkillType(activeSkill); | |||
| if (player.TimeUntilActiveSkillAvailable[activeSkillType] == 0) | |||
| { | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, activeSkill.SkillCD); | |||
| new Thread | |||
| (() => | |||
| { | |||
| startSkill(); | |||
| new FrameRateTaskExecutor<int>( | |||
| () => !player.IsResetting, | |||
| () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(activeSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| } | |||
| .Start(); | |||
| endSkill(); | |||
| Debugger.Output(player, "return to normal."); | |||
| new FrameRateTaskExecutor<int>( | |||
| () => player.TimeUntilActiveSkillAvailable[activeSkillType] > 0 && !player.IsResetting, | |||
| () => | |||
| { | |||
| player.AddTimeUntilActiveSkillAvailable(activeSkillType, -(int)GameData.frameDuration); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime) | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| } | |||
| .Start(); | |||
| player.SetTimeUntilActiveSkillAvailable(activeSkillType, 0); | |||
| Debugger.Output(player, "ActiveSkill is ready."); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| Debugger.Output(player, "CommonSkill is cooling down!"); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,131 @@ | |||
| using System; | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Timothy.FrameRateTask; | |||
| namespace Gaming // 被动技能开局时就释放,持续到游戏结束 | |||
| { | |||
| public partial class Game | |||
| { | |||
| private partial class SkillManager | |||
| { | |||
| public void RecoverAfterBattle(Character player) | |||
| { | |||
| const int recoverDegree = 5; // 每帧回复血量 | |||
| int nowHP = player.HP; | |||
| int lastHP = nowHP; | |||
| long waitTime = 0; | |||
| const long interval = 10000; // 每隔interval时间不受伤害,角色即开始回血 | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => true, | |||
| () => | |||
| { | |||
| lastHP = nowHP; // lastHP等于上一帧的HP | |||
| nowHP = player.HP; // nowHP更新为这一帧的HP | |||
| if (lastHP > nowHP) // 这一帧扣血了 | |||
| { | |||
| waitTime = 0; | |||
| } | |||
| else if (waitTime < interval) | |||
| { | |||
| waitTime += GameData.frameDuration; | |||
| } | |||
| if (waitTime >= interval) // 回复时,每帧(50ms)回复5,即1s回复100。 | |||
| player.TryAddHp(recoverDegree); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: GameData.gameDuration | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void SpeedUpWhenLeavingGrass(Character player) | |||
| { | |||
| PlaceType nowPlace = gameMap.GetPlaceType(player.Position); | |||
| PlaceType lastPlace = nowPlace; | |||
| bool speedup = false; | |||
| const int SpeedUpTime = 2000; // 加速时间:2s | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => true, | |||
| () => | |||
| { | |||
| lastPlace = nowPlace; | |||
| nowPlace = gameMap.GetPlaceType(player.Position); | |||
| if ((lastPlace == PlaceType.Grass) && nowPlace == PlaceType.Null) | |||
| { | |||
| if (!speedup) | |||
| { | |||
| new Thread(() => | |||
| { | |||
| speedup = true; | |||
| player.AddMoveSpeed(SpeedUpTime, 3.0); | |||
| speedup = false; | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| } | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => 0, | |||
| maxTotalDuration: GameData.gameDuration | |||
| ) | |||
| { | |||
| AllowTimeExceed = true, | |||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||
| TimeExceedAction = b => | |||
| { | |||
| if (b) | |||
| Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||
| #if DEBUG | |||
| else | |||
| { | |||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||
| } | |||
| #endif | |||
| } | |||
| }.Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void Vampire(Character player) | |||
| { | |||
| player.OriVampire = 0.5; | |||
| player.Vampire = player.OriVampire; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| using System; | |||
| using Preparation.Utility; | |||
| using GameClass.GameObj; | |||
| using System.Reflection; | |||
| using GameEngine; | |||
| namespace Gaming | |||
| { | |||
| public partial class Game | |||
| { | |||
| readonly SkillManager skillManager; | |||
| private partial class SkillManager | |||
| { | |||
| public bool UseActiveSkill(Character character, ActiveSkillType activeSkillType) | |||
| { | |||
| if (character.Occupation.ListOfIActiveSkill.Contains(activeSkillType)) | |||
| return FindIActiveSkill(activeSkillType).SkillEffect(character); | |||
| return false; | |||
| } | |||
| public void UsePassiveSkill(Character character, PassiveSkillType passiveSkillType) | |||
| { | |||
| if (character.Occupation.ListOfIPassiveSkill.Contains(passiveSkillType)) | |||
| switch (passiveSkillType) | |||
| { | |||
| default: | |||
| return; | |||
| } | |||
| return; | |||
| } | |||
| public void UseAllPassiveSkill(Character character) | |||
| { | |||
| foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill) | |||
| switch (passiveSkill) | |||
| { | |||
| default: | |||
| return; | |||
| } | |||
| } | |||
| private readonly Map gameMap; | |||
| private readonly ActionManager actionManager; | |||
| private readonly AttackManager attackManager; | |||
| private readonly PropManager propManager; | |||
| public SkillManager(Map gameMap, ActionManager action, AttackManager attack, PropManager prop) | |||
| { | |||
| this.gameMap = gameMap; | |||
| this.actionManager = action; | |||
| this.propManager = prop; | |||
| this.attackManager = attack; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -14,6 +14,7 @@ namespace Preparation.Interface | |||
| public List<PassiveSkillType> ListOfIPassiveSkill { get; } | |||
| public double Concealment { get; } | |||
| public int AlertnessRadius { get; } | |||
| public int TimeOfOpeningOrLocking { get; } | |||
| } | |||
| public interface IGhost : IOccupation | |||
| @@ -49,6 +50,9 @@ namespace Preparation.Interface | |||
| public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.3); | |||
| public int AlertnessRadius => alertnessRadius; | |||
| public int timeOfOpeningOrLocking = GameData.basicTimeOfOpeningOrLocking; | |||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||
| } | |||
| public class Athlete : IStudent | |||
| { | |||
| @@ -77,5 +81,8 @@ namespace Preparation.Interface | |||
| public const int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9); | |||
| public int AlertnessRadius => alertnessRadius; | |||
| public int timeOfOpeningOrLocking = GameData.basicTimeOfOpeningOrLocking; | |||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||
| } | |||
| } | |||
| @@ -20,7 +20,7 @@ namespace Preparation.Utility | |||
| IsStunned = 11, | |||
| IsTryingToAttack = 12,//指前摇 | |||
| IsLockingTheDoor = 13, | |||
| IsRummagingInTheDrawer = 14, | |||
| IsRummagingInTheChest = 14, | |||
| IsClimbingThroughWindows = 15, | |||
| } | |||
| public enum GameObjType | |||
| @@ -120,6 +120,7 @@ namespace Preparation.Utility | |||
| EmergencyExit = 10, | |||
| Window = 11, | |||
| Door = 12, | |||
| Chest = 13, | |||
| } | |||
| public enum BgmType | |||
| { | |||
| @@ -56,7 +56,6 @@ namespace Preparation.Utility | |||
| public const int basicApOfGhost = 1500000; // 攻击力 | |||
| public const int basicTreatSpeed = 100; | |||
| public const int basicFixSpeed = 100; | |||
| public const int basicRescueSpeed = 100; | |||
| public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间 | |||
| public const int BeginGamingAddiction = 10003; | |||
| public const int MidGamingAddiction = 30000; | |||
| @@ -73,11 +72,12 @@ namespace Preparation.Utility | |||
| public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围 | |||
| public const double basicAttackShortRange = 2700; // 基本近程攻击范围 | |||
| public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围 | |||
| public const int basicMoveSpeed = 3800; // 基本移动速度,单位:s-1 | |||
| public const int basicBulletMoveSpeed = 5400; // 基本子弹移动速度,单位:s-1 | |||
| public const int basicMoveSpeed = 1260; // 基本移动速度,单位:s-1 | |||
| public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1 | |||
| public const int characterMaxSpeed = 12000; // 最大速度 | |||
| public const double basicConcealment = 1.0; | |||
| public const int basicAlertnessRadius = 30700; | |||
| public const int basicTimeOfOpeningOrLocking = 3000; | |||
| public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分 | |||
| public const int commonSkillCD = 30000; // 普通技能标准冷却时间 | |||
| public const int commonSkillTime = 10000; // 普通技能标准持续时间 | |||
| @@ -106,7 +106,6 @@ namespace Preparation.Utility | |||
| public const long PropProduceTime = 10000; | |||
| public const int PropDuration = 10000; | |||
| #endregion | |||
| #region 物体相关 | |||
| public const int degreeOfFixedGenerator = 10300000; | |||
| #endregion | |||
| @@ -5,6 +5,7 @@ | |||
| - 该规则直接服务于Sever,并非选手版本 | |||
| - *斜体表示Logic底层尚未(完全)实现* | |||
| - []表示待决定 | |||
| - ~~表示暂不实现~~ | |||
| ## 游戏简介 | |||
| - 1位监管者对抗4位求生者的非对称竞技模式 | |||
| @@ -90,11 +91,11 @@ | |||
| IsStunned = 11, | |||
| IsTryingToAttack = 12,//指前摇 | |||
| IsLockingTheDoor = 13, | |||
| IsRummagingInTheDrawer = 14, | |||
| IsRummagingInTheChest = 14, | |||
| IsClimbingThroughWindows = 15, | |||
| } | |||
| ~~~ | |||
| - *Bgm(字典)* | |||
| - Bgm(字典) | |||
| - 得分 | |||
| - ~~回血率/原始回血率~~ | |||
| - 当前子弹类型 | |||
| @@ -108,15 +109,15 @@ | |||
| - 拥有的被动技能(列表) | |||
| - 拥有的主动技能(列表) | |||
| - 各个主动技能CD(字典) | |||
| - *警戒半径* | |||
| - *double 隐蔽度* | |||
| - *翻墙速度* | |||
| - *开锁门速度* | |||
| - 警戒半径 | |||
| - double 隐蔽度 | |||
| - *翻窗时间* | |||
| - 开锁门时间 | |||
| ### 学生:人物 | |||
| - 修理电机速度 | |||
| - 治疗速度 | |||
| - 救人速度 | |||
| - ~~救人速度~~ | |||
| - ~~自愈次数~~ | |||
| - 沉迷游戏程度 | |||
| - 最大沉迷游戏程度 | |||
| @@ -171,6 +172,7 @@ | |||
| ### 箱子:物体 | |||
| - *里面的道具* | |||
| - *是否开启* | |||
| ### 门:物体 | |||
| - *属于那个教学区* | |||
| @@ -225,7 +227,7 @@ | |||
| - *翻越窗户是一种交互行为,执行时,实质是限定方向的减速运动* | |||
| ### 箱子 | |||
| - *监管者和求生者都能与箱子交互。* | |||
| - *监管者和求生者都能与箱子交互,同一时刻就允许一人进行翻找* | |||
| - *开启箱子有不同概率获得不同道具。* | |||
| - *搜寻物品的基础持续时间为10秒。* | |||
| - *未搜寻完成的箱子在下一次需要重新开始搜寻。* | |||