From 121136cf509123d0d0da44650dcf81ef5fad2de9 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 14 May 2023 22:57:08 +0800 Subject: [PATCH] refactor: :construction: change setPlayerState to the Method of character --- docs/版本更新说明.md | 5 +- .../GameClass/GameObj/Character/Character.cs | 222 ++++++++++++++---- logic/GameClass/GameObj/Immovable.cs | 3 +- logic/GameClass/GameObj/Map/Chest.cs | 5 +- logic/GameClass/GameObj/Map/Doorway.cs | 65 +++-- logic/GameClass/GameObj/Map/Window.cs | 38 +-- logic/GameClass/GameObj/Moveable.cs | 89 ++----- logic/Gaming/ActionManager.cs | 60 ++--- logic/Gaming/AttackManager.cs | 4 +- logic/Gaming/CharacterManager.cs | 83 ++----- .../SkillManager/SkillManager.ActiveSkill.cs | 6 +- logic/Preparation/Interface/IChest.cs | 9 + logic/Preparation/Interface/IDoorway.cs | 12 + logic/Preparation/Interface/IMoveable.cs | 2 +- logic/Preparation/Interface/IWindow.cs | 12 + 15 files changed, 353 insertions(+), 262 deletions(-) create mode 100644 logic/Preparation/Interface/IChest.cs create mode 100644 logic/Preparation/Interface/IDoorway.cs create mode 100644 logic/Preparation/Interface/IWindow.cs diff --git a/docs/版本更新说明.md b/docs/版本更新说明.md index 61f3801..4bb994d 100644 --- a/docs/版本更新说明.md +++ b/docs/版本更新说明.md @@ -30,5 +30,6 @@ - **重复发出同一类型的交互指令和移动指令是无效的** - feat&fix:修复并**将`SendMessage`改为`SendTextMessage`与`SendBinaryMessage`** -# 最新更新 -- docs:更新了 游戏机制与平衡性调整更新草案.pdf \ No newline at end of file +# 5月13日更新 +- docs:更新了 游戏机制与平衡性调整更新草案.pdf +- feat:更新了下载器 \ No newline at end of file diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 1fe012e..3e8622c 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -2,11 +2,16 @@ using Preparation.Utility; using System; using System.Collections.Generic; +using System.Threading; namespace GameClass.GameObj { public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终了 { + + private readonly ReaderWriterLockSlim hpReaderWriterLock = new(); + public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock; + #region 装弹、攻击相关的基本属性及方法 /// /// 装弹冷却 @@ -231,21 +236,65 @@ namespace GameClass.GameObj } #endregion #region 血量相关的基本属性及方法 - public int MaxHp { get; protected set; } // 最大血量 + private int maxHp; + public int MaxHp + { + get + { + HPReadWriterLock.EnterReadLock(); + try + { + return maxHp; + } + finally + { + HPReadWriterLock.ExitReadLock(); + } + } + protected set + { + HPReadWriterLock.EnterWriteLock(); + try + { + maxHp = value; + } + finally + { + HPReadWriterLock.ExitWriteLock(); + } + } + } // 最大血量 protected int hp; public int HP { - get => hp; + get + { + HPReadWriterLock.EnterReadLock(); + try + { + return hp; + } + finally + { + HPReadWriterLock.ExitReadLock(); + } + } set { - if (value > 0) + HPReadWriterLock.EnterWriteLock(); + try { - lock (gameObjLock) + if (value > 0) + { hp = value <= MaxHp ? value : MaxHp; - } - else - lock (gameObjLock) + } + else hp = 0; + } + finally + { + HPReadWriterLock.ExitWriteLock(); + } } } @@ -256,47 +305,62 @@ namespace GameClass.GameObj /// 减操作是否成功 public int TrySubHp(int sub) { - int previousHp = hp; - lock (gameObjLock) - hp = hp <= sub ? 0 : hp - sub; - Debugger.Output(this, " hp has subed to: " + hp.ToString()); - return previousHp - hp; + HPReadWriterLock.EnterWriteLock(); + try + { + int previousHp = hp; + if (hp <= sub) + { + hp = 0; + return hp; + } + else + { + hp -= sub; + return sub; + } + } + finally + { + HPReadWriterLock.ExitWriteLock(); + } } private double vampire = 0; // 回血率:0-1之间 public double Vampire { - get => vampire; - set + get { - if (value > 1) - lock (gameObjLock) - vampire = 1; - else if (value < 0) - lock (gameObjLock) - vampire = 0; - else - lock (gameObjLock) - vampire = value; + HPReadWriterLock.EnterReadLock(); + try + { + return vampire; + } + finally + { + HPReadWriterLock.ExitReadLock(); + } } - } - private double oriVampire = 0; - public double OriVampire - { - get => oriVampire; set { - if (value > 1) - lock (gameObjLock) + HPReadWriterLock.EnterWriteLock(); + try + { + if (value > 1) vampire = 1; - else if (value < 0) - lock (gameObjLock) + else if (value < 0) vampire = 0; - else - lock (gameObjLock) + else vampire = value; + } + finally + { + HPReadWriterLock.ExitWriteLock(); + } } } + private double oriVampire = 0; + public double OriVampire { get; protected set; } #endregion #region 状态相关的基本属性与方法 private PlayerStateType playerState = PlayerStateType.Null; @@ -363,7 +427,7 @@ namespace GameClass.GameObj private GameObj? whatInteractingWith = null; public GameObj? WhatInteractingWith => whatInteractingWith; - public long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + private long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) { //只能被SetPlayerState引用 whatInteractingWith = gameObj; @@ -374,7 +438,7 @@ namespace GameClass.GameObj return ++stateNum; } - public long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + private long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) { //只能被SetPlayerState引用 whatInteractingWith = gameObj; @@ -385,6 +449,74 @@ namespace GameClass.GameObj return stateNum; } + + public long SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + { + lock (actionLock) + { + PlayerStateType nowPlayerState = PlayerState; + if (nowPlayerState == value) return -1; + switch (nowPlayerState) + { + case PlayerStateType.Escaped: + case PlayerStateType.Deceased: + return -1; + + case PlayerStateType.Addicted: + if (value == PlayerStateType.Rescued) + return ChangePlayerStateInOneThread(value, gameObj); + else if (value == PlayerStateType.Null) + return ChangePlayerState(value, gameObj); + else return -1; + case PlayerStateType.Rescued: + if (value == PlayerStateType.Addicted) + return ChangePlayerStateInOneThread(value, gameObj); + else if (value == PlayerStateType.Null) + return ChangePlayerState(value, gameObj); + else return -1; + + case PlayerStateType.TryingToAttack: + if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) + return ChangePlayerState(value, gameObj); + else return -1; + case PlayerStateType.Stunned: + case PlayerStateType.Charmed: + if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows && value != PlayerStateType.Swinging) + return ChangePlayerState(value, gameObj); + else return -1; + case PlayerStateType.Swinging: + if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) + { + ThreadNum.Release(); + return ChangePlayerState(value, gameObj); + } + else return -1; + case PlayerStateType.ClimbingThroughWindows: + if (value != PlayerStateType.Moving) + { + Window window = (Window)WhatInteractingWith!; + window.FinishClimbing(); + if (window.Stage.x == 0) + ThreadNum.Release(); + else ReSetPos(window.Stage); + return ChangePlayerState(value, gameObj); + } + else return -1; + + case PlayerStateType.OpeningTheChest: + ((Chest)WhatInteractingWith!).StopOpen(); + return ChangePlayerState(value, gameObj); + case PlayerStateType.OpeningTheDoorway: + Doorway doorway = (Doorway)WhatInteractingWith!; + doorway.StopOpenning(); + return ChangePlayerState(value, gameObj); + + default: + return ChangePlayerState(value, gameObj); + } + } + } + public long SetPlayerStateNaturally() { lock (actionLock) @@ -398,20 +530,20 @@ namespace GameClass.GameObj public void RemoveFromGame(PlayerStateType playerStateType) { - MoveReaderWriterLock.EnterWriteLock(); - try + lock (actionLock) { - lock (actionLock) + MoveReaderWriterLock.EnterWriteLock(); + try { - playerState = playerStateType; canMove = false; isRemoved = true; - position = GameData.PosWhoDie; } - } - finally - { - MoveReaderWriterLock.ExitWriteLock(); + finally + { + MoveReaderWriterLock.ExitWriteLock(); + } + playerState = playerStateType; + position = GameData.PosWhoDie; } } #endregion diff --git a/logic/GameClass/GameObj/Immovable.cs b/logic/GameClass/GameObj/Immovable.cs index 6662d98..8820399 100644 --- a/logic/GameClass/GameObj/Immovable.cs +++ b/logic/GameClass/GameObj/Immovable.cs @@ -1,5 +1,4 @@ -using Preparation.Interface; -using Preparation.Utility; +using Preparation.Utility; namespace GameClass.GameObj { diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs index 69a1ed9..41e51db 100644 --- a/logic/GameClass/GameObj/Map/Chest.cs +++ b/logic/GameClass/GameObj/Map/Chest.cs @@ -1,11 +1,12 @@ -using Preparation.Utility; +using Preparation.Interface; +using Preparation.Utility; namespace GameClass.GameObj { /// /// 箱子 /// - public class Chest : Immovable + public class Chest : Immovable, IChest { public Chest(XY initPos) : base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest) diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs index 71b2017..5a83588 100644 --- a/logic/GameClass/GameObj/Map/Doorway.cs +++ b/logic/GameClass/GameObj/Map/Doorway.cs @@ -1,12 +1,14 @@ -using Preparation.Interface; +using Google.Protobuf.WellKnownTypes; +using Preparation.Interface; using Preparation.Utility; +using System; namespace GameClass.GameObj { /// /// 出口 /// - public class Doorway : Immovable + public class Doorway : Immovable, IDoorway { public Doorway(XY initPos) : base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Doorway) @@ -25,7 +27,11 @@ namespace GameClass.GameObj private bool powerSupply = false; public bool PowerSupply { - get => powerSupply; + get + { + lock (gameObjLock) + return powerSupply; + } set { lock (gameObjLock) @@ -36,29 +42,58 @@ namespace GameClass.GameObj private int openStartTime = 0; public int OpenStartTime { - get => openStartTime; - set + get { lock (gameObjLock) - openStartTime = value; + return openStartTime; + } + } + public bool TryToOpen() + { + lock (gameObjLock) + { + if (!powerSupply || openStartTime > 0) return false; + openStartTime = Environment.TickCount; + return true; + } + } + + public bool StopOpenning() + { + lock (gameObjLock) + { + if (openDegree + Environment.TickCount - openStartTime >= GameData.degreeOfOpenedDoorway) + { + openDegree = GameData.degreeOfOpenedDoorway; + return true; + } + else + { + openDegree = openDegree + Environment.TickCount - openStartTime; + openStartTime = 0; + return false; + } + } + } + + public void FinishOpenning() + { + lock (gameObjLock) + { + openDegree = GameData.degreeOfOpenedDoorway; } } private int openDegree = 0; public int OpenDegree { - get => openDegree; - set + get { - if (value > 0) - lock (gameObjLock) - openDegree = (value < GameData.degreeOfOpenedDoorway) ? value : GameData.degreeOfOpenedDoorway; - else - lock (gameObjLock) - openDegree = 0; + lock (gameObjLock) + return openDegree; } } - public bool IsOpen() => (openDegree == GameData.degreeOfOpenedDoorway); + public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway); } } diff --git a/logic/GameClass/GameObj/Map/Window.cs b/logic/GameClass/GameObj/Map/Window.cs index 50fd308..e864a55 100644 --- a/logic/GameClass/GameObj/Map/Window.cs +++ b/logic/GameClass/GameObj/Map/Window.cs @@ -1,14 +1,12 @@ using Preparation.Interface; using Preparation.Utility; -using System.Numerics; -using System; namespace GameClass.GameObj { /// /// 窗 /// - public class Window : Immovable + public class Window : Immovable, IWindow { public Window(XY initPos) : base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Window) @@ -32,12 +30,8 @@ namespace GameClass.GameObj { get { - GameObjReaderWriterLock.EnterReadLock(); - try - { + lock (gameObjLock) return stage; - } - finally { GameObjReaderWriterLock.ExitReadLock(); } } } @@ -46,47 +40,31 @@ namespace GameClass.GameObj { get { - GameObjReaderWriterLock.EnterReadLock(); - try - { + lock (gameObjLock) return whoIsClimbing; - } - finally { GameObjReaderWriterLock.ExitReadLock(); } } } - public bool TryToClimb(Character character) + public bool TryToClimb(ICharacter character) { - GameObjReaderWriterLock.EnterWriteLock(); - try - { + lock (gameObjLock) if (whoIsClimbing == null) { stage = new(0, 0); - whoIsClimbing = character; + whoIsClimbing = (Character)character; return true; } else return false; - } - finally { GameObjReaderWriterLock.ExitWriteLock(); } } public void FinishClimbing() { - GameObjReaderWriterLock.EnterWriteLock(); - try - { + lock (gameObjLock) whoIsClimbing = null; - } - finally { GameObjReaderWriterLock.ExitWriteLock(); } } public void Enter2Stage(XY xy) { - GameObjReaderWriterLock.EnterWriteLock(); - try - { + lock (gameObjLock) stage = xy; - } - finally { GameObjReaderWriterLock.ExitWriteLock(); } } } } diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs index 2c78489..ff124df 100644 --- a/logic/GameClass/GameObj/Moveable.cs +++ b/logic/GameClass/GameObj/Moveable.cs @@ -11,19 +11,9 @@ namespace GameClass.GameObj //player.actionLock>其他.actionLock private readonly ReaderWriterLockSlim moveReaderWriterLock = new(); public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock; + //规定moveReaderWriterLockactionLock public override XY Position { @@ -81,20 +70,20 @@ namespace GameClass.GameObj if (moveVec.x != 0 || moveVec.y != 0) { - moveReaderWriterLock.EnterReadLock(); - try + lock (actionLock) { - lock (actionLock) + moveReaderWriterLock.EnterReadLock(); + try { if (!canMove || isRemoved) return -1; - if (stateNo != stateNum) return -1; - facingDirection = moveVec; - this.position += moveVec; } - } - finally - { - moveReaderWriterLock.ExitReadLock(); + finally + { + moveReaderWriterLock.ExitReadLock(); + } + if (stateNo != stateNum) return -1; + facingDirection = moveVec; + this.position += moveVec; } } return moveVec * moveVec; @@ -129,10 +118,7 @@ namespace GameClass.GameObj moveReaderWriterLock.EnterWriteLock(); try { - lock (actionLock) - { - canMove = value; - } + canMove = value; } finally { @@ -161,52 +147,29 @@ namespace GameClass.GameObj { get { - moveReaderWriterLock.EnterReadLock(); - try + lock (actionLock) { - lock (actionLock) + moveReaderWriterLock.EnterReadLock(); + try + { return !isMoving && canMove && !isRemoved; - } - finally - { - moveReaderWriterLock.ExitReadLock(); + } + finally + { + moveReaderWriterLock.ExitReadLock(); + } } } } - protected int moveSpeed; + protected long moveSpeed; /// /// 移动速度 /// - public int MoveSpeed + public long MoveSpeed { - get - { - moveReaderWriterLock.EnterReadLock(); - try - { - return moveSpeed; - } - finally - { - moveReaderWriterLock.ExitReadLock(); - } - } - set - { - moveReaderWriterLock.EnterWriteLock(); - try - { - lock (actionLock) - { - moveSpeed = value; - } - } - finally - { - moveReaderWriterLock.ExitWriteLock(); - } - } + get => Interlocked.Read(ref moveSpeed); + set => Interlocked.Exchange(ref moveSpeed, value); } /// /// 原初移动速度 diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 1cc5dab..a8196bd 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -36,7 +36,7 @@ namespace Gaming public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { if (moveTimeInMilliseconds < 5) return false; - long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving); + long stateNum = playerToMove.SetPlayerState(PlayerStateType.Moving); if (stateNum == -1) return false; new Thread ( @@ -56,7 +56,7 @@ namespace Gaming public bool MovePlayerWhenStunned(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { if (playerToMove.CharacterType == CharacterType.Robot) return false; - long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Charmed); + long stateNum = playerToMove.SetPlayerState(PlayerStateType.Charmed); if (stateNum == -1) return false; new Thread (() => @@ -86,7 +86,7 @@ namespace Gaming { if (player.Commandable()) { - characterManager.SetPlayerState(player); + player.SetPlayerState(); return true; } } @@ -103,7 +103,7 @@ namespace Gaming return false; ++generatorForFix.NumOfFixing; - characterManager.SetPlayerState(player, PlayerStateType.Fixing); + player.SetPlayerState(PlayerStateType.Fixing); long threadNum = player.StateNum; new Thread ( @@ -117,7 +117,7 @@ namespace Gaming if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) gameMap.NumOfRepairedGenerators++; if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) - characterManager.SetPlayerState(player); + player.SetPlayerState(); }, timeInterval: GameData.frameDuration, finallyReturn: () => 0 @@ -134,24 +134,26 @@ namespace Gaming public bool OpenDoorway(Student player) { - if (!(player.Commandable()) || player.PlayerState == PlayerStateType.OpeningTheDoorway) + if (!(player.Commandable())) return false; Doorway? doorwayToOpen = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); - if (doorwayToOpen == null || doorwayToOpen.OpenStartTime > 0 || !doorwayToOpen.PowerSupply) - return false; + if (doorwayToOpen == null) return false; - characterManager.SetPlayerState(player, PlayerStateType.OpeningTheDoorway, doorwayToOpen); - int startTime = doorwayToOpen.OpenStartTime = gameMap.Timer.nowTime(); + long stateNum = player.SetPlayerState(PlayerStateType.OpeningTheDoorway, doorwayToOpen); + if (stateNum == -1) return false; new Thread ( () => { + //player.ThreadNum.WaitOne(); Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree); - - if (doorwayToOpen.OpenStartTime == startTime) + lock (player.ActionLock) { - doorwayToOpen.OpenDegree = GameData.degreeOfOpenedDoorway; - player.SetPlayerStateNaturally(); + if (stateNum == player.StateNum) + { + player.SetPlayerStateNaturally(); + doorwayToOpen.FinishOpenning(); + } } } @@ -203,8 +205,8 @@ namespace Gaming ( () => { - characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated); - characterManager.SetPlayerState(player, PlayerStateType.Treating); + playerTreated.SetPlayerState(PlayerStateType.Treated); + player.SetPlayerState(PlayerStateType.Treating); long threadNum = player.StateNum; new FrameRateTaskExecutor( @@ -212,15 +214,15 @@ namespace Gaming loopToDo: () => { if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) - characterManager.SetPlayerState(playerTreated); + playerTreated.SetPlayerState(); }, timeInterval: GameData.frameDuration, finallyReturn: () => 0 ) .Start(); - if (threadNum == player.StateNum) characterManager.SetPlayerState(player); - else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated); + if (threadNum == player.StateNum) player.SetPlayerState(); + else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState(); } ) { IsBackground = true }.Start(); @@ -235,8 +237,8 @@ namespace Gaming } if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) return false; - characterManager.SetPlayerState(player, PlayerStateType.Rescuing); - characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued); + player.SetPlayerState(PlayerStateType.Rescuing); + playerRescued.SetPlayerState(PlayerStateType.Rescued); long threadNum = player.StateNum; new Thread @@ -259,14 +261,14 @@ namespace Gaming { if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue) { - characterManager.SetPlayerState(playerRescued); + playerRescued.SetPlayerState(); playerRescued.HP = playerRescued.MaxHp / 2; player.AddScore(GameData.StudentScoreRescue); } else - characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted); + playerRescued.SetPlayerState(PlayerStateType.Addicted); } - if (threadNum == player.StateNum) characterManager.SetPlayerState(player); + if (threadNum == player.StateNum) player.SetPlayerState(); playerRescued.TimeOfRescue = 0; } ) @@ -283,7 +285,7 @@ namespace Gaming if (chestToOpen == null || chestToOpen.OpenStartTime > 0) return false; - characterManager.SetPlayerState(player, PlayerStateType.OpeningTheChest, chestToOpen); + player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen); int startTime = gameMap.Timer.nowTime(); chestToOpen.Open(startTime, player); new Thread @@ -315,7 +317,7 @@ namespace Gaming Window? windowForClimb = (Window?)gameMap.OneForInteractInACross(player.Position, GameObjType.Window); if (windowForClimb == null) return false; - long stateNum = characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows, windowForClimb); + long stateNum = player.SetPlayerState(PlayerStateType.ClimbingThroughWindows, windowForClimb); if (stateNum == -1) return false; XY windowToPlayer = new( @@ -371,7 +373,7 @@ namespace Gaming { if (stateNum == player.StateNum) { - characterManager.SetPlayerState(player); + player.SetPlayerState(); windowForClimb.FinishClimbing(); } } @@ -414,7 +416,7 @@ namespace Gaming } if (!flag) return false; - characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor); + player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor); long threadNum = player.StateNum; new Thread ( @@ -436,7 +438,7 @@ namespace Gaming doorToLock.IsOpen = (!doorToLock.IsOpen); } if (threadNum == player.StateNum) - characterManager.SetPlayerState(player); + player.SetPlayerState(); doorToLock.OpenOrLockDegree = 0; } diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 76338d9..e551bad 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -200,7 +200,7 @@ namespace Gaming if (bullet.CastTime > 0) { - characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); + player.SetPlayerState(PlayerStateType.TryingToAttack); long threadNum = player.StateNum; new Thread @@ -221,7 +221,7 @@ namespace Gaming { if (threadNum == player.StateNum) { - characterManager.SetPlayerState(player); + player.SetPlayerState(); } else TryRemoveBullet(bullet); } diff --git a/logic/Gaming/CharacterManager.cs b/logic/Gaming/CharacterManager.cs index c0f0f91..0645f1d 100644 --- a/logic/Gaming/CharacterManager.cs +++ b/logic/Gaming/CharacterManager.cs @@ -17,65 +17,6 @@ namespace Gaming this.gameMap = gameMap; } - public long SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) - { - lock (player.ActionLock) - { - PlayerStateType nowPlayerState = player.PlayerState; - if (nowPlayerState == value) return -1; - switch (nowPlayerState) - { - case PlayerStateType.Escaped: - case PlayerStateType.Deceased: - return -1; - - case PlayerStateType.Addicted: - if (value == PlayerStateType.Rescued) - return player.ChangePlayerStateInOneThread(value, gameObj); - else if (value == PlayerStateType.Null) - return player.ChangePlayerState(value, gameObj); - else return -1; - case PlayerStateType.Rescued: - if (value == PlayerStateType.Addicted) - return player.ChangePlayerStateInOneThread(value, gameObj); - else if (value == PlayerStateType.Null) - return player.ChangePlayerState(value, gameObj); - else return -1; - - case PlayerStateType.TryingToAttack: - case PlayerStateType.Stunned: - case PlayerStateType.Charmed: - case PlayerStateType.Swinging: - if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) - return player.ChangePlayerState(value, gameObj); - else return -1; - case PlayerStateType.ClimbingThroughWindows: - if (value != PlayerStateType.Moving) - { - Window window = (Window)player.WhatInteractingWith!; - window.FinishClimbing(); - if (window.Stage.x == 0) - player.ThreadNum.Release(); - else player.ReSetPos(window.Stage); - return player.ChangePlayerState(value, gameObj); - } - else return -1; - - case PlayerStateType.OpeningTheChest: - ((Chest)player.WhatInteractingWith!).StopOpen(); - return player.ChangePlayerState(value, gameObj); - case PlayerStateType.OpeningTheDoorway: - Doorway doorway = (Doorway)player.WhatInteractingWith!; - doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; - doorway.OpenStartTime = 0; - return player.ChangePlayerState(value, gameObj); - - default: - return player.ChangePlayerState(value, gameObj); - } - } - } - public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null) { Character newPlayer; @@ -268,7 +209,7 @@ namespace Gaming return; } } - SetPlayerState(player, PlayerStateType.Addicted); + player.SetPlayerState(PlayerStateType.Addicted); long threadNum = player.StateNum; new Thread (() => @@ -302,14 +243,14 @@ namespace Gaming public long BeStunned(Character player, int time) { if (player.CharacterType == CharacterType.Robot) return -1; - long threadNum = SetPlayerState(player, PlayerStateType.Stunned); + long threadNum = player.SetPlayerState(PlayerStateType.Stunned); if (threadNum == -1) return -1; new Thread (() => { Thread.Sleep(time); if (threadNum == player.StateNum) - SetPlayerState(player); + player.SetPlayerState(); } ) { IsBackground = true }.Start(); @@ -339,7 +280,6 @@ namespace Gaming #if DEBUG Debugger.Output(student, "is being shot!"); #endif - if (student.NoHp()) return; // 原来已经死了 if (!bullet.Parent!.IsGhost()) return; if (student.CharacterType == CharacterType.StraightAStudent) @@ -347,6 +287,9 @@ namespace Gaming ((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0; } student.SetDegreeOfTreatment0(); + + if (student.NoHp()) return; // 原来已经死了 + #if DEBUG Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString()); #endif @@ -394,18 +337,22 @@ namespace Gaming public bool BackSwing(Character player, int time) { if (time <= 0) return false; - if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false; - SetPlayerState(player, PlayerStateType.Swinging); - long threadNum = player.StateNum; + long stateNum = player.SetPlayerState(PlayerStateType.Swinging); + if (stateNum == -1) return false; new Thread (() => { + player.ThreadNum.WaitOne(); Thread.Sleep(time); - if (threadNum == player.StateNum) + lock (player.ActionLock) { - SetPlayerState(player); + if (stateNum == player.StateNum) + { + player.ThreadNum.Release(); + player.SetPlayerStateNaturally(); + } } } ) diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index b04aa8e..b9b5d7a 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -111,8 +111,8 @@ namespace Gaming Debugger.Output(player, "use robot!"); IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.UseRobot); activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true; - if (activeSkill.IsBeingUsed) characterManager.SetPlayerState(player, PlayerStateType.UsingSkill); - else characterManager.SetPlayerState(player); + if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill); + else player.SetPlayerState(); return true; } @@ -247,7 +247,7 @@ namespace Gaming { if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character)) { - characterManager.SetPlayerState(character); + character.SetPlayerState(); character.HP = GameData.RemainHpWhenAddLife; ((Student)character).TimeOfRescue = 0; player.AddScore(GameData.StudentScoreRescue); diff --git a/logic/Preparation/Interface/IChest.cs b/logic/Preparation/Interface/IChest.cs new file mode 100644 index 0000000..d787cde --- /dev/null +++ b/logic/Preparation/Interface/IChest.cs @@ -0,0 +1,9 @@ +using Preparation.Utility; + +namespace Preparation.Interface +{ + public interface IChest : IGameObj + { + public void StopOpen(); + } +} \ No newline at end of file diff --git a/logic/Preparation/Interface/IDoorway.cs b/logic/Preparation/Interface/IDoorway.cs new file mode 100644 index 0000000..e4fe0cc --- /dev/null +++ b/logic/Preparation/Interface/IDoorway.cs @@ -0,0 +1,12 @@ +using Preparation.Utility; + +namespace Preparation.Interface +{ + public interface IDoorway : IGameObj + { + public int OpenStartTime { get; } + public int OpenDegree { get; } + public bool StopOpenning(); + public bool TryToOpen(); + } +} \ No newline at end of file diff --git a/logic/Preparation/Interface/IMoveable.cs b/logic/Preparation/Interface/IMoveable.cs index 01577c7..ad87c31 100644 --- a/logic/Preparation/Interface/IMoveable.cs +++ b/logic/Preparation/Interface/IMoveable.cs @@ -12,7 +12,7 @@ namespace Preparation.Interface public bool IsRemoved { get; } public bool IsAvailableForMove { get; } public long StateNum { get; } - public Semaphore ThreadNum { get; set; } + public Semaphore ThreadNum { get; } public long MovingSetPos(XY moveVec, long stateNum); public void ReSetCanMove(bool value); public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞 diff --git a/logic/Preparation/Interface/IWindow.cs b/logic/Preparation/Interface/IWindow.cs new file mode 100644 index 0000000..d68e548 --- /dev/null +++ b/logic/Preparation/Interface/IWindow.cs @@ -0,0 +1,12 @@ +using Preparation.Utility; + +namespace Preparation.Interface +{ + public interface IWindow : IGameObj + { + public void Enter2Stage(XY xy); + public bool TryToClimb(ICharacter character); + public XY Stage { get; } + public void FinishClimbing(); + } +} \ No newline at end of file