| @@ -318,18 +318,10 @@ namespace GameClass.GameObj | |||
| private GameObj? whatInteractingWith = null; | |||
| public GameObj? WhatInteractingWith => whatInteractingWith; | |||
| public void SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| public void ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| switch (playerState) | |||
| { | |||
| case PlayerStateType.OpeningTheChest: | |||
| ((Chest)whatInteractingWith).StopOpen(); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| whatInteractingWith = gameObj; | |||
| if (value != PlayerStateType.Moving) | |||
| IsMoving = false; | |||
| @@ -35,14 +35,14 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| private bool isOpening = false; | |||
| public bool IsOpening | |||
| private int openStartTime = 0; | |||
| public int OpenStartTime | |||
| { | |||
| get => isOpening; | |||
| get => openStartTime; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| isOpening = value; | |||
| openStartTime = value; | |||
| } | |||
| } | |||
| @@ -61,6 +61,6 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway); | |||
| public bool IsOpen() => (openDegree == GameData.degreeOfOpenedDoorway); | |||
| } | |||
| } | |||
| @@ -23,22 +23,22 @@ namespace Gaming | |||
| { | |||
| if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) | |||
| { | |||
| if (CharacterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty)) | |||
| if (characterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty)) | |||
| player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStunnedWhenJumpyDumpty)); | |||
| gameMap.Remove((GameObj)collisionObj); | |||
| } | |||
| } | |||
| if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) | |||
| { | |||
| if (CharacterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | |||
| if (characterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge)) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge)); | |||
| CharacterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); | |||
| characterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge); | |||
| } | |||
| } | |||
| public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | |||
| { | |||
| if (!playerToMove.Commandable() || !TryToStop()) return false; | |||
| playerToMove.SetPlayerState(PlayerStateType.Moving); | |||
| characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving); | |||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | |||
| return true; | |||
| } | |||
| @@ -47,7 +47,7 @@ namespace Gaming | |||
| { | |||
| if (player.Commandable() || !TryToStop()) | |||
| { | |||
| player.SetPlayerState(); | |||
| characterManager.SetPlayerState(player); | |||
| return true; | |||
| } | |||
| return false; | |||
| @@ -63,7 +63,7 @@ namespace Gaming | |||
| return false; | |||
| ++generatorForFix.NumOfFixing; | |||
| player.SetPlayerState(PlayerStateType.Fixing); | |||
| characterManager.SetPlayerState(player, PlayerStateType.Fixing); | |||
| new Thread | |||
| ( | |||
| () => | |||
| @@ -74,7 +74,7 @@ namespace Gaming | |||
| { | |||
| if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) | |||
| { | |||
| player.SetPlayerState(); | |||
| characterManager.SetPlayerState(player); | |||
| gameMap.NumOfRepairedGenerators++; | |||
| } | |||
| }, | |||
| @@ -96,31 +96,21 @@ namespace Gaming | |||
| if (!(player.Commandable()) || player.PlayerState == PlayerStateType.OpeningTheDoorway) | |||
| return false; | |||
| Doorway? doorwayToOpen = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); | |||
| if (doorwayToOpen == null || doorwayToOpen.IsOpening || !doorwayToOpen.PowerSupply) | |||
| if (doorwayToOpen == null || doorwayToOpen.OpenStartTime > 0 || !doorwayToOpen.PowerSupply) | |||
| return false; | |||
| player.SetPlayerState(PlayerStateType.OpeningTheDoorway); | |||
| doorwayToOpen.IsOpening = true; | |||
| characterManager.SetPlayerState(player, PlayerStateType.OpeningTheDoorway, doorwayToOpen); | |||
| int startTime = doorwayToOpen.OpenStartTime = gameMap.Timer.nowTime(); | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheDoorway && gameMap.Timer.IsGaming && doorwayToOpen.OpenDegree < GameData.degreeOfOpenedDoorway, | |||
| loopToDo: () => | |||
| { | |||
| doorwayToOpen.OpenDegree += GameData.frameDuration; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0 | |||
| ) | |||
| Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree); | |||
| .Start(); | |||
| doorwayToOpen.IsOpening = false; | |||
| if (doorwayToOpen.OpenDegree >= GameData.degreeOfOpenedDoorway) | |||
| if (doorwayToOpen.OpenStartTime == startTime) | |||
| { | |||
| if (player.PlayerState == PlayerStateType.OpeningTheDoorway) | |||
| player.SetPlayerState(); | |||
| doorwayToOpen.OpenDegree = GameData.degreeOfOpenedDoorway; | |||
| player.SetPlayerStateNaturally(); | |||
| } | |||
| } | |||
| @@ -172,22 +162,22 @@ namespace Gaming | |||
| ( | |||
| () => | |||
| { | |||
| playerTreated.SetPlayerState(PlayerStateType.Treated); | |||
| player.SetPlayerState(PlayerStateType.Treating); | |||
| characterManager.SetPlayerState(player, PlayerStateType.Treated); | |||
| characterManager.SetPlayerState(player, PlayerStateType.Treating); | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) | |||
| playerTreated.SetPlayerState(); | |||
| characterManager.SetPlayerState(playerTreated); | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0 | |||
| ) | |||
| .Start(); | |||
| if (player.PlayerState == PlayerStateType.Treating) player.SetPlayerState(); | |||
| else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState(); | |||
| if (player.PlayerState == PlayerStateType.Treating) characterManager.SetPlayerState(player); | |||
| else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| @@ -202,8 +192,8 @@ namespace Gaming | |||
| } | |||
| if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) | |||
| return false; | |||
| player.SetPlayerState(PlayerStateType.Rescuing); | |||
| playerRescued.SetPlayerState(PlayerStateType.Rescued); | |||
| characterManager.SetPlayerState(player, PlayerStateType.Rescuing); | |||
| characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued); | |||
| new Thread | |||
| ( | |||
| @@ -225,14 +215,14 @@ namespace Gaming | |||
| { | |||
| if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue) | |||
| { | |||
| playerRescued.SetPlayerState(); | |||
| characterManager.SetPlayerState(playerRescued); | |||
| playerRescued.HP = playerRescued.MaxHp / 2; | |||
| player.AddScore(GameData.StudentScoreRescue); | |||
| } | |||
| else | |||
| playerRescued.SetPlayerState(PlayerStateType.Addicted); | |||
| characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted); | |||
| } | |||
| if (player.PlayerState == PlayerStateType.Rescuing) player.SetPlayerState(); | |||
| if (player.PlayerState == PlayerStateType.Rescuing) characterManager.SetPlayerState(player); | |||
| playerRescued.TimeOfRescue = 0; | |||
| } | |||
| ) | |||
| @@ -249,7 +239,7 @@ namespace Gaming | |||
| if (chestToOpen == null || chestToOpen.OpenStartTime > 0) | |||
| return false; | |||
| player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen); | |||
| characterManager.SetPlayerState(player, PlayerStateType.OpeningTheChest, chestToOpen); | |||
| int startTime = gameMap.Timer.nowTime(); | |||
| chestToOpen.Open(startTime, player); | |||
| new Thread | |||
| @@ -300,7 +290,7 @@ namespace Gaming | |||
| //Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer); | |||
| // gameMap.Add(addWall); | |||
| player.SetPlayerState(PlayerStateType.ClimbingThroughWindows); | |||
| characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows); | |||
| windowForClimb.WhoIsClimbing = player; | |||
| new Thread | |||
| ( | |||
| @@ -342,7 +332,7 @@ namespace Gaming | |||
| // gameMap.Remove(addWall); | |||
| if (player.PlayerState == PlayerStateType.ClimbingThroughWindows) | |||
| { | |||
| player.SetPlayerState(); | |||
| characterManager.SetPlayerState(player); | |||
| } | |||
| } | |||
| @@ -382,7 +372,7 @@ namespace Gaming | |||
| } | |||
| if (!flag) return false; | |||
| player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor); | |||
| characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor); | |||
| new Thread | |||
| ( | |||
| () => | |||
| @@ -405,7 +395,7 @@ namespace Gaming | |||
| doorToLock.IsOpen = (!doorToLock.IsOpen); | |||
| } | |||
| if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor) | |||
| player.SetPlayerState(); | |||
| characterManager.SetPlayerState(player); | |||
| doorToLock.OpenOrLockDegree = 0; | |||
| } | |||
| @@ -81,14 +81,14 @@ namespace Gaming | |||
| { | |||
| if (objBeingShot == null) | |||
| { | |||
| CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); | |||
| characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); | |||
| return; | |||
| } | |||
| Debugger.Output(bullet, bullet.TypeOfBullet.ToString()); | |||
| BombObj(bullet, objBeingShot); | |||
| CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); | |||
| characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); | |||
| return; | |||
| } | |||
| @@ -140,10 +140,10 @@ namespace Gaming | |||
| if (objBeingShot == null) | |||
| { | |||
| CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); | |||
| characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing); | |||
| } | |||
| else | |||
| CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); | |||
| characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit); | |||
| } | |||
| public bool Attack(Character? player, double angle) | |||
| @@ -174,7 +174,7 @@ namespace Gaming | |||
| if (bullet.CastTime > 0) | |||
| { | |||
| player.SetPlayerState(PlayerStateType.TryingToAttack); | |||
| characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); | |||
| new Thread | |||
| (() => | |||
| @@ -195,7 +195,7 @@ namespace Gaming | |||
| { | |||
| if (player.PlayerState == PlayerStateType.TryingToAttack) | |||
| { | |||
| player.SetPlayerState(); | |||
| characterManager.SetPlayerState(player); | |||
| } | |||
| else | |||
| bullet.IsMoving = false; | |||
| @@ -7,6 +7,7 @@ using GameEngine; | |||
| using Preparation.Interface; | |||
| using Timothy.FrameRateTask; | |||
| using System.Numerics; | |||
| using System.Timers; | |||
| namespace Gaming | |||
| { | |||
| @@ -21,6 +22,21 @@ namespace Gaming | |||
| this.gameMap = gameMap; | |||
| } | |||
| public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| { | |||
| switch (player.PlayerState) | |||
| { | |||
| case PlayerStateType.OpeningTheChest: | |||
| ((Chest)player.WhatInteractingWith).StopOpen(); | |||
| break; | |||
| case PlayerStateType.OpeningTheDoorway: | |||
| ((Doorway)player.WhatInteractingWith).OpenDegree += gameMap.Timer.nowTime() - ((Doorway)player.WhatInteractingWith).OpenStartTime; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| player.ChangePlayerState(value, gameObj); | |||
| } | |||
| public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null) | |||
| { | |||
| @@ -216,7 +232,7 @@ namespace Gaming | |||
| return; | |||
| } | |||
| } | |||
| player.SetPlayerState(PlayerStateType.Addicted); | |||
| SetPlayerState(player, PlayerStateType.Addicted); | |||
| new Thread | |||
| (() => | |||
| { | |||
| @@ -246,23 +262,23 @@ namespace Gaming | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public static bool BeStunned(Character player, int time) | |||
| public bool BeStunned(Character player, int time) | |||
| { | |||
| if (player.PlayerState == PlayerStateType.Stunned || player.NoHp() || player.CharacterType == CharacterType.Robot) return false; | |||
| new Thread | |||
| (() => | |||
| { | |||
| player.SetPlayerState(PlayerStateType.Stunned); | |||
| SetPlayerState(player, PlayerStateType.Stunned); | |||
| Thread.Sleep(time); | |||
| if (player.PlayerState == PlayerStateType.Stunned) | |||
| player.SetPlayerState(); | |||
| SetPlayerState(player); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return true; | |||
| } | |||
| public static bool TryBeAwed(Student character, Bullet bullet) | |||
| public bool TryBeAwed(Student character, Bullet bullet) | |||
| { | |||
| if (character.CanBeAwed()) | |||
| { | |||
| @@ -337,11 +353,11 @@ namespace Gaming | |||
| else TryBeAwed(student, bullet); | |||
| } | |||
| public static bool BackSwing(Character? player, int time) | |||
| public bool BackSwing(Character? player, int time) | |||
| { | |||
| if (player == null || time <= 0) return false; | |||
| if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false; | |||
| player.SetPlayerState(PlayerStateType.Swinging); | |||
| SetPlayerState(player, PlayerStateType.Swinging); | |||
| new Thread | |||
| (() => | |||
| @@ -350,7 +366,7 @@ namespace Gaming | |||
| if (player.PlayerState == PlayerStateType.Swinging) | |||
| { | |||
| player.SetPlayerState(); | |||
| SetPlayerState(player); | |||
| } | |||
| } | |||
| ) | |||
| @@ -233,7 +233,7 @@ namespace Gaming | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| PropManager.UseProp(player, propType); | |||
| propManager.UseProp(player, propType); | |||
| } | |||
| } | |||
| public void ThrowProp(long playerID, PropType propType = PropType.Null) | |||
| @@ -375,7 +375,7 @@ namespace Gaming | |||
| characterManager = new CharacterManager(gameMap); | |||
| attackManager = new AttackManager(gameMap, characterManager); | |||
| actionManager = new ActionManager(gameMap, characterManager); | |||
| propManager = new PropManager(gameMap); | |||
| propManager = new PropManager(gameMap, characterManager); | |||
| skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager, characterManager); | |||
| } | |||
| } | |||
| @@ -16,10 +16,10 @@ namespace Gaming | |||
| private class PropManager | |||
| { | |||
| private readonly Map gameMap; | |||
| private readonly CharacterManager characterManager; | |||
| private readonly List<XY> availableCellForGenerateProp; | |||
| public static void UseProp(Character player, PropType propType) | |||
| public void UseProp(Character player, PropType propType) | |||
| { | |||
| if (player.IsResetting || player.CharacterType == CharacterType.Robot) | |||
| return; | |||
| @@ -57,7 +57,7 @@ namespace Gaming | |||
| if (player.PlayerState == PlayerStateType.Stunned) | |||
| { | |||
| player.AddScore(GameData.ScorePropRecoverFromDizziness); | |||
| player.SetPlayerState(); | |||
| player.SetPlayerStateNaturally(); | |||
| } | |||
| break; | |||
| default: | |||
| @@ -210,8 +210,9 @@ namespace Gaming | |||
| { IsBackground = true }.Start(); | |||
| */ | |||
| } | |||
| public PropManager(Map gameMap) // 道具不能扔过墙 | |||
| public PropManager(Map gameMap, CharacterManager characterManager) // 道具不能扔过墙 | |||
| { | |||
| this.characterManager = characterManager; | |||
| this.gameMap = gameMap; | |||
| /* this.moveEngine = new MoveEngine( | |||
| gameMap: gameMap, | |||
| @@ -145,7 +145,7 @@ namespace Gaming | |||
| { | |||
| if (!character.IsGhost() && XY.Distance(character.Position, player.Position) <= player.ViewRange) | |||
| { | |||
| if (CharacterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl)) | |||
| if (characterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl)) | |||
| player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStudentFaintingWhenHowl)); | |||
| break; | |||
| } | |||
| @@ -155,7 +155,7 @@ namespace Gaming | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| CharacterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl); | |||
| characterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl); | |||
| Debugger.Output(player, "howled!"); | |||
| }, | |||
| () => | |||
| @@ -177,7 +177,7 @@ namespace Gaming | |||
| || character.PlayerState == PlayerStateType.UsingSkill) | |||
| && gameMap.CanSee(player, character)) | |||
| { | |||
| if (CharacterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish)) | |||
| if (characterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish)) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish)); | |||
| break; | |||
| } | |||
| @@ -205,7 +205,7 @@ namespace Gaming | |||
| { | |||
| if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character)) | |||
| { | |||
| character.SetPlayerState(); | |||
| characterManager.SetPlayerState(character); | |||
| character.HP = GameData.RemainHpWhenAddLife; | |||
| ((Student)character).TimeOfRescue = 0; | |||
| player.AddScore(GameData.StudentScoreRescue); | |||
| @@ -32,7 +32,7 @@ namespace Server | |||
| case Preparation.Utility.GameObjType.Chest: | |||
| return Chest((Chest)gameObj, time); | |||
| case Preparation.Utility.GameObjType.Doorway: | |||
| return Gate((Doorway)gameObj); | |||
| return Gate((Doorway)gameObj, time); | |||
| case Preparation.Utility.GameObjType.EmergencyExit: | |||
| if (((EmergencyExit)gameObj).CanOpen) | |||
| return HiddenGate((EmergencyExit)gameObj); | |||
| @@ -195,13 +195,14 @@ namespace Server | |||
| msg.ClassroomMessage.Progress = generator.DegreeOfRepair; | |||
| return msg; | |||
| } | |||
| private static MessageOfObj Gate(Doorway doorway) | |||
| private static MessageOfObj Gate(Doorway doorway, int time) | |||
| { | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| msg.GateMessage = new(); | |||
| msg.GateMessage.X = doorway.Position.x; | |||
| msg.GateMessage.Y = doorway.Position.y; | |||
| msg.GateMessage.Progress = doorway.OpenDegree; | |||
| int progress = ((doorway.OpenStartTime > 0) ? (time - doorway.OpenStartTime) : 0) + doorway.OpenDegree; | |||
| msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress; | |||
| return msg; | |||
| } | |||
| private static MessageOfObj HiddenGate(EmergencyExit Exit) | |||
| @@ -252,7 +252,7 @@ | |||
| - 特性 | |||
| - 冥想 | |||
| - 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为0.3%/ms | |||
| - 受到攻击(并非伤害)或眩晕或翻窗(或攻击他人)学习进度清零 | |||
| - 受到攻击(并非伤害)或学习或进入不可接受治疗状态(包括翻窗)学习进度清零 | |||
| - 主动技能5 | |||
| - 写答案 | |||
| - CD:30s | |||
| @@ -401,6 +401,7 @@ public: | |||
| ### 人物 | |||
| - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 | |||
| - EndAllAction()及Move指令调用数总和一帧内不超过10次 | |||
| ### 初始状态 | |||
| - 玩家出生点固定且一定为空地 | |||