diff --git a/docs/使用文档.md b/docs/使用文档.md index 40be5fb..8750510 100644 --- a/docs/使用文档.md +++ b/docs/使用文档.md @@ -147,8 +147,8 @@ start python .\CAPI\python\PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -d -o -w | 1 | Athlete | | 2 | Teacher | | 3 | StraightAStudent | - | 4 | Robot(目前未实现所有功能) | - | 5 | TechOtaku(目前未实现所有功能) | + | 4 | Robot | + | 5 | TechOtaku | | 6 | Sunshine | * 捣蛋鬼 diff --git a/docs/游戏机制与平衡性调整更新草案.md b/docs/游戏机制与平衡性调整更新草案.md index f08ff94..db29155 100644 --- a/docs/游戏机制与平衡性调整更新草案.md +++ b/docs/游戏机制与平衡性调整更新草案.md @@ -51,7 +51,6 @@ v1.6 - Teacher - 学习速度由0改为50 - 警戒范围由7500改为10000 - - 视野范围由9000降为8000 - 翻窗速度改为1000 - 特质: - 扣血则得分100×受到伤害/基本伤害(1500000) @@ -60,7 +59,7 @@ v1.6 - “使用瞬间,在**视野距离/3范围内(不是可视范围)的**翻窗、开锁门、攻击前后摇、**使用技能期间**的捣蛋鬼会被眩晕(3070+**500***已受伤害/基本伤害(1500000))ms” - 技能喝茶(HaveTea)(新增) - CD:90s - - 在有队友受过伤的情况下,使用瞬间,向当前方向瞬移3000(可以穿墙),如果会碰撞则失败。 + - 使用瞬间,向额外参数/1000.0的角度瞬移3000(可以穿墙),如果会碰撞则失败。 - Robot(新增) - 无技能 - 特性 @@ -71,14 +70,14 @@ v1.6 - 不可使用道具(可以捡起和扔道具) - TechOtaku(新增) - 一名TechOtaku最多可以在场上同时最多拥有3个Robot,无法共享视野 - 0. SummonGolem + 1. SummonGolem - CD:40s,持续时间:6s - 在持续时间中,学生进入人物状态进入UsingSpecialSkill(不能移动),进入其他状态会导致制作机器人失败。 - 在持续时间中,学生面前生成道具CraftingBench;学生进入其他状态或该道具被碰撞后,CraftingBench消失且制作机器人失败。 - 持续时间结束后,道具CraftingBench所在位置生成一个Robot,CraftingBench消失 - TechOtaku的Robot的PlayerId = TechOtaku的PlayerId + n×5(一局游戏理论人数),其中1<=n<=3(自己的n为0) - 新造的Robot的PlayerId的n总是尽量小 - 1. UseRobot + 2. UseRobot - CD:2s,持续时间:0s - 输入额外参数PlayerID,切换到要使用的角色。 - 切换到其他角色时,自己进入UsingSkill状态。 @@ -94,7 +93,7 @@ v1.6 | 勉励速度/ms | 80 | 90 | 100 | 120 | 0 | 100 | | 隐蔽度 | 0.5 | 0.9 | 0.9 | 0.8 | 0.8 | 1.1 | | 警戒范围 | 10000 | 15000 | 13500 | 15000 | 0 | 15000 | -| 视野范围 | 8000 | 11000 | 9000 | 10000 | 0 | 9000 | +| 视野范围 | 9000 | 11000 | 9000 | 10000 | 0 | 9000 | | 开锁门速度/ms | 5000 | 5000 | 5000 | 3500 | 0 | 5000 | | 翻窗速度/ms | 1000 | 1466 | 1018 | 1222 | 1 | 1100 | | 翻箱速度/ms | 1250 | 1250 | 1250 | 1125 | 1000 | 1100 | diff --git a/docs/版本更新说明.md b/docs/版本更新说明.md index 7dc7e94..3de31d1 100644 --- a/docs/版本更新说明.md +++ b/docs/版本更新说明.md @@ -44,5 +44,10 @@ - fix:修复了InSpire会给Tricker加速的问题 - fix:修复了开锁门的bug +# 5月19日15:00更新 +- docs:更新了 游戏机制与平衡性调整更新草案.pdf +- hotfix:修复了移动状态设置错误 + # 最新更新 +- feat:Assassin、Teacher已调整 - docs:更新了 游戏机制与平衡性调整更新草案.pdf \ No newline at end of file diff --git a/logic/GameClass/GameObj/Bullet/Bullet.cs b/logic/GameClass/GameObj/Bullet/Bullet.cs index fa25353..b7c20a9 100644 --- a/logic/GameClass/GameObj/Bullet/Bullet.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.cs @@ -14,7 +14,7 @@ namespace GameClass.GameObj protected int ap; public int AP { - get => Interlocked.CompareExchange(ref ap, 0, 1); + get => Interlocked.CompareExchange(ref ap, 0, 0); } public void AddAP(int addAp) { diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 6855120..79d1e4b 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -362,8 +362,7 @@ namespace GameClass.GameObj lock (actionLock) { if (playerState == PlayerStateType.Moving) - if (IsMoving == 1) return PlayerStateType.Moving; - else return PlayerStateType.Null; + return (IsMoving == 1) ? PlayerStateType.Moving : PlayerStateType.Null; return playerState; } } @@ -540,27 +539,41 @@ namespace GameClass.GameObj ThreadNum.Release(); } case PlayerStateType.UsingSkill: - if (CharacterType == CharacterType.TechOtaku) { - if (typeof(CraftingBench).IsInstanceOfType(whatInteractingWith)) + switch (CharacterType) { - try - { - ((CraftingBench)whatInteractingWith!).StopSkill(); + case CharacterType.TechOtaku: + { + if (typeof(CraftingBench).IsInstanceOfType(whatInteractingWith)) + { + try + { + ((CraftingBench)whatInteractingWith!).StopSkill(); + return ChangePlayerState(value, gameObj); + } + finally + { + ThreadNum.Release(); + } + } + else + { + if (value != PlayerStateType.UsingSkill) + ((UseRobot)FindActiveSkill(ActiveSkillType.UseRobot)).NowPlayerID = (int)playerID; + return ChangePlayerState(value, gameObj); + } + } + case CharacterType.Assassin: + if (value == PlayerStateType.Moving) return StateNum; + else + { + TryDeleteInvisible(); + return ChangePlayerState(value, gameObj); + } + default: return ChangePlayerState(value, gameObj); - } - finally - { - ThreadNum.Release(); - } - } - else - { - if (value != PlayerStateType.UsingSkill) - ((UseRobot)FindActiveSkill(ActiveSkillType.UseRobot)).NowPlayerID = (int)playerID; } } - return ChangePlayerState(value, gameObj); default: return ChangePlayerState(value, gameObj); } diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs index 7f9c74f..21bf524 100644 --- a/logic/GameClass/GameObj/Moveable.cs +++ b/logic/GameClass/GameObj/Moveable.cs @@ -50,7 +50,7 @@ namespace GameClass.GameObj private int isMoving = 0; public int IsMoving { - get => Interlocked.CompareExchange(ref isMoving, 0, 1); + get => Interlocked.CompareExchange(ref isMoving, 0, 0); set => Interlocked.Exchange(ref isMoving, value); } @@ -157,7 +157,7 @@ namespace GameClass.GameObj /// public int MoveSpeed { - get => Interlocked.CompareExchange(ref moveSpeed, 0, 1); + get => Interlocked.CompareExchange(ref moveSpeed, 0, 0); set => Interlocked.Exchange(ref moveSpeed, value); } /// diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 5f05c6b..cfb2a58 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -13,7 +13,6 @@ namespace Gaming { public static bool CanBeginToCharge(Character player) { - if ((!player.Commandable())) return false; ActiveSkill skill = player.FindActiveSkill(ActiveSkillType.CanBeginToCharge); Debugger.Output(player, "can begin to charge!"); @@ -93,19 +92,32 @@ namespace Gaming public static bool BecomeInvisible(Character player) { - if ((!player.Commandable())) return false; ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.BecomeInvisible); + long stateNum = player.SetPlayerState(PlayerStateType.UsingSkill); + if (stateNum == -1) + { + return false; + } return ActiveSkillEffect(activeSkill, player, () => { player.AddScore(GameData.ScoreBecomeInvisible); player.AddInvisible(activeSkill.DurationTime); Debugger.Output(player, "become invisible!"); }, - () => - { }); + () => + { + lock (player.ActionLock) + { + if (stateNum == player.StateNum) + { + player.SetPlayerStateNaturally(); + } + } + } + ); } - public bool UseRobot(Character player, int robotID) + public static bool UseRobot(Character player, int robotID) { if ((robotID - player.PlayerID) % GameData.numOfPeople != 0) return false; if ((robotID - (int)player.PlayerID) / GameData.numOfPeople < 0 || (robotID - (int)player.PlayerID) / GameData.numOfPeople > GameData.maxSummonedGolemNum) return false; @@ -261,8 +273,7 @@ namespace Gaming } craftingBench.ParentStateNum = stateNum; gameMap.Add(craftingBench); - /* - */ + return ActiveSkillEffect(activeSkill, player, () => { }, @@ -343,8 +354,8 @@ namespace Gaming || character.PlayerState == PlayerStateType.ClimbingThroughWindows) && XY.DistanceFloor3(character.Position, player.Position) <= player.ViewRange / 3) { - if (CharacterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP)) > 0) - player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP))); + if (CharacterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost) > 0) + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost)); break; } } @@ -359,6 +370,41 @@ namespace Gaming { }); } + public bool HaveTea(Character player, int angle1000) + { + long stateNum = player.SetPlayerState(PlayerStateType.UsingSkill); + if (stateNum == -1) + { + return false; + } + player.ThreadNum.WaitOne(); + + XY res = player.Position + new XY(angle1000 / 1000.0, GameData.distanceOfHaveTea); + Debugger.Output(res.ToString()); + if (actionManager.moveEngine.CheckCollision(player, res) != null) + { + player.ThreadNum.Release(); + return false; + } + Debugger.Output("NO Collision!"); + player.ReSetPos(res); + lock (player.ActionLock) + { + if (player.StateNum == stateNum) + { + player.SetPlayerStateNaturally(); + } + } + player.ThreadNum.Release(); + + return ActiveSkillEffect(player.FindActiveSkill(ActiveSkillType.HaveTea), player, () => + { + Debugger.Output(player, "have tea!"); + }, + () => + { }); + } + public bool Rouse(Character player) { if ((!player.Commandable())) return false; diff --git a/logic/Gaming/SkillManager/SkillManager.cs b/logic/Gaming/SkillManager/SkillManager.cs index fd2c21e..b3958cf 100644 --- a/logic/Gaming/SkillManager/SkillManager.cs +++ b/logic/Gaming/SkillManager/SkillManager.cs @@ -30,6 +30,8 @@ namespace Gaming return Encourage(character); case ActiveSkillType.Punish: return Punish(character); + case ActiveSkillType.HaveTea: + return HaveTea(character, parameter); case ActiveSkillType.JumpyBomb: return JumpyBomb(character); case ActiveSkillType.SparksNSplash: diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index 4d8e606..d7f07e8 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -166,7 +166,7 @@ namespace Preparation.Interface public BulletType InitBullet => BulletType.Null; - public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish }); + public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish, ActiveSkillType.HaveTea }); public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); public const int fixSpeed = 50; @@ -181,7 +181,7 @@ namespace Preparation.Interface public const int alertnessRadius = GameData.basicStudentAlertnessRadius * 2 / 3; public int AlertnessRadius => alertnessRadius; - public int viewRange = GameData.basicStudentViewRange * 8 / 10; + public int viewRange = GameData.basicStudentViewRange * 9 / 10; public int ViewRange => viewRange; public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index c8fa69d..72a1cba 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -34,7 +34,7 @@ namespace Preparation.Interface { get { - return Interlocked.CompareExchange(ref timeUntilActiveSkillAvailable, 0, 1); + return Interlocked.CompareExchange(ref timeUntilActiveSkillAvailable, 0, 0); } set { @@ -47,7 +47,7 @@ namespace Preparation.Interface public int isBeingUsed = 0;//实为bool public int IsBeingUsed { - get => Interlocked.CompareExchange(ref isBeingUsed, 0, 1); + get => Interlocked.CompareExchange(ref isBeingUsed, 0, 0); set => Interlocked.Exchange(ref isBeingUsed, value); } } @@ -70,6 +70,12 @@ namespace Preparation.Interface public override int DurationTime => 0; } + public class HaveTea : ActiveSkill + { + public override int SkillCD => GameData.commonSkillCD * 3; + public override int DurationTime => 0; + } + public class Rouse : ActiveSkill { public override int SkillCD => GameData.commonSkillCD * 4; @@ -163,7 +169,7 @@ namespace Preparation.Interface private int degreeOfMeditation = 0; public int DegreeOfMeditation { - get => Interlocked.CompareExchange(ref degreeOfMeditation, 0, 1); + get => Interlocked.CompareExchange(ref degreeOfMeditation, 0, 0); set => Interlocked.Exchange(ref degreeOfMeditation, value); } } @@ -245,6 +251,8 @@ namespace Preparation.Interface return new CanBeginToCharge(); case ActiveSkillType.Punish: return new Punish(); + case ActiveSkillType.HaveTea: + return new HaveTea(); case ActiveSkillType.JumpyBomb: return new JumpyBomb(); case ActiveSkillType.SparksNSplash: @@ -284,6 +292,8 @@ namespace Preparation.Interface return ActiveSkillType.Inspire; case Punish: return ActiveSkillType.Punish; + case HaveTea: + return ActiveSkillType.HaveTea; case JumpyBomb: return ActiveSkillType.JumpyBomb; case SparksNSplash: diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index b24dbd1..538c091 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -214,8 +214,9 @@ namespace Preparation.Utility public const int timeOfStudentStunnedWhenCharge = 2090; public const int timeOfGhostStunnedWhenPunish = 3070; - public const int factorOfTimeStunnedWhenPunish = 500 / basicApOfGhost; - public const int factorOfScoreWhenTeacherAttacked = 100;//每个 + public const int factorOfTimeStunnedWhenPunish = 500; + public const int factorOfScoreWhenTeacherAttacked = 100; + public const int distanceOfHaveTea = 3000; public const int timeOfGhostSwingingAfterHowl = 800; public const int timeOfStudentStunnedWhenHowl = 5500;