| @@ -43,7 +43,7 @@ enum PropType // 地图中的可拾取道具类型 | |||
| { | |||
| NULL_PROP_TYPE = 0; | |||
| ADD_SPEED = 1; | |||
| ADD_LIFE_OR_AP = 2; | |||
| ADD_LIFE_OR_AP = 2;//ADD_LIFE_OR_Clairaudience | |||
| ADD_HP_OR_AP = 3; | |||
| SHIELD_OR_SPEAR = 4; | |||
| KEY3 = 5; | |||
| @@ -54,9 +54,9 @@ enum PropType // 地图中的可拾取道具类型 | |||
| enum StudentBuffType // 人类可用的增益效果类型 | |||
| { | |||
| NULL_SBUFF_TYPE = 0; | |||
| SBUFFTYPE1 = 1; | |||
| SBUFFTYPE2 = 2; | |||
| SBUFFTYPE3 = 3; | |||
| SBUFFTYPE1 = 1;//AddSpeed | |||
| SBUFFTYPE2 = 2;//AddLIFE | |||
| SBUFFTYPE3 = 3;//Shield | |||
| SBUFFTYPE4 = 4; | |||
| } | |||
| @@ -86,10 +86,11 @@ enum PlayerState | |||
| enum TrickerBuffType // 屠夫可用的增益效果类型 | |||
| { | |||
| 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,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。 | |||
| @@ -114,7 +115,7 @@ enum TrickerType | |||
| { | |||
| NULL_TRICKER_TYPE = 0; | |||
| ASSASSIN = 1; | |||
| TRICKERTYPE2 = 2; | |||
| TRICKERTYPE2 = 2;//KLEE | |||
| TRICKERTYPE3 = 3; | |||
| TRICKERTYPE4 = 4; | |||
| } | |||
| @@ -23,9 +23,9 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| 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 RecoveryFromHit => GameData.basicRecoveryFromHit; | |||
| public const int cd = GameData.basicBackswing; | |||
| @@ -68,11 +68,11 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| 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 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 override int CD => cd; | |||
| @@ -94,4 +94,95 @@ namespace GameClass.GameObj | |||
| 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 int AP => 7220; | |||
| public override int Speed => 0; | |||
| public override bool IsToBomb => false; | |||
| public override bool IsRemoteAttack => false; | |||
| public override int CastTime => 0; | |||
| public override int Backswing => 0; | |||
| public override int RecoveryFromHit => 0; | |||
| @@ -13,7 +13,7 @@ namespace GameClass.GameObj | |||
| public abstract double BulletAttackRange { get; } | |||
| public abstract int AP { get; set; } | |||
| public abstract int Speed { get; } | |||
| public abstract bool IsToBomb { get; } | |||
| public abstract bool IsRemoteAttack { get; } | |||
| public abstract int CastTime { get; } | |||
| public abstract int Backswing { get; } | |||
| public abstract int RecoveryFromHit { get; } | |||
| @@ -63,6 +63,10 @@ namespace GameClass.GameObj | |||
| return new FlyingKnife(character, place, pos); | |||
| case BulletType.CommonAttackOfGhost: | |||
| 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: | |||
| return null; | |||
| } | |||
| @@ -71,10 +75,6 @@ namespace GameClass.GameObj | |||
| { | |||
| switch (bulletType) | |||
| { | |||
| case BulletType.AtomBomb: | |||
| case BulletType.LineBullet: | |||
| case BulletType.FastBullet: | |||
| case BulletType.OrdinaryBullet: | |||
| case BulletType.FlyingKnife: | |||
| default: | |||
| return GameData.bulletRadius; | |||
| @@ -88,10 +88,10 @@ namespace GameClass.GameObj | |||
| return CommonAttackOfGhost.cd; | |||
| case BulletType.FlyingKnife: | |||
| 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: | |||
| return GameData.basicCD; | |||
| } | |||
| @@ -66,6 +66,12 @@ namespace GameClass.GameObj | |||
| case CharacterType.Assassin: | |||
| this.occupation = new Assassin(); | |||
| break; | |||
| case CharacterType.Teacher: | |||
| this.occupation = new Teacher(); | |||
| break; | |||
| case CharacterType.Klee: | |||
| this.occupation = new Klee(); | |||
| break; | |||
| case CharacterType.Athlete: | |||
| default: | |||
| this.occupation = new Athlete(); | |||
| @@ -82,7 +88,7 @@ namespace GameClass.GameObj | |||
| this.characterType = characterType; | |||
| this.SpeedOfOpeningOrLocking = Occupation.TimeOfOpeningOrLocking; | |||
| this.SpeedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows; | |||
| this.SpeedOfOpenChest = Occupation.TimeOfOpenChest; | |||
| this.SpeedOfOpenChest = Occupation.SpeedOfOpenChest; | |||
| foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | |||
| { | |||
| @@ -47,7 +47,8 @@ namespace GameClass.GameObj | |||
| lock (gameObjLock) | |||
| { | |||
| bulletOfPlayer = value; | |||
| CD = BulletFactory.BulletCD(value); | |||
| OrgCD = (BulletFactory.BulletCD(value)); | |||
| CD = 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -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(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| @@ -132,6 +132,8 @@ namespace GameClass.GameObj | |||
| return new CanBeginToCharge(); | |||
| case ActiveSkillType.Punish: | |||
| return new Punish(); | |||
| case ActiveSkillType.JumpyBomb: | |||
| return new JumpyBomb(); | |||
| default: | |||
| return new NullSkill(); | |||
| } | |||
| @@ -149,6 +151,8 @@ namespace GameClass.GameObj | |||
| return ActiveSkillType.CanBeginToCharge; | |||
| case Punish: | |||
| return ActiveSkillType.Punish; | |||
| case JumpyBomb: | |||
| return ActiveSkillType.JumpyBomb; | |||
| default: | |||
| return ActiveSkillType.Null; | |||
| } | |||
| @@ -52,13 +52,13 @@ namespace GameClass.GameObj | |||
| /// <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) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.AddLifeOrAp; | |||
| public override PropType GetPropType() => PropType.AddLifeOrClairaudience; | |||
| } | |||
| public sealed class AddHpOrAp : Prop | |||
| { | |||
| @@ -141,8 +141,8 @@ namespace GameClass.GameObj | |||
| { | |||
| case PropType.AddSpeed: | |||
| return new AddSpeed(pos, place); | |||
| case PropType.AddLifeOrAp: | |||
| return new AddLifeOrAp(pos, place); | |||
| case PropType.AddLifeOrClairaudience: | |||
| return new AddLifeOrClairaudience(pos, place); | |||
| case PropType.ShieldOrSpear: | |||
| return new ShieldOrSpear(pos, place); | |||
| 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 (AttackManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | |||
| @@ -495,7 +503,7 @@ namespace Gaming | |||
| gameMap: gameMap, | |||
| OnCollision: (obj, collisionObj, moveVec) => | |||
| { | |||
| SkillWhenMove((Character)obj, collisionObj); | |||
| SkillWhenColliding((Character)obj, collisionObj); | |||
| //if (collisionObj is Mine) | |||
| //{ | |||
| // ActivateMine((Character)obj, (Mine)collisionObj); | |||
| @@ -33,7 +33,7 @@ namespace Gaming | |||
| Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | |||
| #endif | |||
| if (obj.CanMove) | |||
| if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty) | |||
| BulletBomb((Bullet)obj, null); | |||
| } | |||
| ); | |||
| @@ -124,10 +124,6 @@ namespace Gaming | |||
| gameMap.GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); | |||
| } | |||
| } | |||
| // player.Reset(); | |||
| // ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 | |||
| } | |||
| private void BombObj(Bullet bullet, GameObj objBeingShot) | |||
| @@ -174,10 +170,10 @@ namespace Gaming | |||
| #endif | |||
| bullet.CanMove = false; | |||
| if (gameMap.Remove(bullet) && bullet.IsToBomb) | |||
| if (gameMap.Remove(bullet) && bullet.BulletBombRange > 0) | |||
| gameMap.Add(new BombedBullet(bullet)); | |||
| if (!bullet.IsToBomb) | |||
| if (bullet.BulletBombRange == 0) | |||
| { | |||
| if (objBeingShot == null) | |||
| { | |||
| @@ -201,7 +197,14 @@ namespace Gaming | |||
| 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); | |||
| if (bullet.RecoveryFromHit > 0) | |||
| { | |||
| @@ -304,7 +307,7 @@ namespace Gaming | |||
| beAttackedList.Clear(); | |||
| } | |||
| public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头) | |||
| public bool Attack(Character? player, double angle) | |||
| { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | |||
| if (player == null) | |||
| { | |||
| @@ -31,10 +31,10 @@ namespace Gaming | |||
| player.AddSpear(GameData.PropDuration); | |||
| else player.AddShield(GameData.PropDuration); | |||
| break; | |||
| case PropType.AddLifeOrAp: | |||
| case PropType.AddLifeOrClairaudience: | |||
| if (!player.IsGhost()) | |||
| player.AddLIFE(GameData.PropDuration); | |||
| else player.AddAp(GameData.PropDuration); | |||
| else player.AddClairaudience(GameData.PropDuration); | |||
| break; | |||
| case PropType.AddSpeed: | |||
| player.AddMoveSpeed(GameData.PropDuration); | |||
| @@ -36,7 +36,7 @@ namespace Gaming | |||
| return ActiveSkillEffect(skill, player, () => | |||
| { | |||
| player.AddMoveSpeed(skill.DurationTime, 3.0); | |||
| //See SkillWhenMove in ActionManager | |||
| //See SkillWhenColliding in ActionManager | |||
| }, | |||
| () => | |||
| { }); | |||
| @@ -55,12 +55,12 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| 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; }); | |||
| @@ -92,8 +92,8 @@ namespace Gaming | |||
| || player.PlayerState == PlayerStateType.UsingSkill || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || player.PlayerState == PlayerStateType.OpeningTheChest) | |||
| && 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; | |||
| } | |||
| } | |||
| @@ -28,6 +28,9 @@ namespace Gaming | |||
| case ActiveSkillType.Punish: | |||
| Punish(character); | |||
| break; | |||
| case ActiveSkillType.JumpyBomb: | |||
| JumpyBomb(character); | |||
| break; | |||
| default: | |||
| return false; | |||
| } | |||
| @@ -11,6 +11,8 @@ namespace Preparation.Interface | |||
| public void AddScore(int add); | |||
| public double Vampire { get; } | |||
| public PlayerStateType PlayerState { get; set; } | |||
| public BulletType BulletOfPlayer { get; set; } | |||
| public bool IsGhost(); | |||
| } | |||
| } | |||
| @@ -16,7 +16,7 @@ namespace Preparation.Interface | |||
| public int ViewRange { get; } | |||
| public int TimeOfOpeningOrLocking { get; } | |||
| public int SpeedOfClimbingThroughWindows { get; } | |||
| public int TimeOfOpenChest { get; } | |||
| public int SpeedOfOpenChest { get; } | |||
| } | |||
| public interface IGhost : IOccupation | |||
| @@ -32,7 +32,7 @@ namespace Preparation.Interface | |||
| 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; | |||
| private const int maxHp = GameData.basicHp; | |||
| @@ -61,12 +61,12 @@ namespace Preparation.Interface | |||
| public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows; | |||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int TimeOfOpenChest => timeOfOpenChest; | |||
| public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||
| } | |||
| public class HoD : IGhost | |||
| public class Klee : IGhost | |||
| { | |||
| private const int moveSpeed = GameData.basicMoveSpeed * 473 / 380; | |||
| private const int moveSpeed = (int)(GameData.basicMoveSpeed * 155 / 127); | |||
| public int MoveSpeed => moveSpeed; | |||
| private const int maxHp = GameData.basicHp; | |||
| @@ -77,26 +77,26 @@ namespace Preparation.Interface | |||
| public BulletType InitBullet => BulletType.CommonAttackOfGhost; | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.BecomeInvisible, ActiveSkillType.UseKnife }); | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||
| public double concealment = GameData.basicConcealment * 1.5; | |||
| public double concealment = GameData.basicConcealment; | |||
| public double Concealment => concealment; | |||
| public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.3); | |||
| public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.069); | |||
| public int AlertnessRadius => alertnessRadius; | |||
| public int viewRange = (int)(GameData.basicViewRange * 1.3); | |||
| public int viewRange = (int)(GameData.basicViewRange * 1.1); | |||
| public int ViewRange => viewRange; | |||
| public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; | |||
| public int timeOfOpeningOrLocking = (int)(GameData.basicSpeedOfOpeningOrLocking / 1.1); | |||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||
| public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows; | |||
| public int speedOfClimbingThroughWindows = (int)(GameData.basicGhostSpeedOfClimbingThroughWindows / 1.1); | |||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| public int TimeOfOpenChest => timeOfOpenChest; | |||
| public int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1); | |||
| public int SpeedOfOpenChest => speedOfOpenChest; | |||
| } | |||
| public class Teacher : IStudent | |||
| { | |||
| @@ -138,8 +138,8 @@ namespace Preparation.Interface | |||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows / 2; | |||
| 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 | |||
| { | |||
| @@ -181,7 +181,7 @@ namespace Preparation.Interface | |||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10; | |||
| 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 // 子弹类型 | |||
| { | |||
| Null = 0, | |||
| OrdinaryBullet = 1, // 普通子弹 | |||
| AtomBomb = 2, // 原子弹 | |||
| FastBullet = 3, // 快速子弹 | |||
| LineBullet = 4, // 直线子弹 | |||
| FlyingKnife = 5, //飞刀 | |||
| CommonAttackOfGhost = 6, | |||
| FlyingKnife = 1, //飞刀 | |||
| CommonAttackOfGhost = 2, | |||
| JumpyDumpty = 3, | |||
| BombBomb = 4, | |||
| // Ram = 7, | |||
| } | |||
| public enum PropType // 道具类型 | |||
| { | |||
| 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 // 职业 | |||
| { | |||
| Null = 0, | |||
| Assassin = 1, | |||
| Athlete = 2, | |||
| RecoverAfterBattle = 3, | |||
| Klee = 3, | |||
| SpeedUpWhenLeavingGrass = 4, | |||
| Teacher = 5, | |||
| PSkill5 = 6 | |||
| @@ -87,7 +86,7 @@ namespace Preparation.Utility | |||
| Null = 0, | |||
| BecomeInvisible = 1, | |||
| BecomeVampire = 2, | |||
| NuclearWeapon = 3, | |||
| JumpyBomb = 3, | |||
| SuperFast = 4, | |||
| UseKnife = 5, | |||
| CanBeginToCharge = 6, | |||
| @@ -35,6 +35,14 @@ namespace Preparation.Utility | |||
| { | |||
| 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) // 求格子的中心坐标 | |||
| { | |||
| @@ -106,6 +114,7 @@ namespace Preparation.Utility | |||
| return characterType switch | |||
| { | |||
| CharacterType.Assassin => true, | |||
| CharacterType.Klee=> true, | |||
| _ => false, | |||
| }; | |||
| } | |||
| @@ -161,13 +170,13 @@ namespace Preparation.Utility | |||
| public const int basicCD = 3000; // 初始子弹冷却 | |||
| public const int basicCastTime = 500;//基本前摇时间 | |||
| public const int basicBackswing = 818;//基本后摇时间 | |||
| public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 | |||
| public const int basicRecoveryFromHit = 3700;//基本命中攻击恢复时长 | |||
| 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 | |||
| #region 技能相关 | |||
| public const int maxNumOfSkill = 3; | |||
| @@ -183,7 +192,7 @@ namespace Preparation.Utility | |||
| /// Punish | |||
| /// </summary> | |||
| public const int TimeOfGhostFaintingWhenPunish = 3070; | |||
| public const int TimeFactorOfGhostFainting = 1000; | |||
| public const int timeFactorOfGhostFainting = 250; | |||
| #endregion | |||
| #region 道具相关 | |||
| public const int MinPropTypeNum = 1; | |||
| @@ -50,7 +50,7 @@ namespace Server | |||
| { | |||
| case Preparation.Utility.PropType.AddSpeed: | |||
| return Protobuf.PropType.AddSpeed; | |||
| case Preparation.Utility.PropType.AddLifeOrAp: | |||
| case Preparation.Utility.PropType.AddLifeOrClairaudience: | |||
| return Protobuf.PropType.AddLifeOrAp; | |||
| case Preparation.Utility.PropType.AddHpOrAp: | |||
| return Protobuf.PropType.AddHpOrAp; | |||
| @@ -74,7 +74,7 @@ namespace Server | |||
| case Protobuf.PropType.AddSpeed: | |||
| return Preparation.Utility.PropType.AddSpeed; | |||
| case Protobuf.PropType.AddLifeOrAp: | |||
| return Preparation.Utility.PropType.AddLifeOrAp; | |||
| return Preparation.Utility.PropType.AddLifeOrClairaudience; | |||
| case Protobuf.PropType.AddHpOrAp: | |||
| return Preparation.Utility.PropType.AddHpOrAp; | |||
| case Protobuf.PropType.ShieldOrSpear: | |||
| @@ -195,6 +195,8 @@ namespace Server | |||
| { | |||
| case Preparation.Utility.CharacterType.Assassin: | |||
| return Protobuf.TrickerType.Assassin; | |||
| case Preparation.Utility.CharacterType.Klee: | |||
| return Protobuf.TrickerType._2; | |||
| default: | |||
| return Protobuf.TrickerType.NullTrickerType; | |||
| } | |||
| @@ -206,6 +208,8 @@ namespace Server | |||
| { | |||
| case Protobuf.TrickerType.Assassin: | |||
| return Preparation.Utility.CharacterType.Assassin; | |||
| case Protobuf.TrickerType._2: | |||
| return Preparation.Utility.CharacterType.Klee; | |||
| default: | |||
| return Preparation.Utility.CharacterType.Null; | |||
| } | |||
| @@ -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 | |||
| 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 | |||
| @@ -154,7 +154,7 @@ | |||
| - 子弹爆炸范围 | |||
| - 子弹攻击力 | |||
| - 是否可以穿墙 | |||
| - 是否可以爆炸 | |||
| - 是否为远程攻击 | |||
| - 移动速度 | |||
| - 子弹类型 | |||
| @@ -347,7 +347,7 @@ | |||
| | 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] | | |||
| | :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------| | |||
| | 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秒内有一次攻击,得分? | | |||
| | ShieldOrSpear | 10秒内能抵挡一次伤害 | 10秒内成功抵挡一次伤害 |10秒内下一次攻击能破盾,如果对方无盾,则增伤900000| 10秒内攻击中学生| | |||
| | Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分| | |||
| @@ -494,165 +494,9 @@ | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| 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 | |||