| @@ -42,11 +42,13 @@ enum ShapeType // 形状类型 | |||
| enum PropType // 地图中的可拾取道具类型 | |||
| { | |||
| NULL_PROP_TYPE = 0; | |||
| KEY3 = 1; | |||
| KEY5 = 2; | |||
| KEY6 = 3; | |||
| PTYPE4 = 4; | |||
| ADD_SPEED = 1; | |||
| ADD_LIFE_OR_AP = 2; | |||
| ADD_HP_OR_AP = 3; | |||
| SHIELD_OR_SPEAR = 4; | |||
| KEY3 = 5; | |||
| KEY5 = 6; | |||
| KEY6 = 7; | |||
| } | |||
| enum StudentBuffType // 人类可用的增益效果类型 | |||
| @@ -12,7 +12,16 @@ namespace GameClass.GameObj | |||
| } | |||
| public override double BulletBombRange => 0; | |||
| public override double BulletAttackRange => GameData.basicAttackShortRange; | |||
| public override int AP => GameData.basicApOfGhost; | |||
| public int ap = GameData.basicApOfGhost; | |||
| public override int AP | |||
| { | |||
| get => ap; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| ap = value; | |||
| } | |||
| } | |||
| public override int Speed => GameData.basicBulletMoveSpeed; | |||
| public override bool IsToBomb => false; | |||
| @@ -42,7 +51,16 @@ namespace GameClass.GameObj | |||
| } | |||
| public override double BulletBombRange => 0; | |||
| public override double BulletAttackRange => GameData.basicRemoteAttackRange * 13; | |||
| public override int AP => GameData.basicApOfGhost * 4 / 5; | |||
| public int ap = GameData.basicApOfGhost * 4 / 5; | |||
| public override int AP | |||
| { | |||
| get => ap; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| ap = value; | |||
| } | |||
| } | |||
| public override int Speed => GameData.basicBulletMoveSpeed * 2; | |||
| public override bool IsToBomb => false; | |||
| @@ -65,176 +83,4 @@ namespace GameClass.GameObj | |||
| public override BulletType TypeOfBullet => BulletType.FlyingKnife; | |||
| } | |||
| internal sealed class AtomBomb : Bullet | |||
| { | |||
| public AtomBomb(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange * 7 / 3; | |||
| public override double BulletAttackRange => GameData.basicAttackShortRange * 7 / 9; | |||
| public override int AP => GameData.basicApOfGhost * 7 / 3; | |||
| public override int Speed => GameData.basicBulletMoveSpeed * 2 / 3; | |||
| public override int CastTime => GameData.basicCastTime; | |||
| 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 IsToBomb => true; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override bool CanBeBombed(GameObjType gameObjType) | |||
| { | |||
| if (gameObjType == GameObjType.Character) return true; | |||
| return false; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.AtomBomb; | |||
| } | |||
| internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 | |||
| { | |||
| public OrdinaryBullet(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange * 5 / 6; | |||
| public override double BulletAttackRange => GameData.basicAttackShortRange / 2; | |||
| public override int AP => GameData.basicApOfGhost * 5 / 6; | |||
| public override int Speed => GameData.basicBulletMoveSpeed * 5 / 6; | |||
| public override int CastTime => GameData.basicCastTime; | |||
| 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 IsToBomb => true; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override bool CanBeBombed(GameObjType gameObjType) | |||
| { | |||
| if (gameObjType == GameObjType.Character) return true; | |||
| return false; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.OrdinaryBullet; | |||
| } | |||
| internal sealed class FastBullet : Bullet // 1倍攻击范围,0.2倍攻击力,2倍速 | |||
| { | |||
| public FastBullet(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange * 2 / 4; | |||
| public override double BulletAttackRange => GameData.basicAttackShortRange; | |||
| public override int AP => (int)(0.5 * GameData.basicApOfGhost); | |||
| public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3; | |||
| public override int CastTime => GameData.basicCastTime; | |||
| 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 IsToBomb => true; | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| // 圆形攻击范围 | |||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||
| } | |||
| public override bool CanBeBombed(GameObjType gameObjType) | |||
| { | |||
| if (gameObjType == GameObjType.Character) return true; | |||
| return false; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.FastBullet; | |||
| } | |||
| internal sealed class LineBullet : Bullet // 直线爆炸,宽度1格,长度为2倍爆炸范围 | |||
| { | |||
| public LineBullet(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange * 4 / 3; | |||
| public override double BulletAttackRange => 0.1 * GameData.basicAttackShortRange; | |||
| public override int AP => GameData.basicApOfGhost * 2 / 3; | |||
| public override int Speed => GameData.basicBulletMoveSpeed / 3; | |||
| public override int CastTime => GameData.basicCastTime; | |||
| 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 IsToBomb => true; | |||
| public override bool CanBeBombed(GameObjType gameObjType) | |||
| { | |||
| if (gameObjType == GameObjType.Character) return true; | |||
| return false; | |||
| } | |||
| public override bool CanAttack(GameObj target) | |||
| { | |||
| double FacingAngle = Math.Atan2(this.FacingDirection.y, this.FacingDirection.x); | |||
| if (Math.Abs(FacingAngle - Math.PI / 2) < 1e-2) | |||
| { | |||
| if (target.Position.y - this.Position.y > BulletBombRange) | |||
| return false; | |||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle - Math.PI * 3 / 2) < 1e-2) | |||
| { | |||
| if (target.Position.y - this.Position.y < -BulletBombRange) | |||
| return false; | |||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle) < 1e-2) | |||
| { | |||
| if (target.Position.x - this.Position.x > BulletBombRange) | |||
| return false; | |||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| else if (Math.Abs(FacingAngle - Math.PI) < 1e-2) | |||
| { | |||
| if (target.Position.x - this.Position.x < -BulletBombRange) | |||
| return false; | |||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||
| return true; | |||
| return false; | |||
| } | |||
| double vertical = Math.Tan(FacingAngle + Math.PI / 2); | |||
| bool posValue = vertical * Math.Cos(FacingAngle) - Math.Sin(FacingAngle) > 0; | |||
| double dist; | |||
| dist = vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y) / Math.Sqrt(1 + vertical * vertical); | |||
| if (Math.Abs(dist) > BulletBombRange) | |||
| return false; | |||
| else if (dist < 0 && posValue) // 位于直线两侧 | |||
| return false; | |||
| vertical = Math.Tan(FacingAngle); | |||
| dist = Math.Abs(vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y)) / Math.Sqrt(1 + vertical * vertical); | |||
| if (dist > GameData.numOfPosGridPerCell / 2) | |||
| return false; | |||
| return true; | |||
| } | |||
| public override BulletType TypeOfBullet => BulletType.LineBullet; | |||
| } | |||
| } | |||
| } | |||
| @@ -11,7 +11,7 @@ namespace GameClass.GameObj | |||
| /// </summary> | |||
| public abstract double BulletBombRange { get; } | |||
| public abstract double BulletAttackRange { get; } | |||
| public abstract int AP { get; } | |||
| public abstract int AP { get; set; } | |||
| public abstract int Speed { get; } | |||
| public abstract bool IsToBomb { get; } | |||
| public abstract int CastTime { get; } | |||
| @@ -63,14 +63,6 @@ namespace GameClass.GameObj | |||
| return new FlyingKnife(character, place, pos); | |||
| case BulletType.CommonAttackOfGhost: | |||
| return new CommonAttackOfGhost(character, place, pos); | |||
| case BulletType.AtomBomb: | |||
| return new AtomBomb(character, place, pos); | |||
| case BulletType.LineBullet: | |||
| return new LineBullet(character, place, pos); | |||
| case BulletType.FastBullet: | |||
| return new FastBullet(character, place, pos); | |||
| case BulletType.OrdinaryBullet: | |||
| return new OrdinaryBullet(character, place, pos); | |||
| default: | |||
| return null; | |||
| } | |||
| @@ -42,16 +42,18 @@ namespace GameClass.GameObj | |||
| private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc) | |||
| { | |||
| LinkedListNode<BuffValue> buffNode; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||
| } | |||
| ReCalculateFunc(); | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| LinkedListNode<BuffValue> buffNode; | |||
| lock (buffListLock[(int)buffType]) | |||
| { | |||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||
| } | |||
| ReCalculateFunc(); | |||
| Thread.Sleep(buffTime); | |||
| try | |||
| { | |||
| @@ -64,6 +66,7 @@ namespace GameClass.GameObj | |||
| { | |||
| } | |||
| ReCalculateFunc(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| @@ -106,6 +109,42 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| public bool TryUseShield() | |||
| { | |||
| if (HasShield) | |||
| { | |||
| lock (buffListLock[(int)BuffType.Shield]) | |||
| { | |||
| buffList[(int)BuffType.Shield].RemoveFirst(); | |||
| } | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public void AddAp(int time) => AddBuff(new BuffValue(), time, BuffType.AddAp, () => { }); | |||
| public bool HasAp | |||
| { | |||
| get | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddAp]) | |||
| { | |||
| return buffList[(int)BuffType.AddAp].Count != 0; | |||
| } | |||
| } | |||
| } | |||
| public bool TryAddAp() | |||
| { | |||
| if (HasAp) | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddAp]) | |||
| { | |||
| buffList[(int)BuffType.AddAp].RemoveFirst(); | |||
| } | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () => | |||
| { }); | |||
| @@ -125,7 +164,7 @@ namespace GameClass.GameObj | |||
| { | |||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||
| { | |||
| buffList[(int)BuffType.AddLIFE].Clear(); | |||
| buffList[(int)BuffType.AddLIFE].RemoveFirst(); | |||
| } | |||
| return true; | |||
| } | |||
| @@ -144,6 +183,7 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 清除所有buff | |||
| /// </summary> | |||
| @@ -22,16 +22,22 @@ namespace GameClass.GameObj | |||
| return false; // 原来已经死了 | |||
| if (bullet.Parent.TeamID != this.TeamID) | |||
| { | |||
| if (HasShield) | |||
| if (TryUseShield()) | |||
| { | |||
| if (bullet.HasSpear) | |||
| bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(TrySubHp(bullet.AP))); | |||
| { | |||
| int subHp = TrySubHp(bullet.AP); | |||
| bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear); | |||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||
| } | |||
| else | |||
| return false; | |||
| } | |||
| else | |||
| { | |||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * TrySubHp(bullet.AP))); | |||
| int subHp = TrySubHp(bullet.AP + GameData.ApSpearAdd); | |||
| bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp)); | |||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||
| } | |||
| #if DEBUG | |||
| Console.WriteLine($"PlayerID:{ID} is being shot! Now his hp is {hp}."); | |||
| @@ -483,6 +483,9 @@ namespace GameClass.GameObj | |||
| public void AddLIFE(int LIFETime) => buffManager.AddLIFE(LIFETime); | |||
| public bool HasLIFE => buffManager.HasLIFE; | |||
| public void AddAp(int time) => buffManager.AddAp(time); | |||
| public bool HasAp => buffManager.HasAp; | |||
| public void AddSpear(int spearTime) => buffManager.AddSpear(spearTime); | |||
| public bool HasSpear => buffManager.HasSpear; | |||
| @@ -520,9 +523,22 @@ namespace GameClass.GameObj | |||
| { | |||
| if (buffManager.TryActivatingLIFE()) | |||
| { | |||
| hp = MaxHp; | |||
| AddScore(GameData.ScorePropRemainHp); | |||
| hp = GameData.RemainHpWhenAddLife; | |||
| } | |||
| } | |||
| public bool TryAddAp() | |||
| { | |||
| AddScore(GameData.ScorePropAddAp); | |||
| return buffManager.TryAddAp(); | |||
| } | |||
| public bool TryUseShield() | |||
| { | |||
| AddScore(GameData.ScorePropUseShield); | |||
| return buffManager.TryUseShield(); | |||
| } | |||
| #endregion | |||
| /* public override void Reset() // 要加锁吗? | |||
| { | |||
| @@ -47,38 +47,36 @@ namespace GameClass.GameObj | |||
| base(initPos, placeType) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.addSpeed; | |||
| public override PropType GetPropType() => PropType.AddSpeed; | |||
| } | |||
| /// <summary> | |||
| /// 复活甲 | |||
| /// </summary> | |||
| public sealed class AddLIFE : Prop | |||
| public sealed class AddLifeOrAp : Prop | |||
| { | |||
| public AddLIFE(XY initPos, PlaceType placeType) : | |||
| public AddLifeOrAp(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.addLIFE; | |||
| public override PropType GetPropType() => PropType.AddLifeOrAp; | |||
| } | |||
| /// <summary> | |||
| /// 护盾 | |||
| /// </summary> | |||
| public sealed class Shield : Prop | |||
| public sealed class AddHpOrAp : Prop | |||
| { | |||
| public Shield(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public AddHpOrAp(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Shield; | |||
| public override PropType GetPropType() => PropType.AddHpOrAp; | |||
| } | |||
| /// <summary> | |||
| /// 矛 | |||
| /// 矛盾 | |||
| /// </summary> | |||
| public sealed class Spear : Prop | |||
| public sealed class ShieldOrSpear : Prop | |||
| { | |||
| public Spear(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public ShieldOrSpear(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Spear; | |||
| public override PropType GetPropType() => PropType.ShieldOrSpear; | |||
| } | |||
| public sealed class Key3 : Prop | |||
| { | |||
| @@ -135,4 +133,29 @@ namespace GameClass.GameObj | |||
| // public override PropType GetPropType() => PropType.addCD; | |||
| // } | |||
| // #endregion | |||
| public static class PropFactory | |||
| { | |||
| public static Prop GetProp(PropType propType, XY pos, PlaceType place) | |||
| { | |||
| switch (propType) | |||
| { | |||
| case PropType.AddSpeed: | |||
| return new AddSpeed(pos, place); | |||
| case PropType.AddLifeOrAp: | |||
| return new AddLifeOrAp(pos, place); | |||
| case PropType.ShieldOrSpear: | |||
| return new ShieldOrSpear(pos, place); | |||
| case PropType.AddHpOrAp: | |||
| return new AddHpOrAp(pos, place); | |||
| case PropType.Key3: | |||
| return new Key3(pos, place); | |||
| case PropType.Key5: | |||
| return new Key5(pos, place); | |||
| case PropType.Key6: | |||
| return new Key6(pos, place); | |||
| default: | |||
| return new NullProp(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -70,27 +70,15 @@ namespace Gaming | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void BeStunned(Character player, int time) | |||
| public static void BeStunned(Character player, int time) | |||
| { | |||
| new Thread | |||
| (() => | |||
| { | |||
| player.PlayerState = PlayerStateType.Stunned; | |||
| new FrameRateTaskExecutor<int>( | |||
| () => player.PlayerState == PlayerStateType.Stunned && gameMap.Timer.IsGaming, | |||
| () => | |||
| { | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| () => | |||
| { | |||
| if (player.PlayerState == PlayerStateType.Stunned) | |||
| player.PlayerState = PlayerStateType.Null; | |||
| return 0; | |||
| }, | |||
| maxTotalDuration: time | |||
| ) | |||
| .Start(); | |||
| Thread.Sleep(time); | |||
| if (player.PlayerState == PlayerStateType.Stunned) | |||
| player.PlayerState = PlayerStateType.Null; | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| @@ -149,20 +137,8 @@ namespace Gaming | |||
| } | |||
| if (oneBeAttacked.CanBeAwed()) | |||
| { | |||
| oneBeAttacked.PlayerState = PlayerStateType.Stunned; | |||
| bullet.Parent.AddScore(GameData.TrickerScoreStudentBeStunned); | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| Thread.Sleep(GameData.basicStunnedTimeOfStudent); | |||
| if (oneBeAttacked.PlayerState == PlayerStateType.Stunned) | |||
| { | |||
| oneBeAttacked.PlayerState = PlayerStateType.Null; | |||
| } | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| BeStunned(oneBeAttacked, GameData.basicStunnedTimeOfStudent); | |||
| } | |||
| } | |||
| // if (((Character)objBeingShot).IsGhost() && !bullet.Parent.IsGhost() && bullet.TypeOfBullet == BulletType.Ram) | |||
| @@ -333,11 +309,11 @@ namespace Gaming | |||
| if (bullet != null) | |||
| { | |||
| bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0; | |||
| bullet.CanMove = true; | |||
| gameMap.Add(bullet); | |||
| moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | |||
| if (bullet.CastTime > 0) | |||
| { | |||
| player.PlayerState = PlayerStateType.TryingToAttack; | |||
| @@ -28,18 +28,24 @@ namespace Gaming | |||
| Prop prop = player.UseProp(indexing); | |||
| switch (prop.GetPropType()) | |||
| { | |||
| case PropType.Spear: | |||
| player.AddSpear(GameData.PropDuration); | |||
| case PropType.ShieldOrSpear: | |||
| if (player.IsGhost()) | |||
| player.AddSpear(GameData.PropDuration); | |||
| else player.AddShield(GameData.PropDuration); | |||
| break; | |||
| case PropType.Shield: | |||
| player.AddShield(GameData.PropDuration); | |||
| case PropType.AddLifeOrAp: | |||
| if (!player.IsGhost()) | |||
| player.AddLIFE(GameData.PropDuration); | |||
| else player.AddAp(GameData.PropDuration); | |||
| break; | |||
| case PropType.addLIFE: | |||
| player.AddLIFE(GameData.PropDuration); | |||
| break; | |||
| case PropType.addSpeed: | |||
| case PropType.AddSpeed: | |||
| player.AddMoveSpeed(GameData.PropDuration); | |||
| break; | |||
| case PropType.AddHpOrAp: | |||
| if (!player.IsGhost()) | |||
| player.HP += GameData.basicTreatmentDegree; | |||
| else player.AddAp(GameData.PropDuration); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| @@ -110,19 +116,7 @@ namespace Gaming | |||
| private Prop ProduceOnePropNotKey(Random r, XY Pos) | |||
| { | |||
| switch (r.Next(0, GameData.numOfPropTypeNotKey)) | |||
| { | |||
| case 0: | |||
| return new AddLIFE(Pos, gameMap.GetPlaceType(Pos)); | |||
| case 1: | |||
| return new AddSpeed(Pos, gameMap.GetPlaceType(Pos)); | |||
| case 2: | |||
| return new Shield(Pos, gameMap.GetPlaceType(Pos)); | |||
| case 3: | |||
| return new Spear(Pos, gameMap.GetPlaceType(Pos)); | |||
| default: | |||
| return new NullProp(); | |||
| } | |||
| return PropFactory.GetProp((PropType)r.Next(0, GameData.numOfPropTypeNotKey), Pos, gameMap.GetPlaceType(Pos)); | |||
| } | |||
| private Chest GetChest(Random r) | |||
| @@ -49,8 +49,9 @@ namespace Gaming | |||
| { | |||
| if (character.IsGhost() != player.IsGhost() && XY.Distance(player.Position + new XY(player.FacingDirection, player.Radius), character.Position) <= character.Radius) | |||
| { | |||
| attackManager.BeStunned(character, GameData.TimeOfGhostFainting); | |||
| attackManager.BeStunned(player, GameData.TimeOfStudentFainting); | |||
| AttackManager.BeStunned(character, GameData.TimeOfGhostFainting); | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned); | |||
| AttackManager.BeStunned(player, GameData.TimeOfStudentFainting); | |||
| break; | |||
| } | |||
| } | |||
| @@ -79,25 +79,25 @@ namespace Preparation.Interface | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.CanBeginToCharge }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||
| public const int fixSpeed = GameData.basicFixSpeed * 6 / 10; | |||
| public const int fixSpeed = 0; | |||
| public int FixSpeed => fixSpeed; | |||
| public const int treatSpeed = GameData.basicTreatSpeed * 8 / 10; | |||
| public const int treatSpeed = GameData.basicTreatSpeed; | |||
| public int TreatSpeed => treatSpeed; | |||
| public const double concealment = GameData.basicConcealment * 0.9; | |||
| public const double concealment = GameData.basicConcealment * 0.5; | |||
| public double Concealment => concealment; | |||
| public const int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9); | |||
| public const int alertnessRadius = GameData.basicAlertnessRadius / 2; | |||
| public int AlertnessRadius => alertnessRadius; | |||
| public int viewRange = (int)(GameData.basicViewRange * 1.1); | |||
| public int viewRange = GameData.basicViewRange * 9 / 10; | |||
| public int ViewRange => viewRange; | |||
| public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking * 12 / 10; | |||
| public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; | |||
| public int TimeOfOpeningOrLocking => timeOfOpeningOrLocking; | |||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10; | |||
| public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 9 / 10; | |||
| public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; | |||
| public int timeOfOpenChest = GameData.basicSpeedOfOpenChest; | |||
| @@ -116,7 +116,7 @@ namespace Preparation.Interface | |||
| public BulletType InitBullet => BulletType.Null; | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.CanBeginToCharge }); | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||
| public const int fixSpeed = GameData.basicFixSpeed * 6 / 10; | |||
| @@ -64,10 +64,10 @@ namespace Preparation.Utility | |||
| public enum PropType // 道具类型 | |||
| { | |||
| Null = 0, | |||
| addSpeed = 1, | |||
| addLIFE = 2, | |||
| Shield = 3, | |||
| Spear = 4, | |||
| AddSpeed = 1, | |||
| AddLifeOrAp = 2, | |||
| AddHpOrAp = 3, | |||
| ShieldOrSpear = 4, | |||
| Key3 = 5, | |||
| Key5 = 6, | |||
| Key6 = 7, | |||
| @@ -108,7 +108,8 @@ namespace Preparation.Utility | |||
| AddSpeed = 1, | |||
| AddLIFE = 2, | |||
| Shield = 3, | |||
| Spear = 4 | |||
| Spear = 4, | |||
| AddAp = 5, | |||
| } | |||
| public enum PlaceType | |||
| @@ -124,6 +124,10 @@ namespace Preparation.Utility | |||
| 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 static int ScoreUseProp(PropType prop, bool IsGhost) | |||
| { | |||
| @@ -171,6 +175,10 @@ namespace Preparation.Utility | |||
| public const long PropProduceTime = 10000; | |||
| 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; | |||
| @@ -48,6 +48,14 @@ namespace Server | |||
| { | |||
| switch (prop) | |||
| { | |||
| case Preparation.Utility.PropType.AddSpeed: | |||
| return Protobuf.PropType.AddSpeed; | |||
| case Preparation.Utility.PropType.AddLifeOrAp: | |||
| return Protobuf.PropType.AddLifeOrAp; | |||
| case Preparation.Utility.PropType.AddHpOrAp: | |||
| return Protobuf.PropType.AddHpOrAp; | |||
| case Preparation.Utility.PropType.ShieldOrSpear: | |||
| return Protobuf.PropType.ShieldOrSpear; | |||
| case Preparation.Utility.PropType.Key3: | |||
| return Protobuf.PropType.Key3; | |||
| case Preparation.Utility.PropType.Key5: | |||