feat: ✨ rebuild the fix,rescue,treat functions and make a pl…
tags/0.1.0
| @@ -32,16 +32,15 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| } | } | ||||
| public override double BulletBombRange => 0; | public override double BulletBombRange => 0; | ||||
| public override double BulletAttackRange => GameData.basicAttackShortRange * 13; | |||||
| public override int AP => GameData.basicApOfGhost / 3 * 7; | |||||
| public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2; | |||||
| public override bool IsToBomb => true; | |||||
| public override int Backswing => GameData.basicBackswing; | |||||
| public override int RecoveryFromHit => GameData.basicRecoveryFromHit; | |||||
| public override double BulletAttackRange => GameData.basicRemoteAttackRange * 13; | |||||
| public override int AP => GameData.basicApOfGhost / 5 * 4; | |||||
| public override int Speed => GameData.basicBulletMoveSpeed * 2; | |||||
| public override bool IsToBomb => false; | |||||
| public override int Backswing => GameData.basicBackswing / 5 * 3; | |||||
| public override int RecoveryFromHit => GameData.basicRecoveryFromHit / 4 * 3; | |||||
| public override bool CanAttack(GameObj target) | public override bool CanAttack(GameObj target) | ||||
| { | { | ||||
| // 圆形攻击范围 | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| return false; | |||||
| } | } | ||||
| public override BulletType TypeOfBullet => BulletType.FlyingKnife; | public override BulletType TypeOfBullet => BulletType.FlyingKnife; | ||||
| @@ -8,11 +8,11 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| public partial class Character | public partial class Character | ||||
| { | { | ||||
| private readonly BuffManeger buffManeger; | |||||
| private readonly BuffManager buffManager; | |||||
| /// <summary> | /// <summary> | ||||
| /// 角色携带的buff管理器 | /// 角色携带的buff管理器 | ||||
| /// </summary> | /// </summary> | ||||
| private class BuffManeger | |||||
| private class BuffManager | |||||
| { | { | ||||
| [StructLayout(LayoutKind.Explicit, Size = 8)] | [StructLayout(LayoutKind.Explicit, Size = 8)] | ||||
| private struct BuffValue // buff参数联合体类型,可能是int或double | private struct BuffValue // buff参数联合体类型,可能是int或double | ||||
| @@ -158,7 +158,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| public BuffManeger() | |||||
| public BuffManager() | |||||
| { | { | ||||
| var buffTypeArray = Enum.GetValues(typeof(BuffType)); | var buffTypeArray = Enum.GetValues(typeof(BuffType)); | ||||
| buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | ||||
| @@ -66,7 +66,7 @@ namespace GameClass.GameObj | |||||
| this.CanMove = true; | this.CanMove = true; | ||||
| this.score = 0; | this.score = 0; | ||||
| this.propInventory = null; | this.propInventory = null; | ||||
| this.buffManeger = new BuffManeger(); | |||||
| this.buffManager = new BuffManager(); | |||||
| switch (characterType) | switch (characterType) | ||||
| { | { | ||||
| case CharacterType.Assassin: | case CharacterType.Assassin: | ||||
| @@ -31,7 +31,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| public int OrgCD { get; protected set; } | public int OrgCD { get; protected set; } | ||||
| protected int fixSpeed = 1; | |||||
| protected int fixSpeed = GameData.basicFixSpeed; | |||||
| /// <summary> | /// <summary> | ||||
| /// 修理电机速度 | /// 修理电机速度 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -49,7 +49,35 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 原初修理电机速度 | /// 原初修理电机速度 | ||||
| /// </summary> | /// </summary> | ||||
| public int OrgFixSpeed { get; protected set; } | |||||
| public int OrgFixSpeed { get; protected set; } = GameData.basicFixSpeed; | |||||
| protected int treatSpeed = GameData.basicTreatSpeed; | |||||
| public int TreatSpeed | |||||
| { | |||||
| get => treatSpeed; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| treatSpeed = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| 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; | |||||
| protected int maxBulletNum; | protected int maxBulletNum; | ||||
| public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | ||||
| @@ -63,20 +91,49 @@ namespace GameClass.GameObj | |||||
| get => hp; | get => hp; | ||||
| set | set | ||||
| { | { | ||||
| lock (gameObjLock) | |||||
| hp = value <= MaxHp ? value : MaxHp; | |||||
| if (value > 0) | |||||
| { | |||||
| lock (gameObjLock) | |||||
| hp = value <= MaxHp ? value : MaxHp; | |||||
| } | |||||
| else | |||||
| lock (gameObjLock) | |||||
| hp = 0; | |||||
| } | } | ||||
| } | } | ||||
| private bool isEscaped = false; | |||||
| public bool IsEscaped | |||||
| public int MaxGamingAddiction { get; protected set; } | |||||
| private int gamingAddiction; | |||||
| public int GamingAddiction | |||||
| { | { | ||||
| get => isEscaped; | |||||
| get => gamingAddiction; | |||||
| set | set | ||||
| { | { | ||||
| lock (gameObjLock) | |||||
| if (!isEscaped && !IsGhost()) | |||||
| isEscaped = value; | |||||
| if (gamingAddiction > 0) | |||||
| lock (gameObjLock) | |||||
| gamingAddiction = value <= MaxGamingAddiction ? value : MaxGamingAddiction; | |||||
| else | |||||
| lock (gameObjLock) | |||||
| gamingAddiction = 0; | |||||
| } | |||||
| } | |||||
| private PlayerStateType playerState = PlayerStateType.Null; | |||||
| public PlayerStateType PlayerState | |||||
| { | |||||
| get | |||||
| { | |||||
| if (IsResetting) return PlayerStateType.IsResetting; | |||||
| if (IsMoving) return PlayerStateType.IsMoving; | |||||
| return playerState; | |||||
| } | |||||
| set | |||||
| { | |||||
| if (value != PlayerStateType.IsMoving && value != PlayerStateType.Null) | |||||
| lock (gameObjLock) | |||||
| CanMove = false; | |||||
| lock (gameObjLock) playerState = value; | |||||
| } | } | ||||
| } | } | ||||
| @@ -126,6 +183,32 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| private int selfHealingTimes = 1;//剩余的自愈次数 | |||||
| public int SelfHealingTimes | |||||
| { | |||||
| get => selfHealingTimes; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| selfHealingTimes = (value > 0) ? value : 0; | |||||
| } | |||||
| } | |||||
| private int degreeOfTreatment = 0; | |||||
| public int DegreeOfTreatment | |||||
| { | |||||
| get => degreeOfTreatment; | |||||
| set | |||||
| { | |||||
| if (value > 0) | |||||
| lock (gameObjLock) | |||||
| degreeOfTreatment = (value < MaxHp - HP) ? value : MaxHp - HP; | |||||
| else | |||||
| lock (gameObjLock) | |||||
| degreeOfTreatment = 0; | |||||
| } | |||||
| } | |||||
| public readonly BulletType OriBulletOfPlayer; | public readonly BulletType OriBulletOfPlayer; | ||||
| private BulletType bulletOfPlayer; | private BulletType bulletOfPlayer; | ||||
| public BulletType BulletOfPlayer | public BulletType BulletOfPlayer | ||||
| @@ -166,22 +249,6 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| /// <summary> | |||||
| /// 是否正在更换道具(包括捡起与抛出) | |||||
| /// </summary> | |||||
| private bool isModifyingProp = false; | |||||
| public bool IsModifyingProp | |||||
| { | |||||
| get => isModifyingProp; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| isModifyingProp = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// 是否在隐身 | /// 是否在隐身 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -423,19 +490,19 @@ namespace GameClass.GameObj | |||||
| #endregion | #endregion | ||||
| #region 角色拥有的buff相关属性、方法 | #region 角色拥有的buff相关属性、方法 | ||||
| public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal => | |||||
| public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManager.AddMoveSpeed(add, buffTime, newVal => | |||||
| { MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; }, | { MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; }, | ||||
| OrgMoveSpeed); | OrgMoveSpeed); | ||||
| public bool HasFasterSpeed => buffManeger.HasFasterSpeed; | |||||
| public bool HasFasterSpeed => buffManager.HasFasterSpeed; | |||||
| public void AddShield(int shieldTime) => buffManeger.AddShield(shieldTime); | |||||
| public bool HasShield => buffManeger.HasShield; | |||||
| public void AddShield(int shieldTime) => buffManager.AddShield(shieldTime); | |||||
| public bool HasShield => buffManager.HasShield; | |||||
| public void AddLIFE(int LIFETime) => buffManeger.AddLIFE(LIFETime); | |||||
| public bool HasLIFE => buffManeger.HasLIFE; | |||||
| public void AddLIFE(int LIFETime) => buffManager.AddLIFE(LIFETime); | |||||
| public bool HasLIFE => buffManager.HasLIFE; | |||||
| public void AddSpear(int spearTime) => buffManeger.AddSpear(spearTime); | |||||
| public bool HasSpear => buffManeger.HasSpear; | |||||
| public void AddSpear(int spearTime) => buffManager.AddSpear(spearTime); | |||||
| public bool HasSpear => buffManager.HasSpear; | |||||
| private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | ||||
| public Dictionary<BuffType, bool> Buff | public Dictionary<BuffType, bool> Buff | ||||
| @@ -469,7 +536,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| private void TryActivatingLIFE() | private void TryActivatingLIFE() | ||||
| { | { | ||||
| if (buffManeger.TryActivatingLIFE()) | |||||
| if (buffManager.TryActivatingLIFE()) | |||||
| { | { | ||||
| hp = MaxHp; | hp = MaxHp; | ||||
| } | } | ||||
| @@ -488,7 +555,7 @@ namespace GameClass.GameObj | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| bulletNum = maxBulletNum; | bulletNum = maxBulletNum; | ||||
| buffManeger.ClearAll(); | |||||
| buffManager.ClearAll(); | |||||
| IsInvisible = false; | IsInvisible = false; | ||||
| this.Vampire = this.OriVampire; | this.Vampire = this.OriVampire; | ||||
| } | } | ||||
| @@ -497,7 +564,8 @@ namespace GameClass.GameObj | |||||
| public void Escape() | public void Escape() | ||||
| { | { | ||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| IsResetting = IsEscaped = true; | |||||
| IsResetting = true; | |||||
| PlayerState = PlayerStateType.IsEscaped; | |||||
| } | } | ||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| public override ShapeType Shape => ShapeType.Circle; | public override ShapeType Shape => ShapeType.Circle; | ||||
| @@ -9,13 +9,6 @@ namespace GameClass.Skill | |||||
| { | { | ||||
| public class BecomeVampire : IActiveSkill // 化身吸血鬼 | public class BecomeVampire : IActiveSkill // 化身吸血鬼 | ||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| private const int maxHp = (int)(GameData.basicHp / 6 * 9.5); | |||||
| public int MaxHp => maxHp; | |||||
| // 以上参数以后再改 | |||||
| public int SkillCD => GameData.commonSkillCD / 3 * 4; | public int SkillCD => GameData.commonSkillCD / 3 * 4; | ||||
| public int DurationTime => GameData.commonSkillTime; | public int DurationTime => GameData.commonSkillTime; | ||||
| @@ -56,15 +49,6 @@ namespace GameClass.Skill | |||||
| } | } | ||||
| public class NuclearWeapon : IActiveSkill // 核武器 | public class NuclearWeapon : IActiveSkill // 核武器 | ||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| private const int maxHp = GameData.basicHp; | |||||
| public int MaxHp => maxHp; | |||||
| private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; | |||||
| public int MaxBulletNum => maxBulletNum; | |||||
| // 以上参数以后再改 | |||||
| public int SkillCD => GameData.commonSkillCD / 3 * 7; | public int SkillCD => GameData.commonSkillCD / 3 * 7; | ||||
| public int DurationTime => GameData.commonSkillTime / 10; | public int DurationTime => GameData.commonSkillTime / 10; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| @@ -80,17 +64,25 @@ namespace GameClass.Skill | |||||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | { 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(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 class SuperFast : IActiveSkill // 3倍速 | ||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| private const int maxHp = GameData.basicHp / 6 * 4; | |||||
| public int MaxHp => maxHp; | |||||
| private const int maxBulletNum = GameData.basicBulletNum * 4 / 3; | |||||
| public int MaxBulletNum => maxBulletNum; | |||||
| // 以上参数以后再改 | |||||
| public int SkillCD => GameData.commonSkillCD; | public int SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => GameData.commonSkillTime / 10 * 4; | public int DurationTime => GameData.commonSkillTime / 10 * 4; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| @@ -108,15 +100,6 @@ namespace GameClass.Skill | |||||
| } | } | ||||
| public class NoCommonSkill : IActiveSkill // 这种情况不该发生,定义着以防意外 | public class NoCommonSkill : IActiveSkill // 这种情况不该发生,定义着以防意外 | ||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| private const int maxHp = GameData.basicHp; | |||||
| public int MaxHp => maxHp; | |||||
| private const int maxBulletNum = GameData.basicBulletNum; | |||||
| public int MaxBulletNum => maxBulletNum; | |||||
| // 以上参数以后再改 | |||||
| public int SkillCD => GameData.commonSkillCD; | public int SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => GameData.commonSkillTime; | public int DurationTime => GameData.commonSkillTime; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| @@ -1,8 +1,5 @@ | |||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using System.Threading; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| namespace GameClass.Skill | namespace GameClass.Skill | ||||
| @@ -33,7 +30,7 @@ namespace GameClass.Skill | |||||
| public BulletType InitBullet => BulletType.CommonAttackOfGhost; | public BulletType InitBullet => BulletType.CommonAttackOfGhost; | ||||
| public List<IActiveSkill> ListOfIActiveSkill => new(new IActiveSkill[] { new BecomeInvisible(), }); | |||||
| public List<IActiveSkill> ListOfIActiveSkill => new(new IActiveSkill[] { new BecomeInvisible(), new UseKnife() }); | |||||
| public List<IPassiveSkill> ListOfIPassiveSkill => new(new IPassiveSkill[] { }); | public List<IPassiveSkill> ListOfIPassiveSkill => new(new IPassiveSkill[] { }); | ||||
| } | } | ||||
| @@ -1,8 +1,10 @@ | |||||
| using System; | using System; | ||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
| using System.Threading; | |||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using GameEngine; | using GameEngine; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Timothy.FrameRateTask; | |||||
| namespace Gaming | namespace Gaming | ||||
| { | { | ||||
| @@ -18,9 +20,9 @@ namespace Gaming | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | ||||
| } | } | ||||
| public bool TryToFix(Character player)// 自动检查有无发电机可修 | |||||
| public bool Fix(Character player)// 自动检查有无发电机可修 | |||||
| { | { | ||||
| if (player.IsResetting || player.IsGhost()) | |||||
| if (player.PlayerState != PlayerStateType.Null || player.IsGhost()) | |||||
| return false; | return false; | ||||
| Generator? generatorForFix = null; | Generator? generatorForFix = null; | ||||
| @@ -42,54 +44,72 @@ namespace Gaming | |||||
| gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | ||||
| } | } | ||||
| if (generatorForFix == null || generatorForFix.DegreeOfFRepair == GameData.degreeOfFixedGenerator) | |||||
| return false; | |||||
| player.PlayerState = PlayerStateType.IsFixing; | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => player.PlayerState == PlayerStateType.IsFixing && generatorForFix.DegreeOfFRepair < GameData.degreeOfFixedGenerator && GameData.ApproachToInteract(player.Position, generatorForFix.Position), | |||||
| loopToDo: () => | |||||
| { | |||||
| return !generatorForFix.Repair(player.FixSpeed * GameData.frameDuration); | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0 | |||||
| ) | |||||
| .Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| if (generatorForFix != null) | |||||
| if (generatorForFix.DegreeOfFRepair == GameData.degreeOfFixedGenerator) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); | gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); | ||||
| try | try | ||||
| { | { | ||||
| if (generatorForFix.Repair(player.FixSpeed)) | |||||
| Doorway exit = (Doorway)gameMap.GameObjDict[GameObjType.Doorway][1]; | |||||
| if (!exit.PowerSupply) | |||||
| { | { | ||||
| Doorway exit = (Doorway)gameMap.GameObjDict[GameObjType.Doorway][1]; | |||||
| if (!exit.PowerSupply) | |||||
| int numOfFixedGenerator = 0; | |||||
| foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | |||||
| if (generator.DegreeOfFRepair == GameData.degreeOfFixedGenerator) | |||||
| ++numOfFixedGenerator; | |||||
| if (numOfFixedGenerator >= GameData.numOfGeneratorRequiredForRepair) | |||||
| { | { | ||||
| int numOfFixedGenerator = 0; | |||||
| foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | |||||
| if (generator.DegreeOfFRepair == GameData.degreeOfFixedGenerator) | |||||
| ++numOfFixedGenerator; | |||||
| if (numOfFixedGenerator >= GameData.numOfGeneratorRequiredForRepair) | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); | |||||
| try | |||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) | |||||
| doorway.PowerSupply = true; | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); | |||||
| } | |||||
| foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) | |||||
| doorway.PowerSupply = true; | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| else | |||||
| return false; | |||||
| return false; | |||||
| } | } | ||||
| public bool TryToEscape(Character player) | |||||
| public bool Escape(Character player) | |||||
| { | { | ||||
| if (player.IsResetting || player.IsGhost()) | |||||
| if (!(player.PlayerState == PlayerStateType.Null || player.PlayerState == PlayerStateType.IsMoving) || player.IsGhost()) | |||||
| return false; | return false; | ||||
| Doorway? doorwayForEscape = null; | Doorway? doorwayForEscape = null; | ||||
| gameMap.GameObjLockDict[GameObjType.Doorway].EnterReadLock(); | gameMap.GameObjLockDict[GameObjType.Doorway].EnterReadLock(); | ||||
| try | try | ||||
| { | { | ||||
| @@ -116,6 +136,103 @@ namespace Gaming | |||||
| else | else | ||||
| return false; | return false; | ||||
| } | } | ||||
| public bool Treat(Character player, Character playerTreated) | |||||
| { | |||||
| if (playerTreated.PlayerState == PlayerStateType.Null || player.PlayerState == PlayerStateType.Null || playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position)) | |||||
| return false; | |||||
| if (playerTreated.HP + playerTreated.DegreeOfTreatment >= playerTreated.MaxHp) | |||||
| { | |||||
| playerTreated.HP = playerTreated.MaxHp; | |||||
| playerTreated.DegreeOfTreatment = 0; | |||||
| return true; | |||||
| } | |||||
| if (playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree) | |||||
| { | |||||
| playerTreated.HP += GameData.basicTreatmentDegree; | |||||
| playerTreated.DegreeOfTreatment = 0; | |||||
| return true; | |||||
| } | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => playerTreated.PlayerState == PlayerStateType.IsTreated && player.PlayerState == PlayerStateType.IsTreating && playerTreated.HP + playerTreated.DegreeOfTreatment < playerTreated.MaxHp && playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree && GameData.ApproachToInteract(playerTreated.Position, player.Position), | |||||
| loopToDo: () => | |||||
| { | |||||
| playerTreated.DegreeOfTreatment += GameData.frameDuration * player.TreatSpeed; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0 | |||||
| ) | |||||
| .Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| if (playerTreated.PlayerState == PlayerStateType.IsTreated) playerTreated.PlayerState = PlayerStateType.Null; | |||||
| if (player.PlayerState == PlayerStateType.IsTreating) player.PlayerState = PlayerStateType.Null; | |||||
| if (playerTreated.HP + playerTreated.DegreeOfTreatment >= playerTreated.MaxHp) | |||||
| { | |||||
| playerTreated.HP = playerTreated.MaxHp; | |||||
| playerTreated.DegreeOfTreatment = 0; | |||||
| return true; | |||||
| } | |||||
| if (playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree) | |||||
| { | |||||
| playerTreated.HP += GameData.basicTreatmentDegree; | |||||
| playerTreated.DegreeOfTreatment = 0; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public bool Rescue(Character player, Character playerRescued) | |||||
| { | |||||
| if (player.PlayerState != PlayerStateType.Null || playerRescued.PlayerState != PlayerStateType.IsAddicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) | |||||
| return false; | |||||
| player.PlayerState = PlayerStateType.IsRescuing; | |||||
| playerRescued.PlayerState = PlayerStateType.IsRescued; | |||||
| int rescuedDegree = 0; | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => playerRescued.PlayerState == PlayerStateType.IsRescued && player.PlayerState == PlayerStateType.IsRescuing && GameData.ApproachToInteract(playerRescued.Position, player.Position), | |||||
| loopToDo: () => | |||||
| { | |||||
| rescuedDegree += GameData.frameDuration; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0, | |||||
| maxTotalDuration: 1000 | |||||
| ) | |||||
| .Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| if (rescuedDegree == 1000) | |||||
| { | |||||
| if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; | |||||
| if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.Null; | |||||
| return true; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; | |||||
| if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.IsAddicted; | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /* | /* | ||||
| private void ActivateMine(Character player, Mine mine) | private void ActivateMine(Character player, Mine mine) | ||||
| { | { | ||||
| @@ -5,6 +5,7 @@ using GameClass.GameObj; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using GameEngine; | using GameEngine; | ||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Timothy.FrameRateTask; | |||||
| namespace Gaming | namespace Gaming | ||||
| { | { | ||||
| @@ -35,75 +36,114 @@ namespace Gaming | |||||
| } | } | ||||
| ); | ); | ||||
| } | } | ||||
| private bool CanBeBombed(Bullet bullet, GameObjType gameObjType) | |||||
| public void BeAddictedToGame(Character player) | |||||
| { | { | ||||
| if (gameObjType == GameObjType.Character) return true; | |||||
| return false; | |||||
| new Thread | |||||
| (() => | |||||
| { | |||||
| if (player.GamingAddiction > GameData.BeginGamingAddiction && player.GamingAddiction < GameData.MidGamingAddiction) | |||||
| player.GamingAddiction = GameData.MidGamingAddiction; | |||||
| player.PlayerState = PlayerStateType.IsAddicted; | |||||
| new FrameRateTaskExecutor<int>( | |||||
| () => player.PlayerState == PlayerStateType.IsAddicted && player.GamingAddiction < player.MaxGamingAddiction, | |||||
| () => | |||||
| { | |||||
| player.GamingAddiction += GameData.frameDuration; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| () => | |||||
| { | |||||
| if (player.GamingAddiction == player.MaxGamingAddiction) | |||||
| { | |||||
| player.PlayerState = PlayerStateType.Null; | |||||
| Die(player); | |||||
| } | |||||
| else player.CanMove = true; | |||||
| return 0; | |||||
| } | |||||
| ) | |||||
| .Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| } | } | ||||
| private void BombObj(Bullet bullet, GameObj objBeingShot) | |||||
| public void Die(Character player) | |||||
| { | { | ||||
| switch (objBeingShot.Type) | |||||
| player.CanMove = false; | |||||
| player.IsResetting = true; | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| // try | |||||
| //{ | |||||
| // gameMap.GameObjDict[GameObjType.Character].Remove(playerBeingShot); | |||||
| // } | |||||
| // finally | |||||
| //{ | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| // } | |||||
| Prop? dropProp = null; | |||||
| if (player.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地 | |||||
| { | { | ||||
| case GameObjType.Character: | |||||
| Character playerBeingShot = (Character)objBeingShot; | |||||
| if (playerBeingShot.BeAttacked(bullet)) | |||||
| dropProp = player.PropInventory; | |||||
| dropProp.SetNewPos(GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell)); | |||||
| } | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| if (dropProp != null) | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add(dropProp); | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | |||||
| player.Reset(); | |||||
| // ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 | |||||
| /* new Thread | |||||
| (() => | |||||
| { | { | ||||
| playerBeingShot.CanMove = false; | |||||
| playerBeingShot.IsResetting = true; | |||||
| Thread.Sleep(GameData.reviveTime); | |||||
| playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | ||||
| // try | // try | ||||
| //{ | //{ | ||||
| // gameMap.GameObjDict[GameObjType.Character].Remove(playerBeingShot); | |||||
| // } | |||||
| // finally | |||||
| //{ | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| // gameMap.GameObjDict[GameObjType.Character].Add(playerBeingShot); | |||||
| // } | // } | ||||
| // finally { gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } | |||||
| Prop? dropProp = null; | |||||
| if (playerBeingShot.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地 | |||||
| if (gameMap.Timer.IsGaming) | |||||
| { | { | ||||
| dropProp = playerBeingShot.PropInventory; | |||||
| dropProp.SetNewPos(GameData.GetCellCenterPos(playerBeingShot.Position.x / GameData.numOfPosGridPerCell, playerBeingShot.Position.y / GameData.numOfPosGridPerCell)); | |||||
| playerBeingShot.CanMove = true; | |||||
| } | } | ||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| if (dropProp != null) | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add(dropProp); | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | |||||
| playerBeingShot.Reset(); | |||||
| ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 | |||||
| /* new Thread | |||||
| (() => | |||||
| { | |||||
| Thread.Sleep(GameData.reviveTime); | |||||
| playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| // try | |||||
| //{ | |||||
| // gameMap.GameObjDict[GameObjType.Character].Add(playerBeingShot); | |||||
| // } | |||||
| // finally { gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } | |||||
| playerBeingShot.IsResetting = false; | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| */ | |||||
| } | |||||
| if (gameMap.Timer.IsGaming) | |||||
| { | |||||
| playerBeingShot.CanMove = true; | |||||
| } | |||||
| playerBeingShot.IsResetting = false; | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| */ | |||||
| private bool CanBeBombed(Bullet bullet, GameObjType gameObjType) | |||||
| { | |||||
| if (gameObjType == GameObjType.Character) return true; | |||||
| return false; | |||||
| } | |||||
| private void BombObj(Bullet bullet, GameObj objBeingShot) | |||||
| { | |||||
| switch (objBeingShot.Type) | |||||
| { | |||||
| case GameObjType.Character: | |||||
| Character playerBeingShot = (Character)objBeingShot; | |||||
| if (playerBeingShot.BeAttacked(bullet)) | |||||
| { | |||||
| BeAddictedToGame(playerBeingShot); | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -57,7 +57,7 @@ namespace Gaming | |||||
| newPlayer.TeamID = playerInitInfo.teamID; | newPlayer.TeamID = playerInitInfo.teamID; | ||||
| newPlayer.PlayerID = playerInitInfo.playerID; | newPlayer.PlayerID = playerInitInfo.playerID; | ||||
| /*new Thread //人物装弹 | |||||
| new Thread //人物装弹 | |||||
| ( | ( | ||||
| () => | () => | ||||
| { | { | ||||
| @@ -84,17 +84,17 @@ namespace Gaming | |||||
| finallyReturn: () => 0 | finallyReturn: () => 0 | ||||
| ) | ) | ||||
| { | { | ||||
| AllowTimeExceed = true | |||||
| AllowTimeExceed = true/*, | |||||
| MaxTolerantTimeExceedCount = 5, | MaxTolerantTimeExceedCount = 5, | ||||
| TimeExceedAction = exceedTooMuch => | TimeExceedAction = exceedTooMuch => | ||||
| { | { | ||||
| if (exceedTooMuch) Console.WriteLine("The computer runs too slow that it cannot check the color below the player in time!"); | if (exceedTooMuch) Console.WriteLine("The computer runs too slow that it cannot check the color below the player in time!"); | ||||
| } | |||||
| }*/ | |||||
| } | } | ||||
| .Start(); | .Start(); | ||||
| } | } | ||||
| ) | ) | ||||
| { IsBackground = true }.Start();*/ | |||||
| { IsBackground = true }.Start(); | |||||
| return newPlayer.ID; | return newPlayer.ID; | ||||
| } | } | ||||
| @@ -194,6 +194,52 @@ namespace Gaming | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| public bool Treat(long playerID, long playerTreatedID) | |||||
| { | |||||
| if (!gameMap.Timer.IsGaming) | |||||
| return false; | |||||
| Character? player = gameMap.FindPlayer(playerID); | |||||
| Character? playerTreated = gameMap.FindPlayer(playerTreatedID); | |||||
| if (player != null && playerTreated != null) | |||||
| { | |||||
| return actionManager.Treat(player, playerTreated); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public bool Rescue(long playerID, long playerRescuedID) | |||||
| { | |||||
| if (!gameMap.Timer.IsGaming) | |||||
| return false; | |||||
| Character? player = gameMap.FindPlayer(playerID); | |||||
| Character? playerRescued = gameMap.FindPlayer(playerRescuedID); | |||||
| if (player != null && playerRescued != null) | |||||
| { | |||||
| return actionManager.Treat(player, playerRescued); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public bool Fix(long playerID) | |||||
| { | |||||
| if (!gameMap.Timer.IsGaming) | |||||
| return false; | |||||
| Character? player = gameMap.FindPlayer(playerID); | |||||
| if (player != null) | |||||
| { | |||||
| return actionManager.Fix(player); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public bool Escape(long playerID) | |||||
| { | |||||
| if (!gameMap.Timer.IsGaming) | |||||
| return false; | |||||
| Character? player = gameMap.FindPlayer(playerID); | |||||
| if (player != null) | |||||
| { | |||||
| return actionManager.Escape(player); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void Attack(long playerID, double angle) | public void Attack(long playerID, double angle) | ||||
| { | { | ||||
| if (!gameMap.Timer.IsGaming) | if (!gameMap.Timer.IsGaming) | ||||
| @@ -5,6 +5,20 @@ namespace Preparation.Utility | |||||
| /// 存放所有用到的枚举类型 | /// 存放所有用到的枚举类型 | ||||
| /// </summary> | /// </summary> | ||||
| // public const int numOfObjNotMap = 5;在GameData中 | // public const int numOfObjNotMap = 5;在GameData中 | ||||
| public enum PlayerStateType | |||||
| { | |||||
| Null = 0, | |||||
| IsAddicted = 1, | |||||
| IsEscaped = 2, | |||||
| IsSwinging = 3, | |||||
| IsResetting = 4, | |||||
| IsMoving = 5, | |||||
| IsTreating = 6, | |||||
| IsRescuing = 7, | |||||
| IsFixing = 8, | |||||
| IsTreated = 9, | |||||
| IsRescued = 10, | |||||
| } | |||||
| public enum GameObjType | public enum GameObjType | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| @@ -72,7 +86,7 @@ namespace Preparation.Utility | |||||
| BecomeVampire = 2, | BecomeVampire = 2, | ||||
| NuclearWeapon = 3, | NuclearWeapon = 3, | ||||
| SuperFast = 4, | SuperFast = 4, | ||||
| ASkill4 = 5, | |||||
| UseKnife = 5, | |||||
| ASkill5 = 6 | ASkill5 = 6 | ||||
| } | } | ||||
| public enum PassiveSkillType | public enum PassiveSkillType | ||||
| @@ -6,11 +6,12 @@ namespace Preparation.Utility | |||||
| #region 基本常数与常方法 | #region 基本常数与常方法 | ||||
| public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | ||||
| public const int numOfStepPerSecond = 20; // 每秒行走的步数 | public const int numOfStepPerSecond = 20; // 每秒行走的步数 | ||||
| public const int frameDuration = 50; // 每帧时长 | |||||
| public const int lengthOfMap = 50000; // 地图长度 | public const int lengthOfMap = 50000; // 地图长度 | ||||
| public const int rows = 50; // 行数 | public const int rows = 50; // 行数 | ||||
| public const int cols = 50; // 列数 | public const int cols = 50; // 列数 | ||||
| public const long gameDuration = 600000; // 游戏时长600000ms = 10min | public const long gameDuration = 600000; // 游戏时长600000ms = 10min | ||||
| public const long frameDuration = 50; // 每帧时长 | |||||
| public const int MinSpeed = 1; // 最小速度 | public const int MinSpeed = 1; // 最小速度 | ||||
| public const int MaxSpeed = int.MaxValue; // 最大速度 | public const int MaxSpeed = int.MaxValue; // 最大速度 | ||||
| @@ -45,8 +46,16 @@ namespace Preparation.Utility | |||||
| #endregion | #endregion | ||||
| #region 角色相关 | #region 角色相关 | ||||
| public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 | public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 | ||||
| public const int basicApOfGhost = 500; // 初始攻击力 | |||||
| public const int basicHp = 1003; // 初始血量 | |||||
| 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; | |||||
| public const int basicTreatmentDegree = 1500000; | |||||
| public const int basicRescueDegree = 100000; | |||||
| public const int basicHp = 3000000; // 初始血量 | |||||
| public const int basicCD = 3000; // 初始子弹冷却 | public const int basicCD = 3000; // 初始子弹冷却 | ||||
| public const int basicBackswing = 500;//基本后摇时间 | public const int basicBackswing = 500;//基本后摇时间 | ||||
| public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 | public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 | ||||
| @@ -78,7 +87,7 @@ namespace Preparation.Utility | |||||
| public const long PropProduceTime = 10000; | public const long PropProduceTime = 10000; | ||||
| public const int PropDuration = 10000; | public const int PropDuration = 10000; | ||||
| public const int degreeOfFixedGenerator = 2000; | |||||
| public const int degreeOfFixedGenerator = 10300000; | |||||
| #endregion | #endregion | ||||
| #region 游戏帧相关 | #region 游戏帧相关 | ||||
| public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | ||||