fix: 🐛 fix the bug about int overflows when the teacher uses pubnish
tags/v0.1.0
| @@ -240,8 +240,8 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| #endregion | #endregion | ||||
| #region 血量相关的基本属性及方法 | #region 血量相关的基本属性及方法 | ||||
| private int maxHp; | |||||
| public int MaxHp | |||||
| private long maxHp; | |||||
| public long MaxHp | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| @@ -269,8 +269,8 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| } // 最大血量 | } // 最大血量 | ||||
| protected int hp; | |||||
| public int HP | |||||
| protected long hp; | |||||
| public long HP | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| @@ -307,12 +307,12 @@ namespace GameClass.GameObj | |||||
| /// 尝试减血 | /// 尝试减血 | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="sub">减血量</param> | /// <param name="sub">减血量</param> | ||||
| public int TrySubHp(int sub) | |||||
| public long TrySubHp(long sub) | |||||
| { | { | ||||
| HPReadWriterLock.EnterWriteLock(); | HPReadWriterLock.EnterWriteLock(); | ||||
| try | try | ||||
| { | { | ||||
| int previousHp = hp; | |||||
| long previousHp = hp; | |||||
| if (hp <= sub) | if (hp <= sub) | ||||
| { | { | ||||
| hp = 0; | hp = 0; | ||||
| @@ -1,4 +1,5 @@ | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System.Threading; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -17,20 +18,25 @@ namespace GameClass.GameObj | |||||
| private int numOfFixing = 0; | private int numOfFixing = 0; | ||||
| public int NumOfFixing | public int NumOfFixing | ||||
| { | { | ||||
| get => numOfFixing; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| numOfFixing = value; | |||||
| } | |||||
| } | |||||
| get => Interlocked.CompareExchange(ref numOfFixing, 0, 0); | |||||
| } | |||||
| public void AddNumOfFixing() | |||||
| { | |||||
| Interlocked.Increment(ref numOfFixing); | |||||
| } | |||||
| public void SubNumOfFixing() | |||||
| { | |||||
| Interlocked.Decrement(ref numOfFixing); | |||||
| } | } | ||||
| private int degreeOfRepair = 0; | private int degreeOfRepair = 0; | ||||
| public int DegreeOfRepair | public int DegreeOfRepair | ||||
| { | { | ||||
| get => degreeOfRepair; | |||||
| get | |||||
| { | |||||
| lock (gameObjLock) | |||||
| return degreeOfRepair; | |||||
| } | |||||
| private set | private set | ||||
| { | { | ||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| @@ -76,35 +76,43 @@ namespace Gaming | |||||
| public bool Fix(Student player)// 自动检查有无发电机可修 | public bool Fix(Student player)// 自动检查有无发电机可修 | ||||
| { | { | ||||
| if ((!player.Commandable()) || player.PlayerState == PlayerStateType.Fixing) | |||||
| return false; | |||||
| Generator? generatorForFix = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); | Generator? generatorForFix = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); | ||||
| if (generatorForFix == null) return false; | |||||
| long stateNum = player.SetPlayerState(PlayerStateType.Fixing); | |||||
| if (stateNum == -1) return false; | |||||
| if (generatorForFix == null || generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) | |||||
| player.ThreadNum.WaitOne(); | |||||
| if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) | |||||
| return false; | return false; | ||||
| ++generatorForFix.NumOfFixing; | |||||
| player.SetPlayerState(PlayerStateType.Fixing); | |||||
| long threadNum = player.StateNum; | |||||
| generatorForFix.AddNumOfFixing(); | |||||
| new Thread | new Thread | ||||
| ( | ( | ||||
| () => | () => | ||||
| { | { | ||||
| Thread.Sleep(GameData.frameDuration); | |||||
| Thread.Sleep(GameData.checkInterval); | |||||
| new FrameRateTaskExecutor<int>( | new FrameRateTaskExecutor<int>( | ||||
| loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.StateNum, | |||||
| loopCondition: () => stateNum == player.StateNum && gameMap.Timer.IsGaming, | |||||
| loopToDo: () => | loopToDo: () => | ||||
| { | { | ||||
| if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) | |||||
| if (generatorForFix.Repair(player.FixSpeed * GameData.checkInterval, player)) | |||||
| gameMap.NumOfRepairedGenerators++; | gameMap.NumOfRepairedGenerators++; | ||||
| if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) | if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator) | ||||
| player.SetPlayerState();//Num == player.StateNum | |||||
| { | |||||
| lock (player.ActionLock) | |||||
| { | |||||
| if (stateNum == player.StateNum) | |||||
| player.SetPlayerState(); | |||||
| } | |||||
| } | |||||
| }, | }, | ||||
| timeInterval: GameData.frameDuration, | |||||
| timeInterval: GameData.checkInterval, | |||||
| finallyReturn: () => 0 | finallyReturn: () => 0 | ||||
| ) | ) | ||||
| .Start(); | .Start(); | ||||
| --generatorForFix.NumOfFixing; | |||||
| player.ThreadNum.Release(); | |||||
| generatorForFix.SubNumOfFixing(); | |||||
| } | } | ||||
| ) | ) | ||||
| @@ -248,6 +248,7 @@ namespace Gaming | |||||
| new Thread | new Thread | ||||
| (() => | (() => | ||||
| { | { | ||||
| Debugger.Output(player, " is stunned for " + time.ToString()); | |||||
| Thread.Sleep(time); | Thread.Sleep(time); | ||||
| if (threadNum == player.StateNum) | if (threadNum == player.StateNum) | ||||
| player.SetPlayerState(); | player.SetPlayerState(); | ||||
| @@ -297,18 +298,18 @@ namespace Gaming | |||||
| { | { | ||||
| if (bullet.HasSpear) | if (bullet.HasSpear) | ||||
| { | { | ||||
| int subHp = student.TrySubHp(bullet.AP); | |||||
| long subHp = student.TrySubHp(bullet.AP); | |||||
| #if DEBUG | #if DEBUG | ||||
| Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); | Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); | ||||
| #endif | #endif | ||||
| bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear); | bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear); | ||||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||||
| bullet.Parent.HP = (long)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp)); | |||||
| } | } | ||||
| else return; | else return; | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| int subHp; | |||||
| long subHp; | |||||
| if (bullet.HasSpear) | if (bullet.HasSpear) | ||||
| { | { | ||||
| subHp = student.TrySubHp(bullet.AP + GameData.ApSpearAdd); | subHp = student.TrySubHp(bullet.AP + GameData.ApSpearAdd); | ||||
| @@ -354,8 +354,8 @@ namespace Gaming | |||||
| || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | || character.PlayerState == PlayerStateType.ClimbingThroughWindows) | ||||
| && XY.DistanceFloor3(character.Position, player.Position) <= player.ViewRange / 3) | && XY.DistanceFloor3(character.Position, player.Position) <= player.ViewRange / 3) | ||||
| { | { | ||||
| if (CharacterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost) > 0) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost)); | |||||
| if (CharacterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + (int)((GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost))) > 0) | |||||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenPunish + (int)(GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP) / GameData.basicApOfGhost))); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -6,7 +6,7 @@ namespace Preparation.Interface | |||||
| public interface ICharacter : IMoveable | public interface ICharacter : IMoveable | ||||
| { | { | ||||
| public long TeamID { get; } | public long TeamID { get; } | ||||
| public int HP { get; set; } | |||||
| public long HP { get; set; } | |||||
| public long Score { get; } | public long Score { get; } | ||||
| public void AddScore(long add); | public void AddScore(long add); | ||||
| public double Vampire { get; } | public double Vampire { get; } | ||||
| @@ -137,7 +137,7 @@ namespace Preparation.Utility | |||||
| } | } | ||||
| #endregion | #endregion | ||||
| #region 得分相关 | #region 得分相关 | ||||
| public static int TrickerScoreAttackStudent(int damage) | |||||
| public static long TrickerScoreAttackStudent(long damage) | |||||
| { | { | ||||
| return damage * 100 / basicApOfGhost; | return damage * 100 / basicApOfGhost; | ||||
| } | } | ||||
| @@ -167,7 +167,7 @@ namespace Preparation.Utility | |||||
| return time * 20 / 1000; | return time * 20 / 1000; | ||||
| } | } | ||||
| public const int StudentScoreRescue = 100; | public const int StudentScoreRescue = 100; | ||||
| public static int StudentScoreTreat(int degree) | |||||
| public static long StudentScoreTreat(long degree) | |||||
| { | { | ||||
| return degree * 50 / basicTreatmentDegree; | return degree * 50 / basicTreatmentDegree; | ||||
| } | } | ||||
| @@ -58,8 +58,8 @@ namespace Server | |||||
| { | { | ||||
| X = player.Position.x, | X = player.Position.x, | ||||
| Y = player.Position.y, | Y = player.Position.y, | ||||
| Speed = (int)player.MoveSpeed, | |||||
| Determination = player.HP, | |||||
| Speed = player.MoveSpeed, | |||||
| Determination = (int)player.HP, | |||||
| Addiction = player.GamingAddiction, | Addiction = player.GamingAddiction, | ||||
| Guid = player.ID, | Guid = player.ID, | ||||