| @@ -17,7 +17,7 @@ | |||||
| #### 人物 | #### 人物 | ||||
| - `std::future<bool> EndAllAction()`:可以使不处在不可行动状态中的玩家终止当前行动 | - `std::future<bool> EndAllAction()`:可以使不处在不可行动状态中的玩家终止当前行动 | ||||
| - 在指令仍在进行时,重复发出同一类型的交互指令和移动指令是无效的,你需要先发出 Stop 指令终止进行的指令 | - 在指令仍在进行时,重复发出同一类型的交互指令和移动指令是无效的,你需要先发出 Stop 指令终止进行的指令 | ||||
| - 实际上唤醒或勉励不同的人是有效的 | |||||
| - EndAllAction() 及 Move 指令调用数总和一帧内不超过 10 次 | |||||
| #### 攻击 | #### 攻击 | ||||
| - `std::future<bool> Attack(double angleInRadian)`:`angleInRadian`为攻击方向 | - `std::future<bool> Attack(double angleInRadian)`:`angleInRadian`为攻击方向 | ||||
| @@ -22,7 +22,6 @@ | |||||
| - `def EndAllAction(self) -> Future[bool]`:可以使不处在不可行动状态中的玩家终止当前行动 | - `def EndAllAction(self) -> Future[bool]`:可以使不处在不可行动状态中的玩家终止当前行动 | ||||
| - 在指令仍在进行时,重复发出同一类型的交互指令和移动指令是无效的,你需要先发出 Stop 指令终止进行的指令 | - 在指令仍在进行时,重复发出同一类型的交互指令和移动指令是无效的,你需要先发出 Stop 指令终止进行的指令 | ||||
| - 实际上唤醒或勉励不同的人是有效的 | |||||
| - EndAllAction() 及 Move 指令调用数总和一帧内不超过 10 次 | - EndAllAction() 及 Move 指令调用数总和一帧内不超过 10 次 | ||||
| #### 攻击 | #### 攻击 | ||||
| @@ -11,10 +11,10 @@ | |||||
| # 5月6日12点更新 | # 5月6日12点更新 | ||||
| - hotfix: 修复了突然的bug(物件锁的相关问题) | - hotfix: 修复了突然的bug(物件锁的相关问题) | ||||
| - rule:增加了每帧最多50条主动指令的限制 | |||||
| - rule:增加了每帧最多50条主动指令的限制 | |||||
| # 5月8日更新 | # 5月8日更新 | ||||
| - feat:增加了可选地图功能 | |||||
| - feat:增加了可选地图功能 | |||||
| - **脚本RunServer(ForDebug).cmd/sh现在支持可选地图功能,但想选择地图,选手需要自行参照使用文档修改命令行或在云盘下载脚本** | - **脚本RunServer(ForDebug).cmd/sh现在支持可选地图功能,但想选择地图,选手需要自行参照使用文档修改命令行或在云盘下载脚本** | ||||
| # 5月9日19:30更新 | # 5月9日19:30更新 | ||||
| @@ -23,5 +23,9 @@ | |||||
| # 最新更新 | # 最新更新 | ||||
| - fix:修复JumpyDumpty的初始位置错误的问题 | - fix:修复JumpyDumpty的初始位置错误的问题 | ||||
| - fix:修正和重新说明攻击距离 | |||||
| - **攻击距离是指攻击(子弹)的移动距离,也就是说理论上最远被攻击的学生的中心与捣蛋鬼的中心=学生的半径+捣蛋鬼的半径+攻击距离+子弹半径(200)×2** | |||||
| - fix:修正和重新说明攻击距离 | |||||
| - **攻击距离是指攻击(子弹)的移动距离,也就是说理论上最远被攻击的学生的中心与捣蛋鬼的中心=学生的半径+捣蛋鬼的半径+攻击距离+子弹半径(200)×2** | |||||
| - hotfix:修复小炸弹初始化类型错误的问题 | |||||
| - remove:去除了“实际上唤醒或勉励不同的人是有效的” | |||||
| - **重复发出同一类型的交互指令和移动指令是无效的** | |||||
| - feat&fix:修复并**将`SendMessage`改为`SendTextMessage`与`SendBinaryMessage`** | |||||
| @@ -304,24 +304,51 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| if (playerState == PlayerStateType.Null && IsMoving) return PlayerStateType.Moving; | |||||
| return playerState; | |||||
| lock (actionLock) | |||||
| { | |||||
| if (playerState == PlayerStateType.Null && IsMoving) return PlayerStateType.Moving; | |||||
| return playerState; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| public bool NoHp() => (playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | |||||
| || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued); | |||||
| public bool Commandable() => (playerState != PlayerStateType.Deceased && playerState != PlayerStateType.Escaped | |||||
| && playerState != PlayerStateType.Addicted && playerState != PlayerStateType.Rescued | |||||
| && playerState != PlayerStateType.Swinging && playerState != PlayerStateType.TryingToAttack | |||||
| && playerState != PlayerStateType.ClimbingThroughWindows && playerState != PlayerStateType.Stunned); | |||||
| public bool InteractingWithMapWithoutMoving() => (playerState == PlayerStateType.LockingOrOpeningTheDoor || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest); | |||||
| public bool NullOrMoving() => (playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | |||||
| public bool CanBeAwed() => !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | |||||
| || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued | |||||
| || playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned | |||||
| || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | |||||
| public bool NoHp() | |||||
| { | |||||
| lock (actionLock) | |||||
| return (playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued); | |||||
| } | |||||
| public bool Commandable() | |||||
| { | |||||
| lock (actionLock) | |||||
| { | |||||
| return (playerState != PlayerStateType.Deceased && playerState != PlayerStateType.Escaped | |||||
| && playerState != PlayerStateType.Addicted && playerState != PlayerStateType.Rescued | |||||
| && playerState != PlayerStateType.Swinging && playerState != PlayerStateType.TryingToAttack | |||||
| && playerState != PlayerStateType.ClimbingThroughWindows && playerState != PlayerStateType.Stunned); | |||||
| } | |||||
| } | |||||
| public bool InteractingWithMapWithoutMoving() | |||||
| { | |||||
| lock (actionLock) | |||||
| { | |||||
| return (playerState == PlayerStateType.LockingOrOpeningTheDoor || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest); | |||||
| } | |||||
| } | |||||
| public bool NullOrMoving() | |||||
| { | |||||
| lock (actionLock) | |||||
| { | |||||
| return (playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | |||||
| } | |||||
| } | |||||
| public bool CanBeAwed() | |||||
| { | |||||
| lock (actionLock) | |||||
| return !(playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped | |||||
| || playerState == PlayerStateType.Addicted || playerState == PlayerStateType.Rescued | |||||
| || playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned | |||||
| || playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving); | |||||
| } | |||||
| private GameObj? whatInteractingWith = null; | private GameObj? whatInteractingWith = null; | ||||
| public GameObj? WhatInteractingWith => whatInteractingWith; | public GameObj? WhatInteractingWith => whatInteractingWith; | ||||
| @@ -21,14 +21,14 @@ namespace Gaming | |||||
| { | { | ||||
| if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | ||||
| { | { | ||||
| if (characterManager.BeStunned((Character)player, GameData.timeOfStunnedWhenJumpyDumpty)) | |||||
| if (characterManager.BeStunned((Character)player, GameData.timeOfStunnedWhenJumpyDumpty) > 0) | |||||
| player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStunnedWhenJumpyDumpty)); | player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStunnedWhenJumpyDumpty)); | ||||
| gameMap.Remove((GameObj)collisionObj); | gameMap.Remove((GameObj)collisionObj); | ||||
| } | } | ||||
| } | } | ||||
| if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | ||||
| { | { | ||||
| if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge)) | |||||
| if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); | player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); | ||||
| characterManager.BeStunned(player, GameData.timeOfStudentStunnedWhenCharge); | characterManager.BeStunned(player, GameData.timeOfStudentStunnedWhenCharge); | ||||
| } | } | ||||
| @@ -37,7 +37,6 @@ namespace Gaming | |||||
| { | { | ||||
| if (moveTimeInMilliseconds < 5) return false; | if (moveTimeInMilliseconds < 5) return false; | ||||
| if (!playerToMove.Commandable()) return false; | if (!playerToMove.Commandable()) return false; | ||||
| if (playerToMove.IsMoving) return false; | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, | moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, | ||||
| characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving)); | characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving)); | ||||
| return true; | return true; | ||||
| @@ -139,7 +139,7 @@ namespace Gaming | |||||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | ||||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | ||||
| ); | ); | ||||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos); | |||||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent!, angle, pos); | |||||
| angle = bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0; | angle = bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0; | ||||
| pos = bullet.Position + new XY // 子弹紧贴人物生成。 | pos = bullet.Position + new XY // 子弹紧贴人物生成。 | ||||
| @@ -147,7 +147,7 @@ namespace Gaming | |||||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | ||||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | ||||
| ); | ); | ||||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos); | |||||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent!, angle, pos); | |||||
| } | } | ||||
| var beAttackedList = new List<IGameObj>(); | var beAttackedList = new List<IGameObj>(); | ||||
| @@ -21,12 +21,16 @@ namespace Gaming | |||||
| { | { | ||||
| lock (player.ActionLock) | lock (player.ActionLock) | ||||
| { | { | ||||
| switch (player.PlayerState) | |||||
| PlayerStateType nowPlayerState = player.PlayerState; | |||||
| if (nowPlayerState == value) return -1; | |||||
| switch (nowPlayerState) | |||||
| { | { | ||||
| case PlayerStateType.OpeningTheChest: | case PlayerStateType.OpeningTheChest: | ||||
| if (player.NoHp()) return -1; | |||||
| ((Chest)player.WhatInteractingWith!).StopOpen(); | ((Chest)player.WhatInteractingWith!).StopOpen(); | ||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| case PlayerStateType.OpeningTheDoorway: | case PlayerStateType.OpeningTheDoorway: | ||||
| if (player.NoHp()) return -1; | |||||
| Doorway doorway = (Doorway)player.WhatInteractingWith!; | Doorway doorway = (Doorway)player.WhatInteractingWith!; | ||||
| doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; | doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; | ||||
| doorway.OpenStartTime = 0; | doorway.OpenStartTime = 0; | ||||
| @@ -42,6 +46,7 @@ namespace Gaming | |||||
| else | else | ||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| default: | default: | ||||
| if (player.NoHp()) return -1; | |||||
| return player.ChangePlayerState(value, gameObj); | return player.ChangePlayerState(value, gameObj); | ||||
| } | } | ||||
| } | } | ||||
| @@ -270,28 +275,28 @@ namespace Gaming | |||||
| { IsBackground = true }.Start(); | { IsBackground = true }.Start(); | ||||
| } | } | ||||
| public bool BeStunned(Character player, int time) | |||||
| public long BeStunned(Character player, int time) | |||||
| { | { | ||||
| if (player.PlayerState == PlayerStateType.Stunned || player.NoHp() || player.CharacterType == CharacterType.Robot) return false; | |||||
| if (player.CharacterType == CharacterType.Robot) return -1; | |||||
| long threadNum = SetPlayerState(player, PlayerStateType.Stunned); | |||||
| if (threadNum == -1) return -1; | |||||
| new Thread | new Thread | ||||
| (() => | (() => | ||||
| { | { | ||||
| SetPlayerState(player, PlayerStateType.Stunned); | |||||
| long threadNum = player.StateNum; | |||||
| Thread.Sleep(time); | Thread.Sleep(time); | ||||
| if (threadNum == player.StateNum) | if (threadNum == player.StateNum) | ||||
| SetPlayerState(player); | SetPlayerState(player); | ||||
| } | } | ||||
| ) | ) | ||||
| { IsBackground = true }.Start(); | { IsBackground = true }.Start(); | ||||
| return true; | |||||
| return threadNum; | |||||
| } | } | ||||
| public bool TryBeAwed(Student character, Bullet bullet) | public bool TryBeAwed(Student character, Bullet bullet) | ||||
| { | { | ||||
| if (character.CanBeAwed()) | if (character.CanBeAwed()) | ||||
| { | { | ||||
| if (BeStunned(character, GameData.basicStunnedTimeOfStudent)) | |||||
| if (BeStunned(character, GameData.basicStunnedTimeOfStudent) > 0) | |||||
| bullet.Parent!.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent)); | bullet.Parent!.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent)); | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -188,7 +188,7 @@ namespace Gaming | |||||
| { | { | ||||
| if (!character.IsGhost() && !character.NoHp() && XY.DistanceFloor3(character.Position, player.Position) <= player.ViewRange) | if (!character.IsGhost() && !character.NoHp() && XY.DistanceFloor3(character.Position, player.Position) <= player.ViewRange) | ||||
| { | { | ||||
| if (characterManager.BeStunned(character, GameData.timeOfStudentStunnedWhenHowl)) | |||||
| if (characterManager.BeStunned(character, GameData.timeOfStudentStunnedWhenHowl) > 0) | |||||
| player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStudentStunnedWhenHowl)); | player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStudentStunnedWhenHowl)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -219,7 +219,7 @@ namespace Gaming | |||||
| || character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | || character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | ||||
| && gameMap.CanSee(player, character)) | && gameMap.CanSee(player, character)) | ||||
| { | { | ||||
| if (characterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP))) | |||||
| 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))); | player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP))); | ||||
| break; | break; | ||||
| } | } | ||||