feat: ✨ add new CharacterType Klee and fix some bugs
tags/0.1.0
| @@ -43,7 +43,7 @@ enum PropType // 地图中的可拾取道具类型 | |||||
| { | { | ||||
| NULL_PROP_TYPE = 0; | NULL_PROP_TYPE = 0; | ||||
| ADD_SPEED = 1; | ADD_SPEED = 1; | ||||
| ADD_LIFE_OR_AP = 2; | |||||
| ADD_LIFE_OR_AP = 2;//ADD_LIFE_OR_Clairaudience | |||||
| ADD_HP_OR_AP = 3; | ADD_HP_OR_AP = 3; | ||||
| SHIELD_OR_SPEAR = 4; | SHIELD_OR_SPEAR = 4; | ||||
| KEY3 = 5; | KEY3 = 5; | ||||
| @@ -54,9 +54,9 @@ enum PropType // 地图中的可拾取道具类型 | |||||
| enum StudentBuffType // 人类可用的增益效果类型 | enum StudentBuffType // 人类可用的增益效果类型 | ||||
| { | { | ||||
| NULL_SBUFF_TYPE = 0; | NULL_SBUFF_TYPE = 0; | ||||
| SBUFFTYPE1 = 1; | |||||
| SBUFFTYPE2 = 2; | |||||
| SBUFFTYPE3 = 3; | |||||
| SBUFFTYPE1 = 1;//AddSpeed | |||||
| SBUFFTYPE2 = 2;//AddLIFE | |||||
| SBUFFTYPE3 = 3;//Shield | |||||
| SBUFFTYPE4 = 4; | SBUFFTYPE4 = 4; | ||||
| } | } | ||||
| @@ -86,10 +86,11 @@ enum PlayerState | |||||
| enum TrickerBuffType // 屠夫可用的增益效果类型 | enum TrickerBuffType // 屠夫可用的增益效果类型 | ||||
| { | { | ||||
| NULL_TBUFF_TYPE = 0; | NULL_TBUFF_TYPE = 0; | ||||
| TBUFFTYPE1 = 1; | |||||
| TBUFFTYPE2 = 2; | |||||
| TBUFFTYPE3 = 3; | |||||
| TBUFFTYPE4 = 4; | |||||
| TBUFFTYPE1 = 1;//AddSpeed | |||||
| TBUFFTYPE2 = 2;//Spear | |||||
| TBUFFTYPE3 = 3;//AddAp | |||||
| TBUFFTYPE4 = 4;//Clairaudience | |||||
| INVISIBLE = 5; | |||||
| } | } | ||||
| // 特别说明:由于Student阵营和Tricker阵营有显著的隔离,且暂定职业、主动技能和被动效果相互绑定,故不按照THUAI5的方式区分ActiveSkillType和CharacterType,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。 | // 特别说明:由于Student阵营和Tricker阵营有显著的隔离,且暂定职业、主动技能和被动效果相互绑定,故不按照THUAI5的方式区分ActiveSkillType和CharacterType,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。 | ||||
| @@ -114,7 +115,7 @@ enum TrickerType | |||||
| { | { | ||||
| NULL_TRICKER_TYPE = 0; | NULL_TRICKER_TYPE = 0; | ||||
| ASSASSIN = 1; | ASSASSIN = 1; | ||||
| TRICKERTYPE2 = 2; | |||||
| TRICKERTYPE2 = 2;//KLEE | |||||
| TRICKERTYPE3 = 3; | TRICKERTYPE3 = 3; | ||||
| TRICKERTYPE4 = 4; | TRICKERTYPE4 = 4; | ||||
| } | } | ||||
| @@ -23,9 +23,9 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| public override int Speed => GameData.basicBulletMoveSpeed; | public override int Speed => GameData.basicBulletMoveSpeed; | ||||
| public override bool IsToBomb => false; | |||||
| public override bool IsRemoteAttack => false; | |||||
| public override int CastTime => GameData.basicCastTime; | |||||
| public override int CastTime => (int)BulletAttackRange / Speed; | |||||
| public override int Backswing => GameData.basicBackswing; | public override int Backswing => GameData.basicBackswing; | ||||
| public override int RecoveryFromHit => GameData.basicRecoveryFromHit; | public override int RecoveryFromHit => GameData.basicRecoveryFromHit; | ||||
| public const int cd = GameData.basicBackswing; | public const int cd = GameData.basicBackswing; | ||||
| @@ -68,11 +68,11 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| public override int Speed => GameData.basicBulletMoveSpeed * 2; | public override int Speed => GameData.basicBulletMoveSpeed * 2; | ||||
| public override bool IsToBomb => false; | |||||
| public override bool IsRemoteAttack => true; | |||||
| public override int CastTime => GameData.basicCastTime; | public override int CastTime => GameData.basicCastTime; | ||||
| public override int Backswing => GameData.basicBackswing * 2 / 5; | |||||
| public override int RecoveryFromHit => GameData.basicBackswing * 3 / 4; | |||||
| public override int Backswing => 0; | |||||
| public override int RecoveryFromHit => 0; | |||||
| public const int cd = GameData.basicBackswing * 2 / 5 + 100; | public const int cd = GameData.basicBackswing * 2 / 5 + 100; | ||||
| public override int CD => cd; | public override int CD => cd; | ||||
| @@ -94,4 +94,95 @@ namespace GameClass.GameObj | |||||
| public override BulletType TypeOfBullet => BulletType.FlyingKnife; | public override BulletType TypeOfBullet => BulletType.FlyingKnife; | ||||
| } | } | ||||
| internal sealed class BombBomb : Bullet | |||||
| { | |||||
| public BombBomb(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||||
| base(player, radius, placeType, pos) | |||||
| { | |||||
| } | |||||
| public override double BulletBombRange => GameData.basicBulletBombRange; | |||||
| public override double BulletAttackRange => GameData.basicAttackShortRange; | |||||
| public int ap = (int)(GameData.basicApOfGhost * 6.0 / 5); | |||||
| public override int AP | |||||
| { | |||||
| get => ap; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| ap = value; | |||||
| } | |||||
| } | |||||
| public override int Speed => (int)(GameData.basicBulletMoveSpeed * 0.8); | |||||
| public override bool IsRemoteAttack => false; | |||||
| public override int CastTime => (int)BulletAttackRange / Speed; | |||||
| public override int Backswing => GameData.basicBackswing; | |||||
| public override int RecoveryFromHit => GameData.basicRecoveryFromHit; | |||||
| public const int cd = GameData.basicCD; | |||||
| public override int CD => cd; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| } | |||||
| public override bool CanBeBombed(GameObjType gameObjType) | |||||
| { | |||||
| switch (gameObjType) | |||||
| { | |||||
| case GameObjType.Character: | |||||
| case GameObjType.Generator: | |||||
| return true; | |||||
| default: | |||||
| return false; | |||||
| } | |||||
| } | |||||
| public override BulletType TypeOfBullet => BulletType.BombBomb; | |||||
| } | |||||
| internal sealed class JumpyDumpty : Bullet | |||||
| { | |||||
| public JumpyDumpty(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||||
| base(player, radius, placeType, pos) | |||||
| { | |||||
| } | |||||
| public override double BulletBombRange => GameData.basicBulletBombRange / 2; | |||||
| public override double BulletAttackRange => GameData.basicAttackShortRange * 2; | |||||
| public int ap = (int)(GameData.basicApOfGhost * 0.6); | |||||
| public override int AP | |||||
| { | |||||
| get => ap; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| ap = value; | |||||
| } | |||||
| } | |||||
| public override int Speed => (int)(GameData.basicBulletMoveSpeed * 1.2); | |||||
| public override bool IsRemoteAttack => false; | |||||
| public override int CastTime => 0; | |||||
| public override int Backswing => 0; | |||||
| public override int RecoveryFromHit => 0; | |||||
| public const int cd = 0; | |||||
| public override int CD => cd; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| } | |||||
| public override bool CanBeBombed(GameObjType gameObjType) | |||||
| { | |||||
| switch (gameObjType) | |||||
| { | |||||
| case GameObjType.Character: | |||||
| case GameObjType.Generator: | |||||
| return true; | |||||
| default: | |||||
| return false; | |||||
| } | |||||
| } | |||||
| public override BulletType TypeOfBullet => BulletType.JumpyDumpty; | |||||
| } | |||||
| } | } | ||||
| @@ -12,7 +12,7 @@ namespace GameClass.GameObj | |||||
| public override double BulletAttackRange => 0; | public override double BulletAttackRange => 0; | ||||
| public override int AP => 7220; | public override int AP => 7220; | ||||
| public override int Speed => 0; | public override int Speed => 0; | ||||
| public override bool IsToBomb => false; | |||||
| public override bool IsRemoteAttack => false; | |||||
| public override int CastTime => 0; | public override int CastTime => 0; | ||||
| public override int Backswing => 0; | public override int Backswing => 0; | ||||
| public override int RecoveryFromHit => 0; | public override int RecoveryFromHit => 0; | ||||
| @@ -13,7 +13,7 @@ namespace GameClass.GameObj | |||||
| public abstract double BulletAttackRange { get; } | public abstract double BulletAttackRange { get; } | ||||
| public abstract int AP { get; set; } | public abstract int AP { get; set; } | ||||
| public abstract int Speed { get; } | public abstract int Speed { get; } | ||||
| public abstract bool IsToBomb { get; } | |||||
| public abstract bool IsRemoteAttack { get; } | |||||
| public abstract int CastTime { get; } | public abstract int CastTime { get; } | ||||
| public abstract int Backswing { get; } | public abstract int Backswing { get; } | ||||
| public abstract int RecoveryFromHit { get; } | public abstract int RecoveryFromHit { get; } | ||||
| @@ -45,7 +45,7 @@ namespace GameClass.GameObj | |||||
| this.place = placeType; | this.place = placeType; | ||||
| this.CanMove = true; | this.CanMove = true; | ||||
| this.moveSpeed = this.Speed; | this.moveSpeed = this.Speed; | ||||
| this.hasSpear = player.HasSpear; | |||||
| this.hasSpear = player.TryUseSpear(); | |||||
| this.Parent = player; | this.Parent = player; | ||||
| } | } | ||||
| public override bool IsRigid => true; // 默认为true | public override bool IsRigid => true; // 默认为true | ||||
| @@ -63,6 +63,10 @@ namespace GameClass.GameObj | |||||
| return new FlyingKnife(character, place, pos); | return new FlyingKnife(character, place, pos); | ||||
| case BulletType.CommonAttackOfGhost: | case BulletType.CommonAttackOfGhost: | ||||
| return new CommonAttackOfGhost(character, place, pos); | return new CommonAttackOfGhost(character, place, pos); | ||||
| case BulletType.JumpyDumpty: | |||||
| return new JumpyDumpty(character, place, pos); | |||||
| case BulletType.BombBomb: | |||||
| return new BombBomb(character, place, pos); | |||||
| default: | default: | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -71,10 +75,6 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| switch (bulletType) | switch (bulletType) | ||||
| { | { | ||||
| case BulletType.AtomBomb: | |||||
| case BulletType.LineBullet: | |||||
| case BulletType.FastBullet: | |||||
| case BulletType.OrdinaryBullet: | |||||
| case BulletType.FlyingKnife: | case BulletType.FlyingKnife: | ||||
| default: | default: | ||||
| return GameData.bulletRadius; | return GameData.bulletRadius; | ||||
| @@ -88,10 +88,10 @@ namespace GameClass.GameObj | |||||
| return CommonAttackOfGhost.cd; | return CommonAttackOfGhost.cd; | ||||
| case BulletType.FlyingKnife: | case BulletType.FlyingKnife: | ||||
| return FlyingKnife.cd; | return FlyingKnife.cd; | ||||
| case BulletType.AtomBomb: | |||||
| case BulletType.LineBullet: | |||||
| case BulletType.FastBullet: | |||||
| case BulletType.OrdinaryBullet: | |||||
| case BulletType.BombBomb: | |||||
| return BombBomb.cd; | |||||
| case BulletType.JumpyDumpty: | |||||
| return JumpyDumpty.cd; | |||||
| default: | default: | ||||
| return GameData.basicCD; | return GameData.basicCD; | ||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | |||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
| using System.Threading; | using System.Threading; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| @@ -183,6 +184,44 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| public bool TryUseSpear() | |||||
| { | |||||
| if (HasSpear) | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.Spear]) | |||||
| { | |||||
| buffList[(int)BuffType.Spear].RemoveFirst(); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void AddClairaudience(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Clairaudience, () => | |||||
| { }); | |||||
| public bool HasClairaudience | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.Clairaudience]) | |||||
| { | |||||
| return buffList[(int)BuffType.Clairaudience].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void AddInvisible(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Invisible, () => | |||||
| { }); | |||||
| public bool HasInvisible | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.Invisible]) | |||||
| { | |||||
| return buffList[(int)BuffType.Invisible].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// 清除所有buff | /// 清除所有buff | ||||
| @@ -66,6 +66,12 @@ namespace GameClass.GameObj | |||||
| case CharacterType.Assassin: | case CharacterType.Assassin: | ||||
| this.occupation = new Assassin(); | this.occupation = new Assassin(); | ||||
| break; | break; | ||||
| case CharacterType.Teacher: | |||||
| this.occupation = new Teacher(); | |||||
| break; | |||||
| case CharacterType.Klee: | |||||
| this.occupation = new Klee(); | |||||
| break; | |||||
| case CharacterType.Athlete: | case CharacterType.Athlete: | ||||
| default: | default: | ||||
| this.occupation = new Athlete(); | this.occupation = new Athlete(); | ||||
| @@ -82,7 +88,7 @@ namespace GameClass.GameObj | |||||
| this.characterType = characterType; | this.characterType = characterType; | ||||
| this.SpeedOfOpeningOrLocking = Occupation.TimeOfOpeningOrLocking; | this.SpeedOfOpeningOrLocking = Occupation.TimeOfOpeningOrLocking; | ||||
| this.SpeedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows; | this.SpeedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows; | ||||
| this.SpeedOfOpenChest = Occupation.TimeOfOpenChest; | |||||
| this.SpeedOfOpenChest = Occupation.SpeedOfOpenChest; | |||||
| foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | ||||
| { | { | ||||
| @@ -47,7 +47,8 @@ namespace GameClass.GameObj | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| bulletOfPlayer = value; | bulletOfPlayer = value; | ||||
| CD = BulletFactory.BulletCD(value); | |||||
| OrgCD = (BulletFactory.BulletCD(value)); | |||||
| CD = 0; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -123,22 +124,6 @@ namespace GameClass.GameObj | |||||
| }*/ | }*/ | ||||
| #endregion | #endregion | ||||
| #region 感知相关的基本属性及方法 | #region 感知相关的基本属性及方法 | ||||
| /// <summary> | |||||
| /// 是否在隐身 | |||||
| /// </summary> | |||||
| private bool isInvisible = false; | |||||
| public bool IsInvisible | |||||
| { | |||||
| get => isInvisible; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| isInvisible = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| private Dictionary<BgmType, double> bgmDictionary = new(); | private Dictionary<BgmType, double> bgmDictionary = new(); | ||||
| public Dictionary<BgmType, double> BgmDictionary | public Dictionary<BgmType, double> BgmDictionary | ||||
| { | { | ||||
| @@ -350,7 +335,7 @@ namespace GameClass.GameObj | |||||
| public bool NullOrMoving() => (playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | public bool NullOrMoving() => (playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | ||||
| public bool CanBeAwed() => !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | public bool CanBeAwed() => !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | ||||
| || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued | || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued | ||||
| || playerState == PlayerStateType.Treated || playerState != PlayerStateType.Stunned | |||||
| || playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned | |||||
| || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | ||||
| private int score = 0; | private int score = 0; | ||||
| @@ -519,6 +504,12 @@ namespace GameClass.GameObj | |||||
| public void AddSpear(int spearTime) => buffManager.AddSpear(spearTime); | public void AddSpear(int spearTime) => buffManager.AddSpear(spearTime); | ||||
| public bool HasSpear => buffManager.HasSpear; | public bool HasSpear => buffManager.HasSpear; | ||||
| public void AddClairaudience(int time) => buffManager.AddClairaudience(time); | |||||
| public bool HasClairaudience => buffManager.HasClairaudience; | |||||
| public void AddInvisible(int time) => buffManager.AddInvisible(time); | |||||
| public bool HasInvisible => buffManager.HasInvisible; | |||||
| private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | ||||
| public Dictionary<BuffType, bool> Buff | public Dictionary<BuffType, bool> Buff | ||||
| { | { | ||||
| @@ -568,6 +559,11 @@ namespace GameClass.GameObj | |||||
| return false; | return false; | ||||
| } | } | ||||
| public bool TryUseSpear() | |||||
| { | |||||
| return buffManager.TryUseSpear(); | |||||
| } | |||||
| public bool TryUseShield() | public bool TryUseShield() | ||||
| { | { | ||||
| if (buffManager.TryUseShield()) | if (buffManager.TryUseShield()) | ||||
| @@ -62,10 +62,10 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| public class NuclearWeapon : IActiveSkill // 核武器 | |||||
| public class JumpyBomb : IActiveSkill | |||||
| { | { | ||||
| public int SkillCD => GameData.commonSkillCD * 7 / 3; | |||||
| public int DurationTime => GameData.commonSkillTime / 10; | |||||
| public int SkillCD => GameData.commonSkillCD / 30 * 5; | |||||
| public int DurationTime => GameData.commonSkillTime / 2; | |||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object ActiveSkillLock => commonSkillLock; | public object ActiveSkillLock => commonSkillLock; | ||||
| @@ -132,6 +132,8 @@ namespace GameClass.GameObj | |||||
| return new CanBeginToCharge(); | return new CanBeginToCharge(); | ||||
| case ActiveSkillType.Punish: | case ActiveSkillType.Punish: | ||||
| return new Punish(); | return new Punish(); | ||||
| case ActiveSkillType.JumpyBomb: | |||||
| return new JumpyBomb(); | |||||
| default: | default: | ||||
| return new NullSkill(); | return new NullSkill(); | ||||
| } | } | ||||
| @@ -149,6 +151,8 @@ namespace GameClass.GameObj | |||||
| return ActiveSkillType.CanBeginToCharge; | return ActiveSkillType.CanBeginToCharge; | ||||
| case Punish: | case Punish: | ||||
| return ActiveSkillType.Punish; | return ActiveSkillType.Punish; | ||||
| case JumpyBomb: | |||||
| return ActiveSkillType.JumpyBomb; | |||||
| default: | default: | ||||
| return ActiveSkillType.Null; | return ActiveSkillType.Null; | ||||
| } | } | ||||
| @@ -251,7 +251,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| public bool CanSee(Character player, GameObj gameObj) | public bool CanSee(Character player, GameObj gameObj) | ||||
| { | { | ||||
| if ((gameObj.Type == GameObjType.Character) && !((Character)gameObj).IsInvisible) return false; | |||||
| if ((gameObj.Type == GameObjType.Character) && !((Character)gameObj).HasInvisible) return false; | |||||
| XY pos1 = player.Position; | XY pos1 = player.Position; | ||||
| XY pos2 = gameObj.Position; | XY pos2 = gameObj.Position; | ||||
| XY del = pos1 - pos2; | XY del = pos1 - pos2; | ||||
| @@ -52,13 +52,13 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 复活甲 | /// 复活甲 | ||||
| /// </summary> | /// </summary> | ||||
| public sealed class AddLifeOrAp : Prop | |||||
| public sealed class AddLifeOrClairaudience : Prop | |||||
| { | { | ||||
| public AddLifeOrAp(XY initPos, PlaceType placeType) : | |||||
| public AddLifeOrClairaudience(XY initPos, PlaceType placeType) : | |||||
| base(initPos, placeType) | base(initPos, placeType) | ||||
| { | { | ||||
| } | } | ||||
| public override PropType GetPropType() => PropType.AddLifeOrAp; | |||||
| public override PropType GetPropType() => PropType.AddLifeOrClairaudience; | |||||
| } | } | ||||
| public sealed class AddHpOrAp : Prop | public sealed class AddHpOrAp : Prop | ||||
| { | { | ||||
| @@ -141,8 +141,8 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| case PropType.AddSpeed: | case PropType.AddSpeed: | ||||
| return new AddSpeed(pos, place); | return new AddSpeed(pos, place); | ||||
| case PropType.AddLifeOrAp: | |||||
| return new AddLifeOrAp(pos, place); | |||||
| case PropType.AddLifeOrClairaudience: | |||||
| return new AddLifeOrClairaudience(pos, place); | |||||
| case PropType.ShieldOrSpear: | case PropType.ShieldOrSpear: | ||||
| return new ShieldOrSpear(pos, place); | return new ShieldOrSpear(pos, place); | ||||
| case PropType.AddHpOrAp: | case PropType.AddHpOrAp: | ||||
| @@ -158,4 +158,4 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -17,8 +17,16 @@ namespace Gaming | |||||
| { | { | ||||
| // 人物移动 | // 人物移动 | ||||
| private void SkillWhenMove(Character player, IGameObj collisionObj) | |||||
| private static void SkillWhenColliding(Character player, IGameObj collisionObj) | |||||
| { | { | ||||
| if (collisionObj.Type == GameObjType.Bullet) | |||||
| { | |||||
| if (((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | |||||
| { | |||||
| if (AttackManager.BeStunned((Character)collisionObj, ((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting)) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(((Bullet)collisionObj).AP / GameData.timeFactorOfGhostFainting)); | |||||
| } | |||||
| } | |||||
| if (player.UseIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | if (player.UseIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | ||||
| { | { | ||||
| if (AttackManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | if (AttackManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | ||||
| @@ -188,7 +196,7 @@ namespace Gaming | |||||
| playerTreated = gameMap.StudentForInteract(player.Position); | playerTreated = gameMap.StudentForInteract(player.Position); | ||||
| if (playerTreated == null) return false; | if (playerTreated == null) return false; | ||||
| } | } | ||||
| if ((!player.Commandable()) || player.PlayerState == PlayerStateType.Treating || | |||||
| if (player == playerTreated || (!player.Commandable()) || player.PlayerState == PlayerStateType.Treating || | |||||
| (!playerTreated.Commandable()) || | (!playerTreated.Commandable()) || | ||||
| playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position)) | playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position)) | ||||
| return false; | return false; | ||||
| @@ -254,11 +262,12 @@ namespace Gaming | |||||
| playerRescued = gameMap.StudentForInteract(player.Position); | playerRescued = gameMap.StudentForInteract(player.Position); | ||||
| if (playerRescued == null) return false; | if (playerRescued == null) return false; | ||||
| } | } | ||||
| if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) | |||||
| if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || player == playerRescued | |||||
| || !GameData.ApproachToInteract(playerRescued.Position, player.Position) || playerRescued.TimeOfRescue > 0) | |||||
| return false; | return false; | ||||
| player.PlayerState = PlayerStateType.Rescuing; | player.PlayerState = PlayerStateType.Rescuing; | ||||
| playerRescued.PlayerState = PlayerStateType.Rescued; | playerRescued.PlayerState = PlayerStateType.Rescued; | ||||
| player.TimeOfRescue = 0; | |||||
| new Thread | new Thread | ||||
| ( | ( | ||||
| () => | () => | ||||
| @@ -267,7 +276,7 @@ namespace Gaming | |||||
| loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && player.PlayerState == PlayerStateType.Rescuing && gameMap.Timer.IsGaming && GameData.ApproachToInteract(playerRescued.Position, player.Position), | loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && player.PlayerState == PlayerStateType.Rescuing && gameMap.Timer.IsGaming && GameData.ApproachToInteract(playerRescued.Position, player.Position), | ||||
| loopToDo: () => | loopToDo: () => | ||||
| { | { | ||||
| player.TimeOfRescue += GameData.frameDuration; | |||||
| playerRescued.TimeOfRescue += GameData.frameDuration; | |||||
| }, | }, | ||||
| timeInterval: GameData.frameDuration, | timeInterval: GameData.frameDuration, | ||||
| finallyReturn: () => 0, | finallyReturn: () => 0, | ||||
| @@ -277,16 +286,17 @@ namespace Gaming | |||||
| if (playerRescued.PlayerState == PlayerStateType.Rescued) | if (playerRescued.PlayerState == PlayerStateType.Rescued) | ||||
| { | { | ||||
| if (player.TimeOfRescue >= GameData.basicTimeOfRescue) | |||||
| if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue) | |||||
| { | { | ||||
| playerRescued.PlayerState = PlayerStateType.Null; | playerRescued.PlayerState = PlayerStateType.Null; | ||||
| playerRescued.HP = GameData.RemainHpWhenAddLife; | |||||
| player.AddScore(GameData.StudentScoreRescue); | player.AddScore(GameData.StudentScoreRescue); | ||||
| } | } | ||||
| else | else | ||||
| playerRescued.PlayerState = PlayerStateType.Addicted; | playerRescued.PlayerState = PlayerStateType.Addicted; | ||||
| } | } | ||||
| if (player.PlayerState == PlayerStateType.Rescuing) player.PlayerState = PlayerStateType.Null; | if (player.PlayerState == PlayerStateType.Rescuing) player.PlayerState = PlayerStateType.Null; | ||||
| player.TimeOfRescue = 0; | |||||
| playerRescued.TimeOfRescue = 0; | |||||
| } | } | ||||
| ) | ) | ||||
| { IsBackground = true }.Start(); | { IsBackground = true }.Start(); | ||||
| @@ -494,7 +504,7 @@ namespace Gaming | |||||
| gameMap: gameMap, | gameMap: gameMap, | ||||
| OnCollision: (obj, collisionObj, moveVec) => | OnCollision: (obj, collisionObj, moveVec) => | ||||
| { | { | ||||
| SkillWhenMove((Character)obj, collisionObj); | |||||
| SkillWhenColliding((Character)obj, collisionObj); | |||||
| //if (collisionObj is Mine) | //if (collisionObj is Mine) | ||||
| //{ | //{ | ||||
| // ActivateMine((Character)obj, (Mine)collisionObj); | // ActivateMine((Character)obj, (Mine)collisionObj); | ||||
| @@ -33,7 +33,7 @@ namespace Gaming | |||||
| Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | ||||
| #endif | #endif | ||||
| if (obj.CanMove) | |||||
| if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty) | |||||
| BulletBomb((Bullet)obj, null); | BulletBomb((Bullet)obj, null); | ||||
| } | } | ||||
| ); | ); | ||||
| @@ -124,10 +124,6 @@ namespace Gaming | |||||
| gameMap.GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); | gameMap.GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); | ||||
| } | } | ||||
| } | } | ||||
| // player.Reset(); | |||||
| // ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 | |||||
| } | } | ||||
| private void BombObj(Bullet bullet, GameObj objBeingShot) | private void BombObj(Bullet bullet, GameObj objBeingShot) | ||||
| @@ -174,10 +170,10 @@ namespace Gaming | |||||
| #endif | #endif | ||||
| bullet.CanMove = false; | bullet.CanMove = false; | ||||
| if (gameMap.Remove(bullet) && bullet.IsToBomb) | |||||
| if (gameMap.Remove(bullet) && bullet.BulletBombRange > 0) | |||||
| gameMap.Add(new BombedBullet(bullet)); | gameMap.Add(new BombedBullet(bullet)); | ||||
| if (!bullet.IsToBomb) | |||||
| if (bullet.BulletBombRange == 0) | |||||
| { | { | ||||
| if (objBeingShot == null) | if (objBeingShot == null) | ||||
| { | { | ||||
| @@ -201,7 +197,14 @@ namespace Gaming | |||||
| return; | return; | ||||
| } | } | ||||
| if (bullet.TypeOfBullet == BulletType.BombBomb) | |||||
| { | |||||
| bullet.Parent.BulletOfPlayer = BulletType.JumpyDumpty; | |||||
| Attack((Character)bullet.Parent, 0.0); | |||||
| Attack((Character)bullet.Parent, Math.PI); | |||||
| Attack((Character)bullet.Parent, Math.PI / 2.0); | |||||
| Attack((Character)bullet.Parent, Math.PI * 3.0 / 2.0); | |||||
| } | |||||
| BombObj(bullet, objBeingShot); | BombObj(bullet, objBeingShot); | ||||
| if (bullet.RecoveryFromHit > 0) | if (bullet.RecoveryFromHit > 0) | ||||
| { | { | ||||
| @@ -304,7 +307,7 @@ namespace Gaming | |||||
| beAttackedList.Clear(); | beAttackedList.Clear(); | ||||
| } | } | ||||
| public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头) | |||||
| public bool Attack(Character? player, double angle) | |||||
| { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | ||||
| if (player == null) | if (player == null) | ||||
| { | { | ||||
| @@ -31,10 +31,10 @@ namespace Gaming | |||||
| player.AddSpear(GameData.PropDuration); | player.AddSpear(GameData.PropDuration); | ||||
| else player.AddShield(GameData.PropDuration); | else player.AddShield(GameData.PropDuration); | ||||
| break; | break; | ||||
| case PropType.AddLifeOrAp: | |||||
| case PropType.AddLifeOrClairaudience: | |||||
| if (!player.IsGhost()) | if (!player.IsGhost()) | ||||
| player.AddLIFE(GameData.PropDuration); | player.AddLIFE(GameData.PropDuration); | ||||
| else player.AddAp(GameData.PropDuration); | |||||
| else player.AddClairaudience(GameData.PropDuration); | |||||
| break; | break; | ||||
| case PropType.AddSpeed: | case PropType.AddSpeed: | ||||
| player.AddMoveSpeed(GameData.PropDuration); | player.AddMoveSpeed(GameData.PropDuration); | ||||
| @@ -118,7 +118,7 @@ namespace Gaming | |||||
| private Prop ProduceOnePropNotKey(Random r, XY Pos) | private Prop ProduceOnePropNotKey(Random r, XY Pos) | ||||
| { | { | ||||
| return PropFactory.GetProp((PropType)r.Next(0, GameData.numOfPropTypeNotKey), Pos, gameMap.GetPlaceType(Pos)); | |||||
| return PropFactory.GetProp((PropType)r.Next(GameData.numOfTeachingBuilding + 1, GameData.numOfPropSpecies + 1), Pos, gameMap.GetPlaceType(Pos)); | |||||
| } | } | ||||
| private Chest GetChest(Random r) | private Chest GetChest(Random r) | ||||
| @@ -36,7 +36,7 @@ namespace Gaming | |||||
| return ActiveSkillEffect(skill, player, () => | return ActiveSkillEffect(skill, player, () => | ||||
| { | { | ||||
| player.AddMoveSpeed(skill.DurationTime, 3.0); | player.AddMoveSpeed(skill.DurationTime, 3.0); | ||||
| //See SkillWhenMove in ActionManager | |||||
| //See SkillWhenColliding in ActionManager | |||||
| }, | }, | ||||
| () => | () => | ||||
| { }); | { }); | ||||
| @@ -45,21 +45,22 @@ namespace Gaming | |||||
| public static bool BecomeInvisible(Character player) | public static bool BecomeInvisible(Character player) | ||||
| { | { | ||||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.BecomeInvisible), player, () => | |||||
| IActiveSkill activeSkill = player.UseIActiveSkill(ActiveSkillType.BecomeInvisible); | |||||
| return ActiveSkillEffect(activeSkill, player, () => | |||||
| { | { | ||||
| player.IsInvisible = true; | |||||
| player.AddInvisible(activeSkill.DurationTime); | |||||
| Debugger.Output(player, "become invisible!"); | Debugger.Output(player, "become invisible!"); | ||||
| }, | }, | ||||
| () => | () => | ||||
| { player.IsInvisible = false; }); | |||||
| { }); | |||||
| } | } | ||||
| public bool NuclearWeapon(Character player) | |||||
| public bool JumpyBomb(Character player) | |||||
| { | { | ||||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.NuclearWeapon), player, () => | |||||
| return ActiveSkillEffect(player.UseIActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||||
| { | { | ||||
| player.BulletOfPlayer = BulletType.AtomBomb; | |||||
| Debugger.Output(player, "uses atombomb!"); | |||||
| player.BulletOfPlayer = BulletType.BombBomb; | |||||
| Debugger.Output(player, "uses jumpybomb!"); | |||||
| }, | }, | ||||
| () => | () => | ||||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | ||||
| @@ -91,8 +92,8 @@ namespace Gaming | |||||
| || player.PlayerState == PlayerStateType.UsingSkill || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || player.PlayerState == PlayerStateType.OpeningTheChest) | || player.PlayerState == PlayerStateType.UsingSkill || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || player.PlayerState == PlayerStateType.OpeningTheChest) | ||||
| && gameMap.CanSee(player, character)) | && gameMap.CanSee(player, character)) | ||||
| { | { | ||||
| if (AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting)) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.TimeFactorOfGhostFainting)); | |||||
| if (AttackManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting)) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting)); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -28,6 +28,9 @@ namespace Gaming | |||||
| case ActiveSkillType.Punish: | case ActiveSkillType.Punish: | ||||
| Punish(character); | Punish(character); | ||||
| break; | break; | ||||
| case ActiveSkillType.JumpyBomb: | |||||
| JumpyBomb(character); | |||||
| break; | |||||
| default: | default: | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -11,6 +11,8 @@ namespace Preparation.Interface | |||||
| public void AddScore(int add); | public void AddScore(int add); | ||||
| public double Vampire { get; } | public double Vampire { get; } | ||||
| public PlayerStateType PlayerState { get; set; } | public PlayerStateType PlayerState { get; set; } | ||||
| public BulletType BulletOfPlayer { get; set; } | |||||
| public bool IsGhost(); | public bool IsGhost(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -16,7 +16,7 @@ namespace Preparation.Interface | |||||
| public int ViewRange { get; } | public int ViewRange { get; } | ||||
| public int TimeOfOpeningOrLocking { get; } | public int TimeOfOpeningOrLocking { get; } | ||||
| public int SpeedOfClimbingThroughWindows { get; } | public int SpeedOfClimbingThroughWindows { get; } | ||||
| public int TimeOfOpenChest { get; } | |||||
| public int SpeedOfOpenChest { get; } | |||||
| } | } | ||||
| public interface IGhost : IOccupation | public interface IGhost : IOccupation | ||||
| @@ -32,7 +32,7 @@ namespace Preparation.Interface | |||||
| public class Assassin : IGhost | public class Assassin : IGhost | ||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed * 473 / 380; | |||||
| private const int moveSpeed = (int)(GameData.basicMoveSpeed * 473.0 / 380); | |||||
| public int MoveSpeed => moveSpeed; | public int MoveSpeed => moveSpeed; | ||||
| private const int maxHp = GameData.basicHp; | private const int maxHp = GameData.basicHp; | ||||
| @@ -61,8 +61,42 @@ namespace Preparation.Interface | |||||
| public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows; | public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows; | ||||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | ||||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int TimeOfOpenChest => timeOfOpenChest; | |||||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||||
| } | |||||
| public class Klee : IGhost | |||||
| { | |||||
| private const int moveSpeed = (int)(GameData.basicMoveSpeed * 155 / 127); | |||||
| public int MoveSpeed => moveSpeed; | |||||
| private const int maxHp = GameData.basicHp; | |||||
| public int MaxHp => maxHp; | |||||
| public const int maxBulletNum = 1; | |||||
| public int MaxBulletNum => maxBulletNum; | |||||
| public BulletType InitBullet => BulletType.CommonAttackOfGhost; | |||||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb }); | |||||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||||
| public double concealment = GameData.basicConcealment; | |||||
| public double Concealment => concealment; | |||||
| public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.069); | |||||
| public int AlertnessRadius => alertnessRadius; | |||||
| public int viewRange = (int)(GameData.basicViewRange * 1.1); | |||||
| public int ViewRange => viewRange; | |||||
| public int timeOfOpeningOrLocking = (int)(GameData.basicSpeedOfOpeningOrLocking / 1.1); | |||||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||||
| public int speedOfClimbingThroughWindows = (int)(GameData.basicGhostSpeedOfClimbingThroughWindows / 1.1); | |||||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||||
| public int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1); | |||||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||||
| } | } | ||||
| public class Teacher : IStudent | public class Teacher : IStudent | ||||
| { | { | ||||
| @@ -104,8 +138,8 @@ namespace Preparation.Interface | |||||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows / 2; | public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows / 2; | ||||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | ||||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int TimeOfOpenChest => timeOfOpenChest; | |||||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||||
| } | } | ||||
| public class Athlete : IStudent | public class Athlete : IStudent | ||||
| { | { | ||||
| @@ -147,7 +181,7 @@ namespace Preparation.Interface | |||||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10; | public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10; | ||||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | ||||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int TimeOfOpenChest => timeOfOpenChest; | |||||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||||
| } | } | ||||
| } | } | ||||
| @@ -53,31 +53,30 @@ namespace Preparation.Utility | |||||
| public enum BulletType // 子弹类型 | public enum BulletType // 子弹类型 | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| OrdinaryBullet = 1, // 普通子弹 | |||||
| AtomBomb = 2, // 原子弹 | |||||
| FastBullet = 3, // 快速子弹 | |||||
| LineBullet = 4, // 直线子弹 | |||||
| FlyingKnife = 5, //飞刀 | |||||
| CommonAttackOfGhost = 6, | |||||
| FlyingKnife = 1, //飞刀 | |||||
| CommonAttackOfGhost = 2, | |||||
| JumpyDumpty = 3, | |||||
| BombBomb = 4, | |||||
| // Ram = 7, | // Ram = 7, | ||||
| } | } | ||||
| public enum PropType // 道具类型 | public enum PropType // 道具类型 | ||||
| { | |||||
| {//numOfPropSpecies 见Gamedata | |||||
| Null = 0, | Null = 0, | ||||
| AddSpeed = 1, | |||||
| AddLifeOrAp = 2, | |||||
| AddHpOrAp = 3, | |||||
| ShieldOrSpear = 4, | |||||
| Key3 = 5, | |||||
| Key5 = 6, | |||||
| Key6 = 7, | |||||
| Key3 = 1, | |||||
| Key5 = 2, | |||||
| Key6 = 3, | |||||
| AddSpeed = 4, | |||||
| AddLifeOrClairaudience = 5, | |||||
| AddHpOrAp = 6, | |||||
| ShieldOrSpear = 7, | |||||
| RecoveryFromDizziness = 8, | |||||
| } | } | ||||
| public enum CharacterType // 职业 | public enum CharacterType // 职业 | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| Assassin = 1, | Assassin = 1, | ||||
| Athlete = 2, | Athlete = 2, | ||||
| RecoverAfterBattle = 3, | |||||
| Klee = 3, | |||||
| SpeedUpWhenLeavingGrass = 4, | SpeedUpWhenLeavingGrass = 4, | ||||
| Teacher = 5, | Teacher = 5, | ||||
| PSkill5 = 6 | PSkill5 = 6 | ||||
| @@ -87,7 +86,7 @@ namespace Preparation.Utility | |||||
| Null = 0, | Null = 0, | ||||
| BecomeInvisible = 1, | BecomeInvisible = 1, | ||||
| BecomeVampire = 2, | BecomeVampire = 2, | ||||
| NuclearWeapon = 3, | |||||
| JumpyBomb = 3, | |||||
| SuperFast = 4, | SuperFast = 4, | ||||
| UseKnife = 5, | UseKnife = 5, | ||||
| CanBeginToCharge = 6, | CanBeginToCharge = 6, | ||||
| @@ -111,8 +110,9 @@ namespace Preparation.Utility | |||||
| Shield = 3, | Shield = 3, | ||||
| Spear = 4, | Spear = 4, | ||||
| AddAp = 5, | AddAp = 5, | ||||
| Clairaudience = 6, | |||||
| Invisible = 7, | |||||
| } | } | ||||
| public enum PlaceType | public enum PlaceType | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| @@ -35,6 +35,14 @@ namespace Preparation.Utility | |||||
| { | { | ||||
| return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window && gameObjType != GameObjType.Wall; | return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window && gameObjType != GameObjType.Wall; | ||||
| } | } | ||||
| /* public static bool Collide(GameObjType gameObjType) | |||||
| { | |||||
| return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass | |||||
| && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window | |||||
| && gameObjType != GameObjType.Bullet&&gameObjType != GameObjType.Prop | |||||
| &&gameObjType != GameObjType.PickedProp&&gameObjType != GameObjType.BombedBullet | |||||
| &&gameObjType != GameObjType.EmergencyExit&&gameObjType != GameObjType.Doorway; | |||||
| }*/ | |||||
| public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 | public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 | ||||
| { | { | ||||
| @@ -59,10 +67,12 @@ namespace Preparation.Utility | |||||
| } | } | ||||
| public static bool ApproachToInteract(XY pos1, XY pos2) | public static bool ApproachToInteract(XY pos1, XY pos2) | ||||
| { | { | ||||
| if (pos1 == pos2) return false; | |||||
| return Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) <= 1 && Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2)) <= 1; | return Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) <= 1 && Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2)) <= 1; | ||||
| } | } | ||||
| public static bool ApproachToInteractInACross(XY pos1, XY pos2) | public static bool ApproachToInteractInACross(XY pos1, XY pos2) | ||||
| { | { | ||||
| if (pos1 == pos2) return false; | |||||
| return (Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) + Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2))) <= 1; | return (Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) + Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2))) <= 1; | ||||
| } | } | ||||
| #endregion | #endregion | ||||
| @@ -104,6 +114,7 @@ namespace Preparation.Utility | |||||
| return characterType switch | return characterType switch | ||||
| { | { | ||||
| CharacterType.Assassin => true, | CharacterType.Assassin => true, | ||||
| CharacterType.Klee => true, | |||||
| _ => false, | _ => false, | ||||
| }; | }; | ||||
| } | } | ||||
| @@ -159,13 +170,13 @@ namespace Preparation.Utility | |||||
| public const int basicCD = 3000; // 初始子弹冷却 | public const int basicCD = 3000; // 初始子弹冷却 | ||||
| public const int basicCastTime = 500;//基本前摇时间 | public const int basicCastTime = 500;//基本前摇时间 | ||||
| public const int basicBackswing = 818;//基本后摇时间 | public const int basicBackswing = 818;//基本后摇时间 | ||||
| public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 | |||||
| public const int basicRecoveryFromHit = 3700;//基本命中攻击恢复时长 | |||||
| public const int basicStunnedTimeOfStudent = 4130; | public const int basicStunnedTimeOfStudent = 4130; | ||||
| public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1 | |||||
| public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围 | |||||
| public const double basicAttackShortRange = 2700; // 基本近程攻击范围 | |||||
| public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围 | |||||
| public const int basicBulletMoveSpeed = 1800; // 基本子弹移动速度,单位:s-1 | |||||
| public const double basicRemoteAttackRange = 3000; // 基本远程攻击范围 | |||||
| public const double basicAttackShortRange = 900; // 基本近程攻击范围 | |||||
| public const double basicBulletBombRange = 1000; // 基本子弹爆炸范围 | |||||
| #endregion | #endregion | ||||
| #region 技能相关 | #region 技能相关 | ||||
| public const int maxNumOfSkill = 3; | public const int maxNumOfSkill = 3; | ||||
| @@ -181,11 +192,9 @@ namespace Preparation.Utility | |||||
| /// Punish | /// Punish | ||||
| /// </summary> | /// </summary> | ||||
| public const int TimeOfGhostFaintingWhenPunish = 3070; | public const int TimeOfGhostFaintingWhenPunish = 3070; | ||||
| public const int TimeFactorOfGhostFainting = 1000; | |||||
| public const int timeFactorOfGhostFainting = 250; | |||||
| #endregion | #endregion | ||||
| #region 道具相关 | #region 道具相关 | ||||
| public const int MinPropTypeNum = 1; | |||||
| public const int MaxPropTypeNum = 10; | |||||
| public const int PropRadius = numOfPosGridPerCell / 2; | public const int PropRadius = numOfPosGridPerCell / 2; | ||||
| public const int PropMoveSpeed = 3000; | public const int PropMoveSpeed = 3000; | ||||
| public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; | public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; | ||||
| @@ -196,6 +205,7 @@ namespace Preparation.Utility | |||||
| public const int ApSpearAdd = basicApOfGhost * 6 / 10; | public const int ApSpearAdd = basicApOfGhost * 6 / 10; | ||||
| public const int RemainHpWhenAddLife = 100; | public const int RemainHpWhenAddLife = 100; | ||||
| public const int numOfPropSpecies = 8; | |||||
| public const int numOfKeyEachArea = 2; | public const int numOfKeyEachArea = 2; | ||||
| public const int numOfPropTypeNotKey = 4; | public const int numOfPropTypeNotKey = 4; | ||||
| public const int numOfTeachingBuilding = 3; | public const int numOfTeachingBuilding = 3; | ||||
| @@ -54,6 +54,14 @@ namespace Preparation.Utility | |||||
| { | { | ||||
| return new XY(v1.x - v2.x, v1.y - v2.y); | return new XY(v1.x - v2.x, v1.y - v2.y); | ||||
| } | } | ||||
| public static bool operator ==(XY v1, XY v2) | |||||
| { | |||||
| return v1.x == v2.x && v1.y == v2.y; | |||||
| } | |||||
| public static bool operator !=(XY v1, XY v2) | |||||
| { | |||||
| return v1.x != v2.x || v1.y != v2.y; | |||||
| } | |||||
| public static double Distance(XY p1, XY p2) | public static double Distance(XY p1, XY p2) | ||||
| { | { | ||||
| return Math.Sqrt(((long)(p1.x - p2.x) * (p1.x - p2.x)) + ((long)(p1.y - p2.y) * (p1.y - p2.y))); | return Math.Sqrt(((long)(p1.x - p2.x) * (p1.x - p2.x)) + ((long)(p1.y - p2.y) * (p1.y - p2.y))); | ||||
| @@ -66,5 +74,15 @@ namespace Preparation.Utility | |||||
| { | { | ||||
| return Math.Atan2(y, x); | return Math.Atan2(y, x); | ||||
| } | } | ||||
| public override bool Equals(object obj) | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| public override int GetHashCode() | |||||
| { | |||||
| throw new NotImplementedException(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -50,7 +50,7 @@ namespace Server | |||||
| { | { | ||||
| case Preparation.Utility.PropType.AddSpeed: | case Preparation.Utility.PropType.AddSpeed: | ||||
| return Protobuf.PropType.AddSpeed; | return Protobuf.PropType.AddSpeed; | ||||
| case Preparation.Utility.PropType.AddLifeOrAp: | |||||
| case Preparation.Utility.PropType.AddLifeOrClairaudience: | |||||
| return Protobuf.PropType.AddLifeOrAp; | return Protobuf.PropType.AddLifeOrAp; | ||||
| case Preparation.Utility.PropType.AddHpOrAp: | case Preparation.Utility.PropType.AddHpOrAp: | ||||
| return Protobuf.PropType.AddHpOrAp; | return Protobuf.PropType.AddHpOrAp; | ||||
| @@ -74,7 +74,7 @@ namespace Server | |||||
| case Protobuf.PropType.AddSpeed: | case Protobuf.PropType.AddSpeed: | ||||
| return Preparation.Utility.PropType.AddSpeed; | return Preparation.Utility.PropType.AddSpeed; | ||||
| case Protobuf.PropType.AddLifeOrAp: | case Protobuf.PropType.AddLifeOrAp: | ||||
| return Preparation.Utility.PropType.AddLifeOrAp; | |||||
| return Preparation.Utility.PropType.AddLifeOrClairaudience; | |||||
| case Protobuf.PropType.AddHpOrAp: | case Protobuf.PropType.AddHpOrAp: | ||||
| return Preparation.Utility.PropType.AddHpOrAp; | return Preparation.Utility.PropType.AddHpOrAp; | ||||
| case Protobuf.PropType.ShieldOrSpear: | case Protobuf.PropType.ShieldOrSpear: | ||||
| @@ -195,6 +195,8 @@ namespace Server | |||||
| { | { | ||||
| case Preparation.Utility.CharacterType.Assassin: | case Preparation.Utility.CharacterType.Assassin: | ||||
| return Protobuf.TrickerType.Assassin; | return Protobuf.TrickerType.Assassin; | ||||
| case Preparation.Utility.CharacterType.Klee: | |||||
| return Protobuf.TrickerType._2; | |||||
| default: | default: | ||||
| return Protobuf.TrickerType.NullTrickerType; | return Protobuf.TrickerType.NullTrickerType; | ||||
| } | } | ||||
| @@ -206,6 +208,8 @@ namespace Server | |||||
| { | { | ||||
| case Protobuf.TrickerType.Assassin: | case Protobuf.TrickerType.Assassin: | ||||
| return Preparation.Utility.CharacterType.Assassin; | return Preparation.Utility.CharacterType.Assassin; | ||||
| case Protobuf.TrickerType._2: | |||||
| return Preparation.Utility.CharacterType.Klee; | |||||
| default: | default: | ||||
| return Preparation.Utility.CharacterType.Null; | return Preparation.Utility.CharacterType.Null; | ||||
| } | } | ||||
| @@ -240,7 +240,13 @@ namespace Server | |||||
| { | { | ||||
| switch (n) | switch (n) | ||||
| { | { | ||||
| case 0: return Protobuf.PlaceType.Land; | |||||
| case 0: | |||||
| case 1: | |||||
| case 2: | |||||
| case 3: | |||||
| case 4: | |||||
| case 5: | |||||
| return Protobuf.PlaceType.Land; | |||||
| case 6: return Protobuf.PlaceType.Wall; | case 6: return Protobuf.PlaceType.Wall; | ||||
| case 7: return Protobuf.PlaceType.Grass; | case 7: return Protobuf.PlaceType.Grass; | ||||
| case 8: return Protobuf.PlaceType.Classroom; | case 8: return Protobuf.PlaceType.Classroom; | ||||
| @@ -1,142 +0,0 @@ | |||||
| | |||||
| namespace Preparation.Utility | |||||
| { | |||||
| /// <summary> | |||||
| /// 存放所有用到的枚举类型 | |||||
| /// </summary> | |||||
| public enum PlayerStateType | |||||
| { | |||||
| Null = 0, | |||||
| Addicted = 1, | |||||
| Escaped = 2, | |||||
| Swinging = 3,//指后摇 | |||||
| Deceased = 4, | |||||
| Moving = 5, | |||||
| Treating = 6, | |||||
| Rescuing = 7, | |||||
| Fixing = 8, | |||||
| Treated = 9, | |||||
| Rescued = 10, | |||||
| Stunned = 11, | |||||
| TryingToAttack = 12,//指前摇 | |||||
| LockingOrOpeningTheDoor = 13, | |||||
| OpeningTheChest = 14, | |||||
| ClimbingThroughWindows = 15, | |||||
| UsingSkill = 16, | |||||
| OpeningTheDoorway = 17, | |||||
| } | |||||
| public enum GameObjType | |||||
| { | |||||
| Null = 0, | |||||
| Character = 1, | |||||
| Prop = 2, | |||||
| PickedProp = 3, | |||||
| Bullet = 4, | |||||
| BombedBullet = 5, | |||||
| Wall = 6, | |||||
| Grass = 7, | |||||
| Generator = 8, // 发电机 | |||||
| Doorway = 9, | |||||
| EmergencyExit = 10, | |||||
| OutOfBoundBlock = 11, // 范围外 | |||||
| Window = 12, | |||||
| Door = 13, | |||||
| Chest = 14, | |||||
| } | |||||
| public enum ShapeType | |||||
| { | |||||
| Null = 0, | |||||
| Circle = 1, // 子弹和人物为圆形,格子为方形 | |||||
| Square = 2 | |||||
| } | |||||
| public enum BulletType // 子弹类型 | |||||
| { | |||||
| Null = 0, | |||||
| OrdinaryBullet = 1, // 普通子弹 | |||||
| AtomBomb = 2, // 原子弹 | |||||
| FastBullet = 3, // 快速子弹 | |||||
| LineBullet = 4, // 直线子弹 | |||||
| FlyingKnife = 5, //飞刀 | |||||
| CommonAttackOfGhost = 6, | |||||
| // Ram = 7, | |||||
| } | |||||
| public enum PropType // 道具类型 | |||||
| { | |||||
| Null = 0, | |||||
| AddSpeed = 1, | |||||
| AddLifeOrAp = 2, | |||||
| AddHpOrAp = 3, | |||||
| ShieldOrSpear = 4, | |||||
| Key3 = 5, | |||||
| Key5 = 6, | |||||
| Key6 = 7, | |||||
| } | |||||
| public enum CharacterType // 职业 | |||||
| { | |||||
| Null = 0, | |||||
| Assassin = 1, | |||||
| Athlete = 2, | |||||
| RecoverAfterBattle = 3, | |||||
| SpeedUpWhenLeavingGrass = 4, | |||||
| Teacher = 5, | |||||
| PSkill5 = 6 | |||||
| } | |||||
| public enum ActiveSkillType // 主动技能 | |||||
| { | |||||
| Null = 0, | |||||
| BecomeInvisible = 1, | |||||
| BecomeVampire = 2, | |||||
| NuclearWeapon = 3, | |||||
| SuperFast = 4, | |||||
| UseKnife = 5, | |||||
| CanBeginToCharge = 6, | |||||
| Punish = 7, | |||||
| } | |||||
| public enum PassiveSkillType | |||||
| { | |||||
| Null = 0, | |||||
| BecomeInvisible = 1, | |||||
| BecomeVampire = 2, | |||||
| NuclearWeapon = 3, | |||||
| SuperFast = 4, | |||||
| ASkill4 = 5, | |||||
| ASkill5 = 6 | |||||
| } | |||||
| public enum BuffType // buff | |||||
| { | |||||
| Null = 0, | |||||
| AddSpeed = 1, | |||||
| AddLIFE = 2, | |||||
| Shield = 3, | |||||
| Spear = 4, | |||||
| AddAp = 5, | |||||
| } | |||||
| public enum PlaceType | |||||
| { | |||||
| Null = 0, | |||||
| BirthPoint1 = 1,//必须从1开始 | |||||
| BirthPoint2 = 2, | |||||
| BirthPoint3 = 3, | |||||
| BirthPoint4 = 4, | |||||
| BirthPoint5 = 5, | |||||
| Wall = 6, | |||||
| Grass = 7, | |||||
| Generator = 8, // 发电机 | |||||
| Doorway = 9, | |||||
| EmergencyExit = 10, | |||||
| Window = 11, | |||||
| Door3 = 12, | |||||
| Door5 = 13, | |||||
| Door6 = 14, | |||||
| Chest = 15, | |||||
| } | |||||
| public enum BgmType | |||||
| { | |||||
| Null = 0, | |||||
| GhostIsComing = 1, | |||||
| StudentIsApproaching = 2, | |||||
| GeneratorIsBeingFixed = 3, | |||||
| } | |||||
| } | |||||
| @@ -7,10 +7,6 @@ | |||||
| <Nullable>enable</Nullable> | <Nullable>enable</Nullable> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | |||||
| <Compile Remove="Properties\EnumType.cs" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="CommandLineParser" Version="2.9.1" /> | <PackageReference Include="CommandLineParser" Version="2.9.1" /> | ||||
| <PackageReference Include="FrameRateTask" Version="1.2.0" /> | <PackageReference Include="FrameRateTask" Version="1.2.0" /> | ||||
| @@ -4,7 +4,7 @@ start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --s | |||||
| ping -n 2 127.0.0.1 > NUL | ping -n 2 127.0.0.1 > NUL | ||||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 1 | |||||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 2 | |||||
| ping -n 2 127.0.0.1 > NUL | ping -n 2 127.0.0.1 > NUL | ||||
| @@ -154,7 +154,7 @@ | |||||
| - 子弹爆炸范围 | - 子弹爆炸范围 | ||||
| - 子弹攻击力 | - 子弹攻击力 | ||||
| - 是否可以穿墙 | - 是否可以穿墙 | ||||
| - 是否可以爆炸 | |||||
| - 是否为远程攻击 | |||||
| - 移动速度 | - 移动速度 | ||||
| - 子弹类型 | - 子弹类型 | ||||
| @@ -347,7 +347,7 @@ | |||||
| | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | ||||
| | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | ||||
| | AddSpeed | 提高移动速度,持续10s |不得分| 提高移动速度,持续10s |不得分| | | AddSpeed | 提高移动速度,持续10s |不得分| 提高移动速度,持续10s |不得分| | ||||
| | AddLifeOrAp |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | | |||||
| | AddLifeOrClairaudience |若在10s内Hp归零,该增益消失以使Hp保留100|在10s内Hp归零,得分? |10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | | |||||
| | AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | | | AddHpOrAp |回血1500000 | 回血成功 | 10秒内下一次攻击增伤1800000|10秒内有一次攻击,得分? | | ||||
| | ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| | | ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| | ||||
| | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| | | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| | ||||
| @@ -494,168 +494,13 @@ | |||||
| public int SkillCD => GameData.commonSkillCD; | public int SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => 0; | public int DurationTime => 0; | ||||
| ~~~ | ~~~ | ||||
| 使用瞬间,在视野范围内的捣蛋鬼会被眩晕(3070+ 玩家损失的血量 / 1000)ms, | |||||
| 使用瞬间,在可视范围内的使用技能状态中、攻击前后摇、开锁门、开箱的捣蛋鬼会被眩晕(3070+ 玩家损失的血量 / 1000)ms, | |||||
| ## 游戏数据 | ## 游戏数据 | ||||
| ### 基本常数 | ### 基本常数 | ||||
| ~~~csharp | |||||
| public const int numOfStepPerSecond = 20; // 每秒行走的步数 | |||||
| public const int frameDuration = 50; // 每帧时长 | |||||
| public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | |||||
| public const long gameDuration = 600000; // 游戏时长600000ms = 10min | |||||
| public const int MinSpeed = 1; // 最小速度 | |||||
| public const int MaxSpeed = int.MaxValue; // 最大速度 | |||||
| #endregion | |||||
| #region 地图相关 | |||||
| public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | |||||
| public const int lengthOfMap = 50000; // 地图长度 | |||||
| public const int rows = 50; // 行数 | |||||
| public const int cols = 50; // 列数 | |||||
| public const int numOfBirthPoint = 5; | |||||
| public const int numOfGenerator = 9; | |||||
| public const int numOfChest = 8; | |||||
| public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 | |||||
| { | |||||
| XY ret = new(x * numOfPosGridPerCell + numOfPosGridPerCell / 2, y * numOfPosGridPerCell + numOfPosGridPerCell / 2); | |||||
| return ret; | |||||
| } | |||||
| public static int PosGridToCellX(XY pos) // 求坐标所在的格子的x坐标 | |||||
| { | |||||
| return pos.x / numOfPosGridPerCell; | |||||
| } | |||||
| public static int PosGridToCellY(XY pos) // 求坐标所在的格子的y坐标 | |||||
| { | |||||
| return pos.y / numOfPosGridPerCell; | |||||
| } | |||||
| public static XY PosGridToCellXY(XY pos) // 求坐标所在的格子的Xy坐标 | |||||
| { | |||||
| return new XY(pos.x / numOfPosGridPerCell, pos.y / numOfPosGridPerCell); | |||||
| } | |||||
| ~~~ | |||||
| ### 角色相关 | |||||
| ~~~csharp | |||||
| public const int numOfStudent = 4; | |||||
| public const int characterRadius = numOfPosGridPerCell / 2 / 5 * 4; // 人物半径 | |||||
| public const int basicTreatSpeed = 100; | |||||
| public const int basicFixSpeed = 100; | |||||
| public const int basicSpeedOfOpeningOrLocking = 3280; | |||||
| public const int basicStudentSpeedOfClimbingThroughWindows = 611; | |||||
| public const int basicGhostSpeedOfClimbingThroughWindows = 1270; | |||||
| public const int basicSpeedOfOpenChest = 1000; | |||||
| public const int basicHp = 3000000; // 初始血量 | |||||
| public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间 | |||||
| public const int BeginGamingAddiction = 10003; | |||||
| public const int MidGamingAddiction = 30000; | |||||
| public const int basicTreatmentDegree = 1500000; | |||||
| public const int basicTimeOfRescue = 1000; | |||||
| public const int basicMoveSpeed = 1270; // 基本移动速度,单位:s-1 | |||||
| public const int characterMaxSpeed = 12000; // 最大速度 | |||||
| public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1 | |||||
| public const double basicConcealment = 1.0; | |||||
| public const int basicAlertnessRadius = 10700; | |||||
| public const int basicViewRange = 5 * numOfPosGridPerCell; | |||||
| public const int maxNumOfPropInPropInventory = 3; | |||||
| ~~~ | |||||
| ### 得分相关 | |||||
| ~~~csharp | |||||
| public static int TrickerScoreAttackStudent(int damage) | |||||
| { | |||||
| return damage * 100 / basicApOfGhost; | |||||
| } | |||||
| public const int TrickerScoreStudentBeAddicted = 50; | |||||
| public const int TrickerScoreStudentBeStunned = 25; | |||||
| public const int TrickerScoreStudentDie = 1000; | |||||
| public static int StudentScoreFix(int degreeOfFix) | |||||
| { | |||||
| return degreeOfFix; | |||||
| } | |||||
| public const int StudentScoreFixed = 25; | |||||
| public static int StudentScorePinDown(int timeOfPiningDown) | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| public const int StudentScoreTrickerBeStunned = 25; | |||||
| public const int StudentScoreRescue = 100; | |||||
| public static int StudentScoreTreat(int degree) | |||||
| { | |||||
| return degree; | |||||
| } | |||||
| public const int StudentScoreEscape = 1000; | |||||
| public const int ScorePropRemainHp = 20; | |||||
| public const int ScorePropUseShield = 20; | |||||
| public const int ScorePropUseSpear = 20; | |||||
| public const int ScorePropAddAp = 10; | |||||
| public const int ScorePropAddHp = 50; | |||||
| ~~~ | |||||
| ### 攻击与子弹相关 | |||||
| ~~~csharp | |||||
| public const int basicApOfGhost = 1500000; // 捣蛋鬼攻击力 | |||||
| public const int MinAP = 0; // 最小攻击力 | |||||
| public const int MaxAP = int.MaxValue; // 最大攻击力 | |||||
| public const int factorDamageGenerator = 2;//子弹对电机的破坏=factorDamageGenerator*AP; | |||||
| public const int bulletRadius = 200; // 默认子弹半径 | |||||
| public const int basicBulletNum = 3; // 基本初始子弹量 | |||||
| public const int basicCD = 3000; // 初始子弹冷却 | |||||
| public const int basicCastTime = 500;//基本前摇时间 | |||||
| public const int basicBackswing = 818;//基本后摇时间 | |||||
| public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 | |||||
| public const int basicStunnedTimeOfStudent = 4130; | |||||
| public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1 | |||||
| public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围 | |||||
| public const double basicAttackShortRange = 2700; // 基本近程攻击范围 | |||||
| public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围 | |||||
| ~~~ | |||||
| ### 技能相关 | |||||
| ~~~csharp | |||||
| public const int maxNumOfSkill = 3; | |||||
| public const int commonSkillCD = 30000; // 普通技能标准冷却时间 | |||||
| public const int commonSkillTime = 10000; // 普通技能标准持续时间 | |||||
| ~~~ | |||||
| ### 道具相关 | |||||
| ~~~csharp | |||||
| public const int MinPropTypeNum = 1; | |||||
| public const int MaxPropTypeNum = 10; | |||||
| public const int PropRadius = numOfPosGridPerCell / 2; | |||||
| public const int PropMoveSpeed = 3000; | |||||
| public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; | |||||
| public const long PropProduceTime = 20000; | |||||
| public const int PropDuration = 10000; | |||||
| public const int ApPropAdd = basicApOfGhost * 12 / 10; | |||||
| public const int ApSpearAdd = basicApOfGhost * 6 / 10; | |||||
| public const int RemainHpWhenAddLife = 100; | |||||
| public const int numOfKeyEachArea = 2; | |||||
| public const int numOfPropTypeNotKey = 4; | |||||
| public const int numOfTeachingBuilding = 3; | |||||
| ~~~ | |||||
| ### 物体相关 | |||||
| ~~~csharp | |||||
| public const int degreeOfFixedGenerator = 10300000; | |||||
| public const int degreeOfLockingOrOpeningTheDoor = 10000; | |||||
| public const int degreeOfOpeningChest = 10000; | |||||
| public const int degreeOfOpenedDoorway = 18000; | |||||
| public const int maxNumOfPropInChest = 2; | |||||
| public const int numOfGeneratorRequiredForRepair = 7; | |||||
| public const int numOfGeneratorRequiredForEmergencyExit = 3; | |||||
| ~~~ | |||||
| 请自行查看Logic/Preparation/Utility/GameData.cs | |||||
| ## 键鼠控制 | ## 键鼠控制 | ||||
| @@ -686,3 +531,4 @@ | |||||
| >>>>>>> 4219415cba0600879a5b134a4067e729c868e84b | |||||