refactor: 🚧 add tool, gadget,and item
tags/v0.1.0
| @@ -316,6 +316,7 @@ $$ | |||||
| ### 道具 | ### 道具 | ||||
| - 使用钥匙相当于销毁 | - 使用钥匙相当于销毁 | ||||
| - 可接受指令状态下能捡起或扔道具,在场上即可使用道具 | |||||
| ### 交互 | ### 交互 | ||||
| - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 | - 被唤醒或被勉励不属于交互状态,翻窗属于交互状态 | ||||
| @@ -35,7 +35,7 @@ namespace GameClass.GameObj | |||||
| public override bool IgnoreCollideExecutor(IGameObj targetObj) | public override bool IgnoreCollideExecutor(IGameObj targetObj) | ||||
| { | { | ||||
| if (targetObj == Parent) return true; | if (targetObj == Parent) return true; | ||||
| if (targetObj.Type == GameObjType.Consumables || targetObj.Type == GameObjType.Bullet) | |||||
| if (targetObj.Type == GameObjType.Gadget || targetObj.Type == GameObjType.Bullet) | |||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -141,7 +141,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| public override void AddScore(int add) | |||||
| public override void AddScore(long add) | |||||
| { | { | ||||
| if (parent == null) | if (parent == null) | ||||
| base.AddScore(add); | base.AddScore(add); | ||||
| @@ -11,6 +11,10 @@ namespace GameClass.GameObj | |||||
| private readonly ReaderWriterLockSlim hpReaderWriterLock = new(); | private readonly ReaderWriterLockSlim hpReaderWriterLock = new(); | ||||
| public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock; | public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock; | ||||
| private readonly object vampireLock = new(); | |||||
| public object VampireLock => vampire; | |||||
| private readonly object inventoryLock = new(); | |||||
| public object InventoryLock => inventoryLock; | |||||
| #region 装弹、攻击相关的基本属性及方法 | #region 装弹、攻击相关的基本属性及方法 | ||||
| /// <summary> | /// <summary> | ||||
| @@ -331,20 +335,12 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| HPReadWriterLock.EnterReadLock(); | |||||
| try | |||||
| { | |||||
| lock (vampireLock) | |||||
| return vampire; | return vampire; | ||||
| } | |||||
| finally | |||||
| { | |||||
| HPReadWriterLock.ExitReadLock(); | |||||
| } | |||||
| } | } | ||||
| set | set | ||||
| { | { | ||||
| HPReadWriterLock.EnterWriteLock(); | |||||
| try | |||||
| lock (vampireLock) | |||||
| { | { | ||||
| if (value > 1) | if (value > 1) | ||||
| vampire = 1; | vampire = 1; | ||||
| @@ -353,10 +349,6 @@ namespace GameClass.GameObj | |||||
| else | else | ||||
| vampire = value; | vampire = value; | ||||
| } | } | ||||
| finally | |||||
| { | |||||
| HPReadWriterLock.ExitWriteLock(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| public double OriVampire { get; protected set; } | public double OriVampire { get; protected set; } | ||||
| @@ -404,7 +396,8 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| lock (actionLock) | lock (actionLock) | ||||
| { | { | ||||
| return (playerState == PlayerStateType.LockingOrOpeningTheDoor || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest); | |||||
| return (playerState == PlayerStateType.LockingTheDoor || playerState == PlayerStateType.OpeningTheDoor | |||||
| || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest); | |||||
| } | } | ||||
| } | } | ||||
| public bool NullOrMoving() | public bool NullOrMoving() | ||||
| @@ -475,41 +468,75 @@ namespace GameClass.GameObj | |||||
| else return -1; | else return -1; | ||||
| case PlayerStateType.TryingToAttack: | case PlayerStateType.TryingToAttack: | ||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) | |||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows | |||||
| && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) | |||||
| return ChangePlayerState(value, gameObj); | return ChangePlayerState(value, gameObj); | ||||
| else return -1; | else return -1; | ||||
| case PlayerStateType.Stunned: | case PlayerStateType.Stunned: | ||||
| case PlayerStateType.Charmed: | case PlayerStateType.Charmed: | ||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows && value != PlayerStateType.Swinging) | |||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows | |||||
| && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor | |||||
| && value != PlayerStateType.Swinging) | |||||
| return ChangePlayerState(value, gameObj); | return ChangePlayerState(value, gameObj); | ||||
| else return -1; | else return -1; | ||||
| case PlayerStateType.Swinging: | case PlayerStateType.Swinging: | ||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows) | |||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows | |||||
| && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) | |||||
| { | { | ||||
| ThreadNum.Release(); | |||||
| return ChangePlayerState(value, gameObj); | |||||
| try | |||||
| { | |||||
| return ChangePlayerState(value, gameObj); | |||||
| } | |||||
| finally | |||||
| { | |||||
| ThreadNum.Release(); | |||||
| } | |||||
| } | } | ||||
| else return -1; | else return -1; | ||||
| case PlayerStateType.ClimbingThroughWindows: | case PlayerStateType.ClimbingThroughWindows: | ||||
| if (value != PlayerStateType.Moving) | |||||
| if (value != PlayerStateType.Moving && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) | |||||
| { | { | ||||
| Window window = (Window)WhatInteractingWith!; | Window window = (Window)WhatInteractingWith!; | ||||
| window.FinishClimbing(); | |||||
| if (window.Stage.x == 0) | |||||
| ThreadNum.Release(); | |||||
| else ReSetPos(window.Stage); | |||||
| return ChangePlayerState(value, gameObj); | |||||
| try | |||||
| { | |||||
| window.FinishClimbing(); | |||||
| return ChangePlayerState(value, gameObj); | |||||
| } | |||||
| finally | |||||
| { | |||||
| if (window.Stage.x == 0) | |||||
| ThreadNum.Release(); | |||||
| else ReSetPos(window.Stage); | |||||
| } | |||||
| } | } | ||||
| else return -1; | else return -1; | ||||
| case PlayerStateType.OpeningTheChest: | case PlayerStateType.OpeningTheChest: | ||||
| ((Chest)WhatInteractingWith!).StopOpen(); | |||||
| ((Chest)whatInteractingWith!).StopOpen(); | |||||
| return ChangePlayerState(value, gameObj); | return ChangePlayerState(value, gameObj); | ||||
| case PlayerStateType.OpeningTheDoorway: | case PlayerStateType.OpeningTheDoorway: | ||||
| Doorway doorway = (Doorway)WhatInteractingWith!; | |||||
| Doorway doorway = (Doorway)whatInteractingWith!; | |||||
| doorway.StopOpenning(); | doorway.StopOpenning(); | ||||
| return ChangePlayerState(value, gameObj); | return ChangePlayerState(value, gameObj); | ||||
| case PlayerStateType.OpeningTheDoor: | |||||
| Door door = (Door)whatInteractingWith!; | |||||
| try | |||||
| { | |||||
| door.StopOpen(); | |||||
| ReleaseTool(door.DoorNum switch | |||||
| { | |||||
| 3 => PropType.Key3, | |||||
| 5 => PropType.Key5, | |||||
| _ => PropType.Key6, | |||||
| } | |||||
| ); | |||||
| return ChangePlayerState(value, gameObj); | |||||
| } | |||||
| finally | |||||
| { | |||||
| ThreadNum.Release(); | |||||
| } | |||||
| default: | default: | ||||
| return ChangePlayerState(value, gameObj); | return ChangePlayerState(value, gameObj); | ||||
| } | } | ||||
| @@ -547,67 +574,52 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| #endregion | #endregion | ||||
| private int score = 0; | |||||
| public int Score | |||||
| private long score = 0; | |||||
| public long Score | |||||
| { | { | ||||
| get => score; | |||||
| get => Interlocked.Read(ref score); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// 加分 | /// 加分 | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="add">增加量</param> | /// <param name="add">增加量</param> | ||||
| public virtual void AddScore(int add) | |||||
| public virtual void AddScore(long add) | |||||
| { | { | ||||
| lock (gameObjLock) | |||||
| { | |||||
| score += add; | |||||
| //Debugger.Output(this, " 's score has been added to: " + score.ToString()); | |||||
| } | |||||
| Interlocked.Add(ref score, add); | |||||
| //Debugger.Output(this, " 's score has been added to: " + score.ToString()); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// 角色所属队伍ID | /// 角色所属队伍ID | ||||
| /// </summary> | /// </summary> | ||||
| private int teamID = int.MaxValue; | |||||
| public int TeamID | |||||
| private long teamID = long.MaxValue; | |||||
| public long TeamID | |||||
| { | { | ||||
| get => teamID; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| teamID = value; | |||||
| Debugger.Output(this, " joins in the team: " + value.ToString()); | |||||
| } | |||||
| } | |||||
| get => Interlocked.Read(ref teamID); | |||||
| set => Interlocked.Exchange(ref teamID, value); | |||||
| } | } | ||||
| private int playerID = int.MaxValue; | |||||
| public int PlayerID | |||||
| private long playerID = long.MaxValue; | |||||
| public long PlayerID | |||||
| { | { | ||||
| get => playerID; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| playerID = value; | |||||
| } | |||||
| } | |||||
| get => Interlocked.Read(ref playerID); | |||||
| set => Interlocked.Exchange(ref playerID, value); | |||||
| } | } | ||||
| #region 道具和buff相关属性、方法 | #region 道具和buff相关属性、方法 | ||||
| private Consumables[] propInventory = new Consumables[GameData.maxNumOfPropInPropInventory] | |||||
| private Gadget[] propInventory = new Gadget[GameData.maxNumOfPropInPropInventory] | |||||
| {new NullProp(), new NullProp(),new NullProp() }; | {new NullProp(), new NullProp(),new NullProp() }; | ||||
| public Consumables[] PropInventory | |||||
| public Gadget[] PropInventory | |||||
| { | { | ||||
| get => propInventory; | |||||
| get | |||||
| { | |||||
| lock (inventoryLock) | |||||
| return propInventory; | |||||
| } | |||||
| set | set | ||||
| { | { | ||||
| lock (gameObjLock) | |||||
| { | |||||
| lock (inventoryLock) | |||||
| propInventory = value; | propInventory = value; | ||||
| Debugger.Output(this, " prop becomes " + (PropInventory == null ? "null" : PropInventory.ToString())); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -615,45 +627,81 @@ namespace GameClass.GameObj | |||||
| /// 使用物品栏中的道具 | /// 使用物品栏中的道具 | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns>被使用的道具</returns> | /// <returns>被使用的道具</returns> | ||||
| public Consumables UseProp(int indexing) | |||||
| public Gadget UseProp(int indexing) | |||||
| { | { | ||||
| if (indexing < 0 || indexing >= GameData.maxNumOfPropInPropInventory) | if (indexing < 0 || indexing >= GameData.maxNumOfPropInPropInventory) | ||||
| return new NullProp(); | return new NullProp(); | ||||
| lock (gameObjLock) | |||||
| lock (inventoryLock) | |||||
| { | { | ||||
| Consumables prop = propInventory[indexing]; | |||||
| Gadget prop = propInventory[indexing]; | |||||
| if (!prop.IsUsable()) return new NullProp(); | |||||
| PropInventory[indexing] = new NullProp(); | PropInventory[indexing] = new NullProp(); | ||||
| return prop; | return prop; | ||||
| } | } | ||||
| } | } | ||||
| public Consumables UseProp(PropType propType) | |||||
| public Gadget UseProp(PropType propType) | |||||
| { | { | ||||
| lock (gameObjLock) | |||||
| if (propType == PropType.Null) | |||||
| { | { | ||||
| if (propType == PropType.Null) | |||||
| lock (inventoryLock) | |||||
| { | { | ||||
| for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | ||||
| { | { | ||||
| if (PropInventory[indexing].GetPropType() != PropType.Null) | |||||
| if (PropInventory[indexing].IsUsable()) | |||||
| { | { | ||||
| Consumables prop = PropInventory[indexing]; | |||||
| Gadget prop = PropInventory[indexing]; | |||||
| PropInventory[indexing] = new NullProp(); | PropInventory[indexing] = new NullProp(); | ||||
| return prop; | return prop; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else | |||||
| } | |||||
| else | |||||
| { | |||||
| lock (inventoryLock) | |||||
| { | |||||
| for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | ||||
| { | { | ||||
| if (PropInventory[indexing].GetPropType() == propType) | |||||
| if (PropInventory[indexing].GetPropType() == propType && PropInventory[indexing].IsUsable()) | |||||
| { | { | ||||
| Consumables prop = PropInventory[indexing]; | |||||
| Gadget prop = PropInventory[indexing]; | |||||
| PropInventory[indexing] = new NullProp(); | PropInventory[indexing] = new NullProp(); | ||||
| return prop; | return prop; | ||||
| } | } | ||||
| } | } | ||||
| return new NullProp(); | |||||
| } | |||||
| } | |||||
| return new NullProp(); | |||||
| } | |||||
| public bool UseTool(PropType propType) | |||||
| { | |||||
| lock (inventoryLock) | |||||
| { | |||||
| for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | |||||
| { | |||||
| if (PropInventory[indexing].GetPropType() == propType && PropInventory[indexing].IsUsable()) | |||||
| { | |||||
| return ((Tool)PropInventory[indexing]).IsUsed = true; | |||||
| } | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void ReleaseTool(PropType propType) | |||||
| { | |||||
| lock (inventoryLock) | |||||
| { | |||||
| for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | |||||
| { | |||||
| if (PropInventory[indexing].GetPropType() == propType && ((Tool)PropInventory[indexing]).IsUsed) | |||||
| { | |||||
| ((Tool)PropInventory[indexing]).IsUsed = false; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -663,9 +711,10 @@ namespace GameClass.GameObj | |||||
| public int IndexingOfAddProp() | public int IndexingOfAddProp() | ||||
| { | { | ||||
| int indexing = 0; | int indexing = 0; | ||||
| for (; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | |||||
| if (PropInventory[indexing].GetPropType() == PropType.Null) | |||||
| break; | |||||
| lock (inventoryLock) | |||||
| for (; indexing < GameData.maxNumOfPropInPropInventory; ++indexing) | |||||
| if (propInventory[indexing].GetPropType() == PropType.Null) | |||||
| break; | |||||
| return indexing; | return indexing; | ||||
| } | } | ||||
| @@ -787,7 +836,7 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| if (IsRemoved) | if (IsRemoved) | ||||
| return true; | return true; | ||||
| if (targetObj.Type == GameObjType.Consumables) | |||||
| if (targetObj.Type == GameObjType.Gadget) | |||||
| { | { | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -17,7 +17,7 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| int score = 0; | int score = 0; | ||||
| foreach (var player in playerList) | foreach (var player in playerList) | ||||
| score += player.Score; | |||||
| score += (int)player.Score; | |||||
| return score; | return score; | ||||
| } | } | ||||
| } | } | ||||
| @@ -15,8 +15,8 @@ namespace GameClass.GameObj | |||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| public override ShapeType Shape => ShapeType.Square; | public override ShapeType Shape => ShapeType.Square; | ||||
| private readonly Consumables[] propInChest = new Consumables[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() }; | |||||
| public Consumables[] PropInChest => propInChest; | |||||
| private readonly Gadget[] propInChest = new Gadget[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() }; | |||||
| public Gadget[] PropInChest => propInChest; | |||||
| private int openStartTime = 0; | private int openStartTime = 0; | ||||
| public int OpenStartTime => openStartTime; | public int OpenStartTime => openStartTime; | ||||
| @@ -1,5 +1,7 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | |||||
| using System.Threading; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -32,30 +34,123 @@ namespace GameClass.GameObj | |||||
| public override bool IsRigid => !isOpen; | public override bool IsRigid => !isOpen; | ||||
| public override ShapeType Shape => ShapeType.Square; | public override ShapeType Shape => ShapeType.Square; | ||||
| private Character? whoLockOrOpen = null; | |||||
| public Character? WhoLockOrOpen | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (gameObjLock) | |||||
| return whoLockOrOpen; | |||||
| } | |||||
| } | |||||
| private bool isOpen = true; | private bool isOpen = true; | ||||
| public bool IsOpen | public bool IsOpen | ||||
| { | { | ||||
| get => isOpen; | |||||
| set | |||||
| get | |||||
| { | { | ||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| isOpen = value; | |||||
| return isOpen; | |||||
| } | } | ||||
| } | } | ||||
| private int openOrLockDegree = 0; | |||||
| public int OpenOrLockDegree | |||||
| private int lockDegree = 0; | |||||
| public int LockDegree | |||||
| { | { | ||||
| get => openOrLockDegree; | |||||
| get | |||||
| { | |||||
| lock (gameObjLock) | |||||
| return lockDegree; | |||||
| } | |||||
| set | set | ||||
| { | { | ||||
| if (value > 0) | |||||
| lock (gameObjLock) | |||||
| openOrLockDegree = (value > GameData.degreeOfLockingOrOpeningTheDoor) ? GameData.degreeOfLockingOrOpeningTheDoor : value; | |||||
| else | |||||
| lock (gameObjLock) | |||||
| openOrLockDegree = 0; | |||||
| value = (value > GameData.degreeOfLockingOrOpeningTheDoor) ? GameData.degreeOfLockingOrOpeningTheDoor : value; | |||||
| lock (gameObjLock) | |||||
| lockDegree = value; | |||||
| } | |||||
| } | |||||
| private long openStartTime = 0; | |||||
| public long OpenStartTime | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (gameObjLock) | |||||
| return openStartTime; | |||||
| } | |||||
| } | |||||
| public bool TryOpen(Character character) | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| if (isOpen) return false; | |||||
| if (whoLockOrOpen != null) return false; | |||||
| openStartTime = Environment.TickCount64; | |||||
| whoLockOrOpen = character; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| public void StopOpen() | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| if (whoLockOrOpen != null) | |||||
| { | |||||
| if (Environment.TickCount64 - openStartTime >= GameData.degreeOfLockingOrOpeningTheDoor) | |||||
| isOpen = true; | |||||
| whoLockOrOpen = null; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void FinishOpen() | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| isOpen = true; | |||||
| whoLockOrOpen = null; | |||||
| } | |||||
| } | |||||
| public bool TryLock(Character character) | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| if (!isOpen) return false; | |||||
| if (whoLockOrOpen != null) return false; | |||||
| lockDegree = 0; | |||||
| whoLockOrOpen = character; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| public void StopLock() | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| if (lockDegree >= GameData.degreeOfLockingOrOpeningTheDoor) | |||||
| isOpen = true; | |||||
| whoLockOrOpen = null; | |||||
| } | |||||
| } | |||||
| public void FinishLock() | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| isOpen = false; | |||||
| whoLockOrOpen = null; | |||||
| } | |||||
| } | |||||
| public void ForceToOpen() | |||||
| { | |||||
| Character? character; | |||||
| lock (gameObjLock) | |||||
| { | |||||
| character = whoLockOrOpen; | |||||
| whoLockOrOpen = null; | |||||
| isOpen = true; | |||||
| } | } | ||||
| if (character != null) character.SetPlayerState(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,15 +1,16 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System.Threading; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| public abstract class Consumables : ObjOfCharacter | |||||
| public abstract class Gadget : ObjOfCharacter | |||||
| { | { | ||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| public override bool IgnoreCollideExecutor(IGameObj targetObj) | public override bool IgnoreCollideExecutor(IGameObj targetObj) | ||||
| { | { | ||||
| if (targetObj.Type == GameObjType.Consumables || targetObj.Type == GameObjType.Bullet | |||||
| if (targetObj.Type == GameObjType.Gadget || targetObj.Type == GameObjType.Bullet | |||||
| || targetObj.Type == GameObjType.Character || targetObj.Type == GameObjType.Chest) | || targetObj.Type == GameObjType.Character || targetObj.Type == GameObjType.Chest) | ||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| @@ -17,21 +18,47 @@ namespace GameClass.GameObj | |||||
| public override ShapeType Shape => ShapeType.Square; | public override ShapeType Shape => ShapeType.Square; | ||||
| public abstract bool IsUsable(); | |||||
| public abstract PropType GetPropType(); | public abstract PropType GetPropType(); | ||||
| public Consumables(XY initPos, int radius = GameData.PropRadius) : | |||||
| base(initPos, radius, GameObjType.Consumables) | |||||
| public Gadget(XY initPos, int radius = GameData.PropRadius) : | |||||
| base(initPos, radius, GameObjType.Gadget) | |||||
| { | { | ||||
| this.canMove = false; | this.canMove = false; | ||||
| this.MoveSpeed = GameData.PropMoveSpeed; | this.MoveSpeed = GameData.PropMoveSpeed; | ||||
| } | } | ||||
| } | } | ||||
| public abstract class Tool : Gadget | |||||
| { | |||||
| private bool isUsed = false; | |||||
| public bool IsUsed | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (gameObjLock) | |||||
| return isUsed; | |||||
| } | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| isUsed = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| public override bool IsUsable() => !IsUsed; | |||||
| public Tool(XY initPos) : base(initPos) { } | |||||
| } | |||||
| public abstract class Consumables : Gadget | |||||
| { | |||||
| public override bool IsUsable() => true; | |||||
| public Consumables(XY initPos) : base(initPos) { } | |||||
| } | |||||
| ///// <summary> | ///// <summary> | ||||
| ///// 坑人地雷 | ///// 坑人地雷 | ||||
| ///// </summary> | ///// </summary> | ||||
| // public abstract class DebuffMine : Consumables | |||||
| // public abstract class DebuffMine : Gadget | |||||
| //{ | //{ | ||||
| // public DebuffMine(XYPosition initPos) : base(initPos) { } | // public DebuffMine(XYPosition initPos) : base(initPos) { } | ||||
| // } | // } | ||||
| @@ -86,35 +113,36 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| public override PropType GetPropType() => PropType.ShieldOrSpear; | public override PropType GetPropType() => PropType.ShieldOrSpear; | ||||
| } | } | ||||
| public sealed class Key3 : Consumables | |||||
| #endregion | |||||
| public sealed class Key3 : Tool | |||||
| { | { | ||||
| public Key3(XY initPos) : base(initPos) | public Key3(XY initPos) : base(initPos) | ||||
| { | { | ||||
| } | } | ||||
| public override PropType GetPropType() => PropType.Key3; | public override PropType GetPropType() => PropType.Key3; | ||||
| } | } | ||||
| public sealed class Key5 : Consumables | |||||
| public sealed class Key5 : Tool | |||||
| { | { | ||||
| public Key5(XY initPos) : base(initPos) | public Key5(XY initPos) : base(initPos) | ||||
| { | { | ||||
| } | } | ||||
| public override PropType GetPropType() => PropType.Key5; | public override PropType GetPropType() => PropType.Key5; | ||||
| } | } | ||||
| public sealed class Key6 : Consumables | |||||
| public sealed class Key6 : Tool | |||||
| { | { | ||||
| public Key6(XY initPos) : base(initPos) | public Key6(XY initPos) : base(initPos) | ||||
| { | { | ||||
| } | } | ||||
| public override PropType GetPropType() => PropType.Key6; | public override PropType GetPropType() => PropType.Key6; | ||||
| } | } | ||||
| public sealed class NullProp : Consumables | |||||
| public sealed class NullProp : Gadget | |||||
| { | { | ||||
| public override bool IsUsable() => false; | |||||
| public NullProp() : base(new XY(1, 1)) | public NullProp() : base(new XY(1, 1)) | ||||
| { | { | ||||
| } | } | ||||
| public override PropType GetPropType() => PropType.Null; | public override PropType GetPropType() => PropType.Null; | ||||
| } | } | ||||
| #endregion | |||||
| // #region 所有坑人地雷 | // #region 所有坑人地雷 | ||||
| ///// <summary> | ///// <summary> | ||||
| ///// 减速 | ///// 减速 | ||||
| @@ -143,7 +171,7 @@ namespace GameClass.GameObj | |||||
| // #endregion | // #endregion | ||||
| public static class PropFactory | public static class PropFactory | ||||
| { | { | ||||
| public static Consumables GetConsumables(PropType propType, XY pos) | |||||
| public static Gadget GetConsumables(PropType propType, XY pos) | |||||
| { | { | ||||
| switch (propType) | switch (propType) | ||||
| { | { | ||||
| @@ -3,7 +3,7 @@ using Preparation.Utility; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| public abstract class Prop : ObjOfCharacter | |||||
| public abstract class Item : ObjOfCharacter | |||||
| { | { | ||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| @@ -13,11 +13,11 @@ namespace GameClass.GameObj | |||||
| public abstract PropType GetPropType(); | public abstract PropType GetPropType(); | ||||
| public Prop(XY initPos, int radius = GameData.PropRadius) : | |||||
| base(initPos, radius, GameObjType.Prop) | |||||
| public Item(XY initPos, int radius = GameData.PropRadius) : | |||||
| base(initPos, radius, GameObjType.Item) | |||||
| { | { | ||||
| this.canMove = false; | this.canMove = false; | ||||
| this.MoveSpeed = GameData.PropMoveSpeed; | |||||
| this.MoveSpeed = 0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -25,12 +25,12 @@ namespace GameClass.GameObj | |||||
| ///// <summary> | ///// <summary> | ||||
| ///// 坑人地雷 | ///// 坑人地雷 | ||||
| ///// </summary> | ///// </summary> | ||||
| // public abstract class DebuffMine : Consumables | |||||
| // public abstract class DebuffMine : Gadget | |||||
| //{ | //{ | ||||
| // public DebuffMine(XYPosition initPos) : base(initPos) { } | // public DebuffMine(XYPosition initPos) : base(initPos) { } | ||||
| // } | // } | ||||
| public sealed class CraftingBench : Prop | |||||
| public sealed class CraftingBench : Item | |||||
| { | { | ||||
| public CraftingBench(XY initPos) : | public CraftingBench(XY initPos) : | ||||
| base(initPos) | base(initPos) | ||||
| @@ -4,14 +4,14 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| // 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组 | // 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组 | ||||
| /* | /* | ||||
| public class Prop : Immovable | |||||
| public class Item : Immovable | |||||
| { | { | ||||
| public override ShapeType Shape => ShapeType.Circle; | public override ShapeType Shape => ShapeType.Circle; | ||||
| public override bool IsRigid => false; | public override bool IsRigid => false; | ||||
| public long MappingID { get; } | public long MappingID { get; } | ||||
| public readonly Consumables propHasPicked; | |||||
| public Prop(Consumables prop) : | |||||
| base(prop.Position, prop.Radius, GameObjType.Prop) | |||||
| public readonly Gadget propHasPicked; | |||||
| public Item(Gadget prop) : | |||||
| base(prop.Position, prop.Radius, GameObjType.Item) | |||||
| { | { | ||||
| this.propHasPicked = prop; | this.propHasPicked = prop; | ||||
| this.MappingID = prop.ID; | this.MappingID = prop.ID; | ||||
| @@ -303,7 +303,7 @@ namespace Gaming | |||||
| player.SetPlayerStateNaturally(); | player.SetPlayerStateNaturally(); | ||||
| for (int i = 0; i < GameData.maxNumOfPropInChest; ++i) | for (int i = 0; i < GameData.maxNumOfPropInChest; ++i) | ||||
| { | { | ||||
| Consumables prop = chestToOpen.PropInChest[i]; | |||||
| Gadget prop = chestToOpen.PropInChest[i]; | |||||
| chestToOpen.PropInChest[i] = new NullProp(); | chestToOpen.PropInChest[i] = new NullProp(); | ||||
| prop.ReSetPos(player.Position); | prop.ReSetPos(player.Position); | ||||
| gameMap.Add(prop); | gameMap.Add(prop); | ||||
| @@ -389,67 +389,133 @@ namespace Gaming | |||||
| return true; | return true; | ||||
| } | } | ||||
| public bool LockOrOpenDoor(Character player) | |||||
| public bool LockDoor(Character player) | |||||
| { | { | ||||
| if (player.CharacterType == CharacterType.Robot) return false; | if (player.CharacterType == CharacterType.Robot) return false; | ||||
| Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door); | Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door); | ||||
| if (doorToLock == null) return false; | if (doorToLock == null) return false; | ||||
| bool flag = false; | |||||
| foreach (Consumables prop in player.PropInventory) | |||||
| PropType propType = doorToLock.DoorNum switch | |||||
| { | |||||
| 3 => PropType.Key3, | |||||
| 5 => PropType.Key5, | |||||
| _ => PropType.Key6, | |||||
| }; | |||||
| if (!player.UseTool(propType)) return false; | |||||
| long stateNum = player.SetPlayerState(PlayerStateType.LockingTheDoor, doorToLock); | |||||
| if (stateNum == -1) | |||||
| { | { | ||||
| switch (prop.GetPropType()) | |||||
| player.ReleaseTool(propType); | |||||
| return false; | |||||
| } | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | { | ||||
| case PropType.Key3: | |||||
| if (doorToLock.DoorNum == 3) | |||||
| flag = true; | |||||
| break; | |||||
| case PropType.Key5: | |||||
| if (doorToLock.DoorNum == 5) | |||||
| flag = true; | |||||
| break; | |||||
| case PropType.Key6: | |||||
| if (doorToLock.DoorNum == 6) | |||||
| flag = true; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| player.ThreadNum.WaitOne(); | |||||
| if (stateNum != player.StateNum) | |||||
| { | |||||
| player.ReleaseTool(propType); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (!doorToLock.TryLock(player)) | |||||
| { | |||||
| player.ReleaseTool(propType); | |||||
| player.SetPlayerState(); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| else | |||||
| { | |||||
| Thread.Sleep(GameData.checkInterval); | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => stateNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.LockDegree < GameData.degreeOfLockingOrOpeningTheDoor, | |||||
| loopToDo: () => | |||||
| { | |||||
| if ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) != null) | |||||
| return false; | |||||
| doorToLock.LockDegree += GameData.checkInterval * player.SpeedOfOpeningOrLocking; | |||||
| return true; | |||||
| }, | |||||
| timeInterval: GameData.checkInterval, | |||||
| finallyReturn: () => 0 | |||||
| ) | |||||
| .Start(); | |||||
| doorToLock.StopLock(); | |||||
| if (stateNum == player.StateNum) player.SetPlayerState(); | |||||
| player.ReleaseTool(propType); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (flag) break; | |||||
| } | |||||
| if (!flag) return false; | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| if (doorToLock.OpenOrLockDegree > 0 || gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character) != null) | |||||
| return false; | |||||
| if (!(player.Commandable()) || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor) | |||||
| return true; | |||||
| } | |||||
| public bool OpenDoor(Character player) | |||||
| { | |||||
| if (player.CharacterType == CharacterType.Robot) return false; | |||||
| Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door); | |||||
| if (doorToLock == null) return false; | |||||
| PropType propType = doorToLock.DoorNum switch | |||||
| { | |||||
| 3 => PropType.Key3, | |||||
| 5 => PropType.Key5, | |||||
| _ => PropType.Key6, | |||||
| }; | |||||
| if (!player.UseTool(propType)) return false; | |||||
| long stateNum = player.SetPlayerState(PlayerStateType.OpeningTheDoor, doorToLock); | |||||
| if (stateNum == -1) | |||||
| { | |||||
| player.ReleaseTool(propType); | |||||
| return false; | return false; | ||||
| } | |||||
| player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor); | |||||
| long threadNum = player.StateNum; | |||||
| new Thread | new Thread | ||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int>( | |||||
| loopCondition: () => flag && threadNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor, | |||||
| loopToDo: () => | |||||
| { | |||||
| flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null); | |||||
| doorToLock.OpenOrLockDegree += GameData.frameDuration * player.SpeedOfOpeningOrLocking; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| finallyReturn: () => 0 | |||||
| ) | |||||
| .Start(); | |||||
| if (doorToLock.OpenOrLockDegree >= GameData.degreeOfLockingOrOpeningTheDoor) | |||||
| { | |||||
| doorToLock.IsOpen = (!doorToLock.IsOpen); | |||||
| } | |||||
| if (threadNum == player.StateNum) | |||||
| player.SetPlayerState(); | |||||
| doorToLock.OpenOrLockDegree = 0; | |||||
| } | |||||
| ( | |||||
| () => | |||||
| { | |||||
| player.ThreadNum.WaitOne(); | |||||
| if (stateNum != player.StateNum) | |||||
| { | |||||
| player.ReleaseTool(propType); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (!doorToLock.TryOpen(player)) | |||||
| { | |||||
| player.ReleaseTool(propType); | |||||
| player.SetPlayerState(); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| else | |||||
| { | |||||
| Thread.Sleep(GameData.degreeOfLockingOrOpeningTheDoor / player.SpeedOfOpeningOrLocking); | |||||
| ) | |||||
| lock (player.ActionLock) | |||||
| { | |||||
| if (stateNum == player.StateNum) | |||||
| { | |||||
| player.SetPlayerState(); | |||||
| doorToLock.StopOpen(); | |||||
| player.ReleaseTool(propType); | |||||
| player.ThreadNum.Release(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | { IsBackground = true }.Start(); | ||||
| return true; | return true; | ||||
| @@ -17,7 +17,7 @@ namespace Gaming | |||||
| this.gameMap = gameMap; | this.gameMap = gameMap; | ||||
| } | } | ||||
| public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null) | |||||
| public Character? AddPlayer(XY pos, long teamID, long playerID, CharacterType characterType, Character? parent = null) | |||||
| { | { | ||||
| Character newPlayer; | Character newPlayer; | ||||
| @@ -370,7 +370,7 @@ namespace Gaming | |||||
| for (int i = 0; i < GameData.maxNumOfPropInPropInventory; i++) | for (int i = 0; i < GameData.maxNumOfPropInPropInventory; i++) | ||||
| { | { | ||||
| Consumables? prop = player.UseProp(i); | |||||
| Gadget? prop = player.UseProp(i); | |||||
| if (prop != null) | if (prop != null) | ||||
| { | { | ||||
| prop.ReSetPos(player.Position); | prop.ReSetPos(player.Position); | ||||
| @@ -2,10 +2,8 @@ | |||||
| using System.Threading; | using System.Threading; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Timothy.FrameRateTask; | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using System.Numerics; | |||||
| namespace Gaming | namespace Gaming | ||||
| { | { | ||||
| @@ -14,10 +12,10 @@ namespace Gaming | |||||
| public struct PlayerInitInfo | public struct PlayerInitInfo | ||||
| { | { | ||||
| public uint birthPointIndex; | public uint birthPointIndex; | ||||
| public int teamID; | |||||
| public int playerID; | |||||
| public long teamID; | |||||
| public long playerID; | |||||
| public CharacterType characterType; | public CharacterType characterType; | ||||
| public PlayerInitInfo(uint birthPointIndex, int teamID, int playerID, CharacterType characterType) | |||||
| public PlayerInitInfo(uint birthPointIndex, long teamID, long playerID, CharacterType characterType) | |||||
| { | { | ||||
| this.birthPointIndex = birthPointIndex; | this.birthPointIndex = birthPointIndex; | ||||
| this.teamID = teamID; | this.teamID = teamID; | ||||
| @@ -199,14 +197,25 @@ namespace Gaming | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| public bool LockOrOpenDoor(long playerID) | |||||
| public bool LockDoor(long playerID) | |||||
| { | { | ||||
| if (!gameMap.Timer.IsGaming) | if (!gameMap.Timer.IsGaming) | ||||
| return false; | return false; | ||||
| Character? player = gameMap.FindPlayerToAction(playerID); | Character? player = gameMap.FindPlayerToAction(playerID); | ||||
| if (player != null) | if (player != null) | ||||
| { | { | ||||
| return actionManager.LockOrOpenDoor(player); | |||||
| return actionManager.LockDoor(player); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public bool OpenDoor(long playerID) | |||||
| { | |||||
| if (!gameMap.Timer.IsGaming) | |||||
| return false; | |||||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||||
| if (player != null) | |||||
| { | |||||
| return actionManager.OpenDoor(player); | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -21,9 +21,9 @@ namespace Gaming | |||||
| public void UseProp(Character player, PropType propType) | public void UseProp(Character player, PropType propType) | ||||
| { | { | ||||
| if (player.IsRemoved || player.CharacterType == CharacterType.Robot) | |||||
| if (player.CharacterType == CharacterType.Robot || player.IsRemoved) | |||||
| return; | return; | ||||
| Consumables prop = player.UseProp(propType); | |||||
| Gadget prop = player.UseProp(propType); | |||||
| switch (prop.GetPropType()) | switch (prop.GetPropType()) | ||||
| { | { | ||||
| case PropType.ShieldOrSpear: | case PropType.ShieldOrSpear: | ||||
| @@ -73,23 +73,22 @@ namespace Gaming | |||||
| /// <returns></returns> | /// <returns></returns> | ||||
| public bool PickProp(Character player, PropType propType = PropType.Null) | public bool PickProp(Character player, PropType propType = PropType.Null) | ||||
| { | { | ||||
| if (player.IsRemoved) | |||||
| return false; | |||||
| if (!player.Commandable()) return false; | |||||
| int indexing = player.IndexingOfAddProp(); | int indexing = player.IndexingOfAddProp(); | ||||
| if (indexing == GameData.maxNumOfPropInPropInventory) | if (indexing == GameData.maxNumOfPropInPropInventory) | ||||
| return false; | return false; | ||||
| Consumables pickProp = new NullProp(); | |||||
| Gadget pickProp = new NullProp(); | |||||
| if (propType == PropType.Null) // 自动检查有无道具可捡 | if (propType == PropType.Null) // 自动检查有无道具可捡 | ||||
| { | { | ||||
| pickProp = player.PropInventory[indexing] = ((Consumables?)gameMap.OneInTheSameCell(player.Position, GameObjType.Consumables)) ?? new NullProp(); | |||||
| pickProp = player.PropInventory[indexing] = ((Gadget?)gameMap.OneInTheSameCell(player.Position, GameObjType.Gadget)) ?? new NullProp(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Consumables].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Gadget].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Consumables prop in gameMap.GameObjDict[GameObjType.Consumables]) | |||||
| foreach (Gadget prop in gameMap.GameObjDict[GameObjType.Gadget]) | |||||
| { | { | ||||
| if (prop.GetPropType() == propType) | if (prop.GetPropType() == propType) | ||||
| { | { | ||||
| @@ -102,14 +101,14 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Consumables].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Gadget].ExitReadLock(); | |||||
| } | } | ||||
| } | } | ||||
| if (pickProp.GetPropType() != PropType.Null) | if (pickProp.GetPropType() != PropType.Null) | ||||
| { | { | ||||
| gameMap.Remove(pickProp); | gameMap.Remove(pickProp); | ||||
| //gameMap.Add(new Prop(pickProp)); | |||||
| //gameMap.Add(new Item(pickProp)); | |||||
| return true; | return true; | ||||
| } | } | ||||
| else | else | ||||
| @@ -120,7 +119,7 @@ namespace Gaming | |||||
| { | { | ||||
| if (!gameMap.Timer.IsGaming || player.IsRemoved) | if (!gameMap.Timer.IsGaming || player.IsRemoved) | ||||
| return; | return; | ||||
| Consumables prop = player.UseProp(propType); | |||||
| Gadget prop = player.UseProp(propType); | |||||
| if (prop.GetPropType() == PropType.Null) | if (prop.GetPropType() == PropType.Null) | ||||
| return; | return; | ||||
| @@ -128,7 +127,7 @@ namespace Gaming | |||||
| gameMap.Add(prop); | gameMap.Add(prop); | ||||
| } | } | ||||
| private static Consumables ProduceOnePropNotKey(Random r, XY Pos) | |||||
| private static Gadget ProduceOnePropNotKey(Random r, XY Pos) | |||||
| { | { | ||||
| return PropFactory.GetConsumables((PropType)r.Next(GameData.numOfTeachingBuilding + 1, GameData.numOfPropSpecies + 1), Pos); | return PropFactory.GetConsumables((PropType)r.Next(GameData.numOfTeachingBuilding + 1, GameData.numOfPropSpecies + 1), Pos); | ||||
| } | } | ||||
| @@ -216,7 +216,9 @@ namespace Gaming | |||||
| { | { | ||||
| if (character.IsGhost() && | if (character.IsGhost() && | ||||
| (character.PlayerState == PlayerStateType.TryingToAttack || character.PlayerState == PlayerStateType.Swinging | (character.PlayerState == PlayerStateType.TryingToAttack || character.PlayerState == PlayerStateType.Swinging | ||||
| || character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | |||||
| || character.PlayerState == PlayerStateType.UsingSkill | |||||
| || character.PlayerState == PlayerStateType.LockingTheDoor || character.PlayerState == PlayerStateType.OpeningTheDoor | |||||
| || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | |||||
| && gameMap.CanSee(player, character)) | && gameMap.CanSee(player, character)) | ||||
| { | { | ||||
| if (characterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP)) > 0) | if (characterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP)) > 0) | ||||
| @@ -5,10 +5,10 @@ namespace Preparation.Interface | |||||
| { | { | ||||
| public interface ICharacter : IGameObj | public interface ICharacter : IGameObj | ||||
| { | { | ||||
| public int TeamID { get; } | |||||
| public long TeamID { get; } | |||||
| public int HP { get; set; } | public int HP { get; set; } | ||||
| public int Score { get; } | |||||
| public void AddScore(int add); | |||||
| public long Score { get; } | |||||
| public void AddScore(long add); | |||||
| public double Vampire { get; } | public double Vampire { get; } | ||||
| public PlayerStateType PlayerState { get; } | public PlayerStateType PlayerState { get; } | ||||
| public BulletType BulletOfPlayer { get; set; } | public BulletType BulletOfPlayer { get; set; } | ||||
| @@ -19,19 +19,20 @@ namespace Preparation.Utility | |||||
| Rescued = 10, | Rescued = 10, | ||||
| Stunned = 11, | Stunned = 11, | ||||
| TryingToAttack = 12,//指前摇 | TryingToAttack = 12,//指前摇 | ||||
| LockingOrOpeningTheDoor = 13, | |||||
| LockingTheDoor = 13, | |||||
| OpeningTheChest = 14, | OpeningTheChest = 14, | ||||
| ClimbingThroughWindows = 15, | ClimbingThroughWindows = 15, | ||||
| UsingSkill = 16, | UsingSkill = 16, | ||||
| OpeningTheDoorway = 17, | OpeningTheDoorway = 17, | ||||
| Charmed = 18, | Charmed = 18, | ||||
| OpeningTheDoor = 19, | |||||
| } | } | ||||
| public enum GameObjType | public enum GameObjType | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| Character = 1, | Character = 1, | ||||
| Consumables = 2, | |||||
| Prop = 3, | |||||
| Gadget = 2, | |||||
| Item = 3, | |||||
| Bullet = 4, | Bullet = 4, | ||||
| BombedBullet = 5, | BombedBullet = 5, | ||||
| @@ -45,8 +45,8 @@ namespace Preparation.Utility | |||||
| { | { | ||||
| return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass | return gameObjType != GameObjType.Null && gameObjType != GameObjType.Grass | ||||
| && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window | && gameObjType != GameObjType.OutOfBoundBlock && gameObjType != GameObjType.Window | ||||
| && gameObjType != GameObjType.Bullet&&gameObjType != GameObjType.Consumables | |||||
| &&gameObjType != GameObjType.Prop&&gameObjType != GameObjType.BombedBullet | |||||
| && gameObjType != GameObjType.Bullet&&gameObjType != GameObjType.Gadget | |||||
| &&gameObjType != GameObjType.Item&&gameObjType != GameObjType.BombedBullet | |||||
| &&gameObjType != GameObjType.EmergencyExit&&gameObjType != GameObjType.Doorway; | &&gameObjType != GameObjType.EmergencyExit&&gameObjType != GameObjType.Doorway; | ||||
| }*/ | }*/ | ||||
| @@ -107,7 +107,8 @@ namespace Preparation.Utility | |||||
| return PlayerState.Graduated; | return PlayerState.Graduated; | ||||
| case Preparation.Utility.PlayerStateType.Fixing: | case Preparation.Utility.PlayerStateType.Fixing: | ||||
| return PlayerState.Learning; | return PlayerState.Learning; | ||||
| case Preparation.Utility.PlayerStateType.LockingOrOpeningTheDoor: | |||||
| case Preparation.Utility.PlayerStateType.LockingTheDoor: | |||||
| case PlayerStateType.OpeningTheDoor: | |||||
| return PlayerState.Locking; | return PlayerState.Locking; | ||||
| case Preparation.Utility.PlayerStateType.OpeningTheChest: | case Preparation.Utility.PlayerStateType.OpeningTheChest: | ||||
| return PlayerState.OpeningAChest; | return PlayerState.OpeningAChest; | ||||
| @@ -33,10 +33,10 @@ namespace Server | |||||
| else return null; | else return null; | ||||
| case Preparation.Utility.GameObjType.Door: | case Preparation.Utility.GameObjType.Door: | ||||
| return Door((Door)gameObj); | return Door((Door)gameObj); | ||||
| case GameObjType.Prop: | |||||
| return Prop((Prop)gameObj); | |||||
| case Preparation.Utility.GameObjType.Consumables: | |||||
| return Prop((Consumables)gameObj); | |||||
| case GameObjType.Item: | |||||
| return Prop((Item)gameObj); | |||||
| case Preparation.Utility.GameObjType.Gadget: | |||||
| return Prop((Gadget)gameObj); | |||||
| default: return null; | default: return null; | ||||
| } | } | ||||
| } | } | ||||
| @@ -68,7 +68,7 @@ namespace Server | |||||
| ViewRange = player.ViewRange, | ViewRange = player.ViewRange, | ||||
| Radius = player.Radius, | Radius = player.Radius, | ||||
| DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0, | DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0, | ||||
| Score = player.Score, | |||||
| Score = (int)player.Score, | |||||
| TreatProgress = player.DegreeOfTreatment, | TreatProgress = player.DegreeOfTreatment, | ||||
| RescueProgress = player.TimeOfRescue, | RescueProgress = player.TimeOfRescue, | ||||
| @@ -110,7 +110,7 @@ namespace Server | |||||
| TrickerType = Transformation.ToTrickerType(player.CharacterType), | TrickerType = Transformation.ToTrickerType(player.CharacterType), | ||||
| Guid = player.ID, | Guid = player.ID, | ||||
| Score = player.Score, | |||||
| Score = (int)player.Score, | |||||
| PlayerId = player.PlayerID, | PlayerId = player.PlayerID, | ||||
| ViewRange = player.ViewRange, | ViewRange = player.ViewRange, | ||||
| Radius = player.Radius, | Radius = player.Radius, | ||||
| @@ -157,7 +157,7 @@ namespace Server | |||||
| return msg; | return msg; | ||||
| } | } | ||||
| private static MessageOfObj Prop(Consumables prop) | |||||
| private static MessageOfObj Prop(Gadget prop) | |||||
| { | { | ||||
| MessageOfObj msg = new() | MessageOfObj msg = new() | ||||
| { | { | ||||
| @@ -173,7 +173,7 @@ namespace Server | |||||
| return msg; | return msg; | ||||
| } | } | ||||
| private static MessageOfObj Prop(Prop prop) | |||||
| private static MessageOfObj Prop(Item prop) | |||||
| { | { | ||||
| MessageOfObj msg = new() | MessageOfObj msg = new() | ||||
| { | { | ||||
| @@ -256,7 +256,7 @@ namespace Server | |||||
| { | { | ||||
| X = door.Position.x, | X = door.Position.x, | ||||
| Y = door.Position.y, | Y = door.Position.y, | ||||
| Progress = door.OpenOrLockDegree, | |||||
| Progress = door.LockDegree, | |||||
| IsOpen = door.IsOpen | IsOpen = door.IsOpen | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -196,8 +196,8 @@ namespace Server | |||||
| { | { | ||||
| foreach (Character character in game.GameMap.GameObjDict[GameObjType.Character]) | foreach (Character character in game.GameMap.GameObjDict[GameObjType.Character]) | ||||
| { | { | ||||
| if (!character.IsGhost()) score[0] += character.Score; | |||||
| else score[1] += character.Score; | |||||
| if (!character.IsGhost()) score[0] += (int)character.Score; | |||||
| else score[1] += (int)character.Score; | |||||
| } | } | ||||
| } | } | ||||
| @@ -121,7 +121,7 @@ namespace Server | |||||
| lock (addPlayerLock) | lock (addPlayerLock) | ||||
| { | { | ||||
| Game.PlayerInitInfo playerInitInfo = new(GetBirthPointIdx(request.PlayerId), PlayerTypeToTeamID(request.PlayerType), (int)request.PlayerId, characterType); | |||||
| Game.PlayerInitInfo playerInitInfo = new(GetBirthPointIdx(request.PlayerId), PlayerTypeToTeamID(request.PlayerType), request.PlayerId, characterType); | |||||
| long newPlayerID = game.AddPlayer(playerInitInfo); | long newPlayerID = game.AddPlayer(playerInitInfo); | ||||
| if (newPlayerID == GameObj.invalidID) | if (newPlayerID == GameObj.invalidID) | ||||
| return; | return; | ||||
| @@ -471,7 +471,7 @@ namespace Server | |||||
| return Task.FromResult(boolRes); | return Task.FromResult(boolRes); | ||||
| } | } | ||||
| var gameID = communicationToGameID[request.PlayerId]; | var gameID = communicationToGameID[request.PlayerId]; | ||||
| boolRes.ActSuccess = game.LockOrOpenDoor(gameID); | |||||
| boolRes.ActSuccess = game.OpenDoor(gameID); | |||||
| return Task.FromResult(boolRes); | return Task.FromResult(boolRes); | ||||
| } | } | ||||
| @@ -487,7 +487,7 @@ namespace Server | |||||
| return Task.FromResult(boolRes); | return Task.FromResult(boolRes); | ||||
| } | } | ||||
| var gameID = communicationToGameID[request.PlayerId]; | var gameID = communicationToGameID[request.PlayerId]; | ||||
| boolRes.ActSuccess = game.LockOrOpenDoor(gameID); | |||||
| boolRes.ActSuccess = game.LockDoor(gameID); | |||||
| return Task.FromResult(boolRes); | return Task.FromResult(boolRes); | ||||
| } | } | ||||