| @@ -133,7 +133,7 @@ namespace GameClass.GameObj | |||
| if (!(bouncer?.TeamID == this.TeamID)) | |||
| { | |||
| if (hasSpear || !HasShield) | |||
| _ = TrySubHp(subHP); | |||
| _ = SubHp(subHP); | |||
| if (hp <= 0) | |||
| TryActivatingLIFE(); | |||
| } | |||
| @@ -218,7 +218,8 @@ namespace GameClass.GameObj | |||
| HPReadWriterLock.ExitWriteLock(); | |||
| } | |||
| } | |||
| } // 最大血量 | |||
| } | |||
| // 最大血量 | |||
| protected long hp; | |||
| public long HP | |||
| { | |||
| @@ -234,22 +235,23 @@ namespace GameClass.GameObj | |||
| HPReadWriterLock.ExitReadLock(); | |||
| } | |||
| } | |||
| set | |||
| } | |||
| public long SetHP(long value) | |||
| { | |||
| HPReadWriterLock.EnterWriteLock(); | |||
| try | |||
| { | |||
| HPReadWriterLock.EnterWriteLock(); | |||
| try | |||
| if (value > 0) | |||
| { | |||
| if (value > 0) | |||
| { | |||
| hp = value <= maxHp ? value : maxHp; | |||
| } | |||
| else | |||
| hp = 0; | |||
| } | |||
| finally | |||
| { | |||
| HPReadWriterLock.ExitWriteLock(); | |||
| return hp = value <= maxHp ? value : maxHp; | |||
| } | |||
| else | |||
| return hp = 0; | |||
| } | |||
| finally | |||
| { | |||
| HPReadWriterLock.ExitWriteLock(); | |||
| } | |||
| } | |||
| @@ -257,7 +259,7 @@ namespace GameClass.GameObj | |||
| /// 尝试减血 | |||
| /// </summary> | |||
| /// <param name="sub">减血量</param> | |||
| public long TrySubHp(long sub) | |||
| public long SubHp(long sub) | |||
| { | |||
| HPReadWriterLock.EnterWriteLock(); | |||
| try | |||
| @@ -280,6 +282,20 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public long AddHP(long add) | |||
| { | |||
| HPReadWriterLock.EnterWriteLock(); | |||
| try | |||
| { | |||
| long previousHp = hp; | |||
| return (hp = (hp + add > maxHp) ? maxHp : hp + add) - previousHp; | |||
| } | |||
| finally | |||
| { | |||
| HPReadWriterLock.ExitWriteLock(); | |||
| } | |||
| } | |||
| private readonly object vampireLock = new(); | |||
| public object VampireLock => vampire; | |||
| @@ -537,13 +553,7 @@ namespace GameClass.GameObj | |||
| if (value == PlayerStateType.Rescued) return -1; | |||
| Door door = (Door)lastObj!; | |||
| door.StopOpen(); | |||
| ReleaseTool(door.DoorNum switch | |||
| { | |||
| 3 => PropType.Key3, | |||
| 5 => PropType.Key5, | |||
| _ => PropType.Key6, | |||
| } | |||
| ); | |||
| ReleaseTool(door.KeyType); | |||
| return ChangePlayerState(runningState, value, gameObj); | |||
| case PlayerStateType.UsingSkill: | |||
| { | |||
| @@ -13,23 +13,16 @@ namespace GameClass.GameObj | |||
| public Door(XY initPos, PlaceType placeType) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Door) | |||
| { | |||
| switch (placeType) | |||
| keyType = placeType switch | |||
| { | |||
| case PlaceType.Door3: | |||
| doorNum = 3; | |||
| break; | |||
| case PlaceType.Door5: | |||
| doorNum = 5; | |||
| break; | |||
| case PlaceType.Door6: | |||
| default: | |||
| doorNum = 6; | |||
| break; | |||
| } | |||
| PlaceType.Door3 => PropType.Key3, | |||
| PlaceType.Door5 => PropType.Key5, | |||
| _ => PropType.Key6, | |||
| }; | |||
| } | |||
| private readonly int doorNum; | |||
| public int DoorNum => doorNum; | |||
| private readonly PropType keyType; | |||
| public PropType KeyType => keyType; | |||
| public override bool IsRigid => !isOpen; | |||
| public override ShapeType Shape => ShapeType.Square; | |||
| @@ -151,12 +144,7 @@ namespace GameClass.GameObj | |||
| { | |||
| if (character.PlayerState == PlayerStateType.OpeningTheDoor) | |||
| { | |||
| character.ReleaseTool(DoorNum switch | |||
| { | |||
| 3 => PropType.Key3, | |||
| 5 => PropType.Key5, | |||
| _ => PropType.Key6, | |||
| }); | |||
| character.ReleaseTool(KeyType); | |||
| character.SetPlayerStateNaturally(); | |||
| } | |||
| else if (character.PlayerState == PlayerStateType.LockingTheDoor) | |||
| @@ -1,5 +1,4 @@ | |||
| using Google.Protobuf.WellKnownTypes; | |||
| using Preparation.Interface; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| @@ -321,7 +321,7 @@ namespace Gaming | |||
| if (playerRescued.AddTimeOfRescue(GameData.checkInterval)) | |||
| { | |||
| playerRescued.SetPlayerStateNaturally(); | |||
| playerRescued.HP = playerRescued.MaxHp / 2; | |||
| playerRescued.SetHP(playerRescued.MaxHp / 2); | |||
| player.AddScore(GameData.StudentScoreRescue); | |||
| return false; | |||
| } | |||
| @@ -479,19 +479,12 @@ namespace Gaming | |||
| 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; | |||
| if (!player.UseTool(doorToLock.KeyType)) return false; | |||
| long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.LockingTheDoor, doorToLock); | |||
| if (stateNum == -1) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToLock.KeyType); | |||
| return false; | |||
| } | |||
| @@ -502,13 +495,13 @@ namespace Gaming | |||
| player.ThreadNum.WaitOne(); | |||
| if (!player.StartThread(stateNum, RunningStateType.RunningActively)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToLock.KeyType); | |||
| player.ThreadNum.Release(); | |||
| return; | |||
| } | |||
| if (!doorToLock.TryLock(player)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToLock.KeyType); | |||
| player.ResetPlayerState(stateNum); | |||
| player.ThreadNum.Release(); | |||
| return; | |||
| @@ -529,7 +522,7 @@ namespace Gaming | |||
| ) | |||
| .Start(); | |||
| doorToLock.StopLock(); | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToLock.KeyType); | |||
| player.ThreadNum.Release(); | |||
| player.ResetPlayerState(stateNum); | |||
| } | |||
| @@ -542,22 +535,15 @@ namespace Gaming | |||
| 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, | |||
| }; | |||
| Door? doorToOpen = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door); | |||
| if (doorToOpen == null) return false; | |||
| if (!player.UseTool(propType)) return false; | |||
| if (!player.UseTool(doorToOpen.KeyType)) return false; | |||
| long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.OpeningTheDoor, doorToLock); | |||
| long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.OpeningTheDoor, doorToOpen); | |||
| if (stateNum == -1) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToOpen.KeyType); | |||
| return false; | |||
| } | |||
| @@ -568,13 +554,13 @@ namespace Gaming | |||
| player.ThreadNum.WaitOne(); | |||
| if (!player.StartThread(stateNum, RunningStateType.RunningSleepily)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToOpen.KeyType); | |||
| player.ThreadNum.Release(); | |||
| return; | |||
| } | |||
| if (!doorToLock.TryOpen(player)) | |||
| if (!doorToOpen.TryOpen(player)) | |||
| { | |||
| player.ReleaseTool(propType); | |||
| player.ReleaseTool(doorToOpen.KeyType); | |||
| if (player.ResetPlayerState(stateNum)) | |||
| player.ThreadNum.Release(); | |||
| return; | |||
| @@ -583,8 +569,8 @@ namespace Gaming | |||
| if (player.ResetPlayerState(stateNum)) | |||
| { | |||
| doorToLock.StopOpen(); | |||
| player.ReleaseTool(propType); | |||
| doorToOpen.StopOpen(); | |||
| player.ReleaseTool(doorToOpen.KeyType); | |||
| player.ThreadNum.Release(); | |||
| } | |||
| } | |||
| @@ -326,12 +326,12 @@ namespace Gaming | |||
| { | |||
| if (bullet.HasSpear) | |||
| { | |||
| long subHp = student.TrySubHp(bullet.AP); | |||
| long subHp = student.SubHp(bullet.AP); | |||
| #if DEBUG | |||
| Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); | |||
| #endif | |||
| bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear); | |||
| bullet.Parent.HP = (long)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||
| bullet.Parent.AddHP((long)bullet.Parent.Vampire * subHp); | |||
| } | |||
| else return; | |||
| } | |||
| @@ -340,14 +340,14 @@ namespace Gaming | |||
| long subHp; | |||
| if (bullet.HasSpear) | |||
| { | |||
| subHp = student.TrySubHp(bullet.AP + GameData.ApSpearAdd); | |||
| subHp = student.SubHp(bullet.AP + GameData.ApSpearAdd); | |||
| #if DEBUG | |||
| Debugger.Output(this, "is being shot with Spear! Now his hp is" + student.HP.ToString()); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| subHp = student.TrySubHp(bullet.AP); | |||
| subHp = student.SubHp(bullet.AP); | |||
| #if DEBUG | |||
| Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); | |||
| #endif | |||
| @@ -358,7 +358,7 @@ namespace Gaming | |||
| student.AddScore(subHp * GameData.factorOfScoreWhenTeacherAttacked / GameData.basicApOfGhost / FactorTeacher); | |||
| } | |||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||
| bullet.Parent.AddHP((long)(bullet.Parent.Vampire * subHp)); | |||
| } | |||
| if (student.HP <= 0) | |||
| student.TryActivatingLIFE(); // 如果有复活甲 | |||
| @@ -46,7 +46,7 @@ namespace Gaming | |||
| if (!player.IsGhost()) | |||
| if (player.HP < player.MaxHp) | |||
| { | |||
| player.HP += GameData.basicTreatmentDegree / 2; | |||
| player.AddHP(GameData.basicTreatmentDegree / 2); | |||
| player.AddScore(GameData.ScorePropAddHp); | |||
| } | |||
| else player.AddAp(GameData.PropDuration); | |||
| @@ -421,7 +421,7 @@ namespace Gaming | |||
| if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character)) | |||
| { | |||
| character.SetPlayerStateNaturally(); | |||
| character.HP = GameData.RemainHpWhenAddLife; | |||
| character.SetHP(GameData.RemainHpWhenAddLife); | |||
| ((Student)character).SetTimeOfRescue(0); | |||
| player.AddScore(GameData.StudentScoreRescue); | |||
| break; | |||
| @@ -452,7 +452,7 @@ namespace Gaming | |||
| if ((character.HP < character.MaxHp) && gameMap.CanSee(player, character)) | |||
| { | |||
| player.AddScore(GameData.StudentScoreTreat(GameData.addHpWhenEncourage)); | |||
| character.HP += GameData.addHpWhenEncourage; | |||
| character.AddHP(GameData.addHpWhenEncourage); | |||
| ((Student)character).SetDegreeOfTreatment0(); | |||
| break; | |||
| } | |||
| @@ -6,7 +6,8 @@ namespace Preparation.Interface | |||
| public interface ICharacter : IMoveable | |||
| { | |||
| public long TeamID { get; } | |||
| public long HP { get; set; } | |||
| public long HP { get; } | |||
| public long AddHP(long add); | |||
| public long Score { get; } | |||
| public void AddScore(long add); | |||
| public double Vampire { get; } | |||