fix: 🐛 fix the bug about numOfNoHpStudent
tags/v0.1.0
| @@ -52,6 +52,12 @@ | |||
| - docs:更新了 游戏机制与平衡性调整更新草案.pdf | |||
| - feat:游戏机制与平衡性调整已完成 | |||
| # 5月20日更新 | |||
| # 5月20日18:00更新 | |||
| - docs:更新了 游戏机制与平衡性调整更新(基本不变版).pdf | |||
| - fix:修复了Pubnish技能眩晕时长的错误 | |||
| - fix:修复了Pubnish技能眩晕时长的错误 | |||
| # 5月20日23:30更新 | |||
| - fix:修复了学习已经完成的作业会卡死的问题 | |||
| # 5月21日更新 | |||
| - fix:修复了游戏结束判定的bug | |||
| @@ -455,13 +455,13 @@ namespace GameClass.GameObj | |||
| case PlayerStateType.Addicted: | |||
| if (value == PlayerStateType.Rescued) | |||
| return ChangePlayerStateInOneThread(value, gameObj); | |||
| else if (value == PlayerStateType.Null) | |||
| else if (value == PlayerStateType.Null || value == PlayerStateType.Deceased) | |||
| return ChangePlayerState(value, gameObj); | |||
| else return -1; | |||
| case PlayerStateType.Rescued: | |||
| if (value == PlayerStateType.Addicted) | |||
| return ChangePlayerStateInOneThread(value, gameObj); | |||
| else if (value == PlayerStateType.Null) | |||
| else if (value == PlayerStateType.Null || value == PlayerStateType.Deceased) | |||
| return ChangePlayerState(value, gameObj); | |||
| else return -1; | |||
| @@ -590,15 +590,17 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public void RemoveFromGame(PlayerStateType playerStateType) | |||
| public bool TryToRemoveFromGame(PlayerStateType playerStateType) | |||
| { | |||
| lock (actionLock) | |||
| { | |||
| TryToRemove(); | |||
| if (!TryToRemove()) return false; | |||
| Debugger.Output(this, "TryToRemove"); | |||
| ReSetCanMove(false); | |||
| SetPlayerState(playerStateType); | |||
| position = GameData.PosWhoDie; | |||
| } | |||
| return true; | |||
| } | |||
| #endregion | |||
| @@ -43,9 +43,9 @@ namespace GameClass.GameObj | |||
| return (Interlocked.CompareExchange(ref isRemoved, 0, 0) == 1); | |||
| } | |||
| } | |||
| public virtual void TryToRemove() | |||
| public virtual bool TryToRemove() | |||
| { | |||
| Interlocked.Exchange(ref isRemoved, 1); | |||
| return Interlocked.Exchange(ref isRemoved, 1) == 0; | |||
| } | |||
| public int Radius { get; } | |||
| @@ -11,58 +11,14 @@ namespace GameClass.GameObj | |||
| private readonly Dictionary<uint, XY> birthPointList; // 出生点列表 | |||
| public Dictionary<uint, XY> BirthPointList => birthPointList; | |||
| private readonly object lockForNum = new(); | |||
| private void WhenStudentNumChange() | |||
| { | |||
| if (numOfDeceasedStudent + numOfEscapedStudent == GameData.numOfStudent) | |||
| { | |||
| Timer.IsGaming = false; | |||
| return; | |||
| } | |||
| if (GameData.numOfStudent - numOfDeceasedStudent - numOfEscapedStudent == 1) | |||
| { | |||
| GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Character player in GameObjDict[GameObjType.Character]) | |||
| if (player.PlayerState == PlayerStateType.Addicted) | |||
| { | |||
| Timer.IsGaming = false; | |||
| break; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| if (Timer.IsGaming) | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterWriteLock(); | |||
| try | |||
| { | |||
| foreach (EmergencyExit emergencyExit in GameObjDict[GameObjType.EmergencyExit]) | |||
| if (emergencyExit.CanOpen) | |||
| { | |||
| emergencyExit.IsOpen = true; | |||
| break; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].ExitWriteLock(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private uint numOfRepairedGenerators = 0; | |||
| public uint NumOfRepairedGenerators | |||
| { | |||
| get => Interlocked.CompareExchange(ref numOfDeceasedStudent, 0, 0); | |||
| get => Interlocked.CompareExchange(ref numOfRepairedGenerators, 0, 0); | |||
| } | |||
| public void AddNumOfRepairedGenerators() | |||
| { | |||
| uint value = Interlocked.Increment(ref numOfDeceasedStudent); | |||
| uint value = Interlocked.Increment(ref numOfRepairedGenerators); | |||
| if (value == GameData.numOfGeneratorRequiredForEmergencyExit) | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterWriteLock(); | |||
| @@ -93,33 +49,79 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| private uint numOfDeceasedStudent = 0; | |||
| public uint NumOfDeceasedStudent | |||
| { | |||
| get => numOfDeceasedStudent; | |||
| set | |||
| { | |||
| lock (lockForNum) | |||
| { | |||
| numOfDeceasedStudent = value; | |||
| WhenStudentNumChange(); | |||
| } | |||
| } | |||
| get => Interlocked.CompareExchange(ref numOfDeceasedStudent, 0, 0); | |||
| } | |||
| private uint numOfEscapedStudent = 0; | |||
| public uint NumOfEscapedStudent | |||
| { | |||
| get => numOfEscapedStudent; | |||
| set | |||
| get => Interlocked.CompareExchange(ref numOfEscapedStudent, 0, 0); | |||
| } | |||
| private uint numOfNoHpStudent = 0; | |||
| public uint NumOfNoHpStudent | |||
| { | |||
| get => Interlocked.CompareExchange(ref numOfNoHpStudent, 0, 0); | |||
| } | |||
| private uint numOfRemovedStudent = 0; | |||
| public uint NumOfRemovedStudent | |||
| { | |||
| get => Interlocked.CompareExchange(ref numOfRemovedStudent, 0, 0); | |||
| } | |||
| public void MapEscapeStudent() | |||
| { | |||
| if (Interlocked.Increment(ref numOfNoHpStudent) == GameData.numOfStudent) | |||
| { | |||
| lock (lockForNum) | |||
| { | |||
| numOfEscapedStudent = value; | |||
| WhenStudentNumChange(); | |||
| } | |||
| Timer.IsGaming = false; | |||
| return; | |||
| } | |||
| Interlocked.Increment(ref numOfEscapedStudent); | |||
| if (Interlocked.Increment(ref numOfRemovedStudent) == GameData.numOfStudent - 1) | |||
| OpenEmergencyExit(); | |||
| } | |||
| public void MapDieStudent() | |||
| { | |||
| if (Interlocked.Increment(ref numOfNoHpStudent) == GameData.numOfStudent) | |||
| { | |||
| Timer.IsGaming = false; | |||
| return; | |||
| } | |||
| Interlocked.Increment(ref numOfDeceasedStudent); | |||
| if (Interlocked.Increment(ref numOfRemovedStudent) == GameData.numOfStudent - 1) | |||
| OpenEmergencyExit(); | |||
| } | |||
| public void MapAddictStudent() | |||
| { | |||
| if (Interlocked.Increment(ref numOfNoHpStudent) == GameData.numOfStudent) | |||
| Timer.IsGaming = false; | |||
| } | |||
| public void MapRescueStudent() | |||
| { | |||
| Interlocked.Decrement(ref numOfNoHpStudent); | |||
| } | |||
| private void OpenEmergencyExit() | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (EmergencyExit emergencyExit in GameObjDict[GameObjType.EmergencyExit]) | |||
| if (emergencyExit.CanOpen) | |||
| { | |||
| emergencyExit.IsOpen = true; | |||
| break; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); | |||
| } | |||
| } | |||
| private Dictionary<GameObjType, IList<IGameObj>> gameObjDict; | |||
| public Dictionary<GameObjType, IList<IGameObj>> GameObjDict => gameObjDict; | |||
| private Dictionary<GameObjType, ReaderWriterLockSlim> gameObjLockDict; | |||
| @@ -163,8 +163,8 @@ namespace Gaming | |||
| if (doorwayForEscape != null && doorwayForEscape.IsOpen()) | |||
| { | |||
| player.AddScore(GameData.StudentScoreEscape); | |||
| ++gameMap.NumOfEscapedStudent; | |||
| player.RemoveFromGame(PlayerStateType.Escaped); | |||
| gameMap.MapEscapeStudent(); | |||
| player.TryToRemoveFromGame(PlayerStateType.Escaped); | |||
| return true; | |||
| } | |||
| else | |||
| @@ -173,8 +173,8 @@ namespace Gaming | |||
| if (emergencyExit != null && emergencyExit.IsOpen) | |||
| { | |||
| player.AddScore(GameData.StudentScoreEscape); | |||
| ++gameMap.NumOfEscapedStudent; | |||
| player.RemoveFromGame(PlayerStateType.Escaped); | |||
| gameMap.MapEscapeStudent(); | |||
| player.TryToRemoveFromGame(PlayerStateType.Escaped); | |||
| return true; | |||
| } | |||
| return false; | |||
| @@ -218,13 +218,18 @@ namespace Gaming | |||
| public void BeAddictedToGame(Student player, Ghost ghost) | |||
| { | |||
| long stateNum = player.SetPlayerState(PlayerStateType.Addicted); | |||
| if (stateNum == -1) | |||
| { | |||
| return; | |||
| } | |||
| if (player.CharacterType == CharacterType.Robot) | |||
| { | |||
| ghost.AddScore(GameData.TrickerScoreDestroyRobot); | |||
| Die(player); | |||
| return; | |||
| } | |||
| ghost.AddScore(GameData.TrickerScoreStudentBeAddicted); | |||
| if (player.GamingAddiction > 0) | |||
| { | |||
| if (player.GamingAddiction < GameData.BeginGamingAddiction) | |||
| @@ -238,16 +243,16 @@ namespace Gaming | |||
| return; | |||
| } | |||
| } | |||
| player.SetPlayerState(PlayerStateType.Addicted); | |||
| long threadNum = player.StateNum; | |||
| ghost.AddScore(GameData.TrickerScoreStudentBeAddicted); | |||
| gameMap.MapAddictStudent(); | |||
| new Thread | |||
| (() => | |||
| { | |||
| #if DEBUG | |||
| Debugger.Output(player, " is addicted "); | |||
| #endif | |||
| new FrameRateTaskExecutor<int>( | |||
| () => threadNum == player.StateNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, | |||
| () => stateNum == player.StateNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, | |||
| () => | |||
| { | |||
| player.GamingAddiction += (player.PlayerState == PlayerStateType.Addicted) ? GameData.frameDuration : 0; | |||
| @@ -255,6 +260,7 @@ namespace Gaming | |||
| timeInterval: GameData.frameDuration, | |||
| () => | |||
| { | |||
| gameMap.MapRescueStudent(); | |||
| if (player.GamingAddiction == player.MaxGamingAddiction && gameMap.Timer.IsGaming) | |||
| { | |||
| ghost.AddScore(GameData.TrickerScoreStudentDie); | |||
| @@ -397,11 +403,9 @@ namespace Gaming | |||
| public void Die(Student player) | |||
| { | |||
| #if DEBUG | |||
| Debugger.Output(player, "die."); | |||
| #endif | |||
| if (player.PlayerState == PlayerStateType.Deceased) return; | |||
| player.RemoveFromGame(PlayerStateType.Deceased); | |||
| if (!player.TryToRemoveFromGame(PlayerStateType.Deceased)) return; | |||
| for (int i = 0; i < GameData.maxNumOfPropInPropInventory; i++) | |||
| { | |||
| @@ -430,9 +434,8 @@ namespace Gaming | |||
| } | |||
| return; | |||
| } | |||
| ++gameMap.NumOfDeceasedStudent; | |||
| gameMap.MapDieStudent(); | |||
| } | |||
| } | |||
| } | |||
| } | |||