| @@ -17,5 +17,9 @@ | |||
| - feat:增加了可选地图功能 | |||
| - **脚本RunServer(ForDebug).cmd/sh现在支持可选地图功能,但想选择地图,选手需要自行参照使用文档修改命令行或在云盘下载脚本** | |||
| # 5月9日更新 | |||
| - docs:更新了 游戏机制与平衡性调整更新草案.pdf | |||
| - change:更改了地图的文件路径 | |||
| # 最新更新 | |||
| - docs:更新了 游戏机制与平衡性调整更新草案.pdf | |||
| - | |||
| @@ -1,8 +1,6 @@ | |||
| using Preparation.Utility; | |||
| using Preparation.Interface; | |||
| using System.Collections.Generic; | |||
| using System; | |||
| using System.Numerics; | |||
| namespace GameClass.GameObj | |||
| { | |||
| @@ -2,15 +2,14 @@ | |||
| using Preparation.Utility; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| using System.Threading; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终了 | |||
| { | |||
| #region 装弹、攻击相关的基本属性及方法 | |||
| private readonly object attackLock = new(); | |||
| public object AttackLock => attackLock; | |||
| /// <summary> | |||
| /// 装弹冷却 | |||
| /// </summary> | |||
| @@ -19,7 +18,7 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| return cd; | |||
| } | |||
| @@ -33,14 +32,14 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| return bulletOfPlayer; | |||
| } | |||
| } | |||
| set | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| bulletOfPlayer = value; | |||
| cd = OrgCD = (BulletFactory.BulletCD(value)); | |||
| @@ -55,7 +54,7 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| return maxBulletNum; | |||
| } | |||
| @@ -66,7 +65,7 @@ namespace GameClass.GameObj | |||
| public int UpdateBulletNum(int time) | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| if (bulletNum < maxBulletNum) | |||
| { | |||
| @@ -84,7 +83,7 @@ namespace GameClass.GameObj | |||
| /// <returns>攻击操作发出的子弹</returns> | |||
| public Bullet? Attack(double angle, int time) | |||
| { | |||
| lock (attackLock) | |||
| lock (actionLock) | |||
| { | |||
| if (bulletOfPlayer == BulletType.Null) | |||
| return null; | |||
| @@ -92,10 +91,11 @@ namespace GameClass.GameObj | |||
| { | |||
| if (bulletNum == maxBulletNum) updateTimeOfBulletNum = time; | |||
| --bulletNum; | |||
| XY res = Position + new XY // 子弹紧贴人物生成。 | |||
| ( | |||
| (int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1), | |||
| (int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1) | |||
| (int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | |||
| (int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | |||
| ); | |||
| Bullet? bullet = BulletFactory.GetBullet(this, res); | |||
| if (bullet == null) return null; | |||
| @@ -326,14 +326,11 @@ namespace GameClass.GameObj | |||
| private GameObj? whatInteractingWith = null; | |||
| public GameObj? WhatInteractingWith => whatInteractingWith; | |||
| private long threadNum = 0; | |||
| public long ThreadNum => threadNum; | |||
| public void ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| ++threadNum; | |||
| stateNum= Interlocked.Increment(ref stateNum); | |||
| whatInteractingWith = gameObj; | |||
| if (value != PlayerStateType.Moving) | |||
| IsMoving = false; | |||
| @@ -344,7 +341,7 @@ namespace GameClass.GameObj | |||
| public void ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| whatInteractingWith = gameObj; | |||
| if (value != PlayerStateType.Moving) | |||
| @@ -356,9 +353,9 @@ namespace GameClass.GameObj | |||
| public void SetPlayerStateNaturally() | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| ++threadNum; | |||
| stateNum= Interlocked.Increment(ref stateNum); | |||
| whatInteractingWith = null; | |||
| IsMoving = false; | |||
| playerState = PlayerStateType.Null; | |||
| @@ -370,7 +367,7 @@ namespace GameClass.GameObj | |||
| MoveReaderWriterLock.EnterWriteLock(); | |||
| try | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| playerState = playerStateType; | |||
| canMove = false; | |||
| @@ -6,17 +6,22 @@ namespace GameClass.GameObj | |||
| { | |||
| public abstract class Moveable : GameObj, IMoveable | |||
| { | |||
| protected readonly object moveObjLock = new(); | |||
| public object MoveLock => moveObjLock; | |||
| protected readonly object actionLock = new(); | |||
| public object ActionLock => actionLock; | |||
| private readonly ReaderWriterLockSlim moveReaderWriterLock = new(); | |||
| public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock; | |||
| //规定moveReaderWriterLock>moveObjLock | |||
| protected long stateNum = 0; | |||
| public long StateNum | |||
| { | |||
| get=>Interlocked.Read(ref stateNum); | |||
| } | |||
| //规定moveReaderWriterLock>actionLock | |||
| public override XY Position | |||
| { | |||
| get | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| return position; | |||
| } | |||
| } | |||
| @@ -25,7 +30,7 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| return facingDirection; | |||
| } | |||
| } | |||
| @@ -35,12 +40,12 @@ namespace GameClass.GameObj | |||
| { | |||
| get | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| return isMoving; | |||
| } | |||
| set | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| isMoving = value; | |||
| } | |||
| @@ -51,7 +56,7 @@ namespace GameClass.GameObj | |||
| public long MovingSetPos(XY moveVec) | |||
| { | |||
| if (moveVec.x != 0 || moveVec.y != 0) | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| facingDirection = moveVec; | |||
| this.position += moveVec; | |||
| @@ -61,7 +66,7 @@ namespace GameClass.GameObj | |||
| public void ReSetPos(XY position) | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| this.position = position; | |||
| } | |||
| @@ -88,7 +93,7 @@ namespace GameClass.GameObj | |||
| moveReaderWriterLock.EnterWriteLock(); | |||
| try | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| canMove = value; | |||
| } | |||
| @@ -141,7 +146,7 @@ namespace GameClass.GameObj | |||
| moveReaderWriterLock.EnterWriteLock(); | |||
| try | |||
| { | |||
| lock (moveObjLock) | |||
| lock (actionLock) | |||
| { | |||
| moveSpeed = value; | |||
| } | |||
| @@ -80,12 +80,12 @@ namespace GameEngine | |||
| if (!obj.IsAvailable || !gameTimer.IsGaming) | |||
| return; | |||
| long threadNum = (obj.Type == GameObjType.Character) ? ((ICharacter)obj).ThreadNum : 0;//对人特殊处理 | |||
| long threadNum = (obj.Type == GameObjType.Character) ? ((ICharacter)obj).StateNum : 0;//对人特殊处理 | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| lock (obj.MoveLock) | |||
| lock (obj.ActionLock) | |||
| obj.IsMoving = true; | |||
| double moveVecLength = 0.0; | |||
| @@ -126,7 +126,7 @@ namespace GameEngine | |||
| res = new XY(direction, moveVecLength); | |||
| //对人特殊处理 | |||
| if (threadNum > 0 && ((ICharacter)obj).ThreadNum != threadNum) return false; | |||
| if (threadNum > 0 && ((ICharacter)obj).StateNum != threadNum) return false; | |||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||
| bool flag; // 循环标志 | |||
| @@ -147,7 +147,7 @@ namespace GameEngine | |||
| isDestroyed = true; | |||
| return false; | |||
| case AfterCollision.MoveMax: | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum) | |||
| MoveMax(obj, res); | |||
| moveVecLength = 0; | |||
| res = new XY(direction, moveVecLength); | |||
| @@ -155,7 +155,7 @@ namespace GameEngine | |||
| } | |||
| } while (flag); | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum) | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res)); | |||
| return true; | |||
| @@ -174,7 +174,7 @@ namespace GameEngine | |||
| res = new XY(direction, moveVecLength); | |||
| if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) | |||
| { | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum) | |||
| obj.MovingSetPos(res); | |||
| } | |||
| else | |||
| @@ -189,7 +189,7 @@ namespace GameEngine | |||
| isDestroyed = true; | |||
| break; | |||
| case AfterCollision.MoveMax: | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum) | |||
| MoveMax(obj, res); | |||
| moveVecLength = 0; | |||
| res = new XY(direction, moveVecLength); | |||
| @@ -202,7 +202,7 @@ namespace GameEngine | |||
| { | |||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||
| } | |||
| lock (obj.MoveLock) | |||
| lock (obj.ActionLock) | |||
| obj.IsMoving = false; // 结束移动 | |||
| EndMove(obj); | |||
| return 0; | |||
| @@ -72,14 +72,14 @@ namespace Gaming | |||
| ++generatorForFix.NumOfFixing; | |||
| characterManager.SetPlayerState(player, PlayerStateType.Fixing); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| Thread.Sleep(GameData.frameDuration); | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.ThreadNum, | |||
| loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.StateNum, | |||
| loopToDo: () => | |||
| { | |||
| if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player)) | |||
| @@ -173,10 +173,10 @@ namespace Gaming | |||
| { | |||
| characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated); | |||
| characterManager.SetPlayerState(player, PlayerStateType.Treating); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && threadNum == player.ThreadNum && gameMap.Timer.IsGaming, | |||
| loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player)) | |||
| @@ -187,7 +187,7 @@ namespace Gaming | |||
| ) | |||
| .Start(); | |||
| if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player); | |||
| if (threadNum == player.StateNum) characterManager.SetPlayerState(player); | |||
| else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated); | |||
| } | |||
| ) | |||
| @@ -205,14 +205,14 @@ namespace Gaming | |||
| return false; | |||
| characterManager.SetPlayerState(player, PlayerStateType.Rescuing); | |||
| characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && threadNum == player.ThreadNum && gameMap.Timer.IsGaming, | |||
| loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| playerRescued.TimeOfRescue += GameData.frameDuration; | |||
| @@ -234,7 +234,7 @@ namespace Gaming | |||
| else | |||
| characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted); | |||
| } | |||
| if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player); | |||
| if (threadNum == player.StateNum) characterManager.SetPlayerState(player); | |||
| playerRescued.TimeOfRescue = 0; | |||
| } | |||
| ) | |||
| @@ -303,14 +303,14 @@ namespace Gaming | |||
| // gameMap.Add(addWall); | |||
| characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| windowForClimb.WhoIsClimbing = player; | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming, | |||
| loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||
| loopToDo: () => { }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0, | |||
| @@ -329,7 +329,7 @@ namespace Gaming | |||
| moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle()); | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming, | |||
| loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| }, | |||
| @@ -343,7 +343,7 @@ namespace Gaming | |||
| player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed); | |||
| windowForClimb.WhoIsClimbing = null; | |||
| // gameMap.Remove(addWall); | |||
| if (threadNum == player.ThreadNum) | |||
| if (threadNum == player.StateNum) | |||
| { | |||
| characterManager.SetPlayerState(player); | |||
| } | |||
| @@ -386,13 +386,13 @@ namespace Gaming | |||
| if (!flag) return false; | |||
| characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => flag && threadNum == player.ThreadNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor, | |||
| loopCondition: () => flag && threadNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor, | |||
| loopToDo: () => | |||
| { | |||
| flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null); | |||
| @@ -407,7 +407,7 @@ namespace Gaming | |||
| { | |||
| doorToLock.IsOpen = (!doorToLock.IsOpen); | |||
| } | |||
| if (threadNum == player.ThreadNum) | |||
| if (threadNum == player.StateNum) | |||
| characterManager.SetPlayerState(player); | |||
| doorToLock.OpenOrLockDegree = 0; | |||
| } | |||
| @@ -39,6 +39,17 @@ namespace Gaming | |||
| this.characterManager = characterManager; | |||
| } | |||
| public void ProduceBulletNaturally(BulletType bulletType, Character player, double angle,XY pos) | |||
| { | |||
| // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | |||
| if (bulletType == BulletType.Null)return; | |||
| Bullet? bullet = BulletFactory.GetBullet(player, pos); | |||
| if (bullet == null) return; | |||
| Debugger.Output(bullet, "Attack in " + pos.ToString()); | |||
| gameMap.Add(bullet); | |||
| moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(bulletType)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | |||
| } | |||
| private void BombObj(Bullet bullet, GameObj objBeingShot) | |||
| { | |||
| #if DEBUG | |||
| @@ -122,9 +133,21 @@ namespace Gaming | |||
| if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null) | |||
| { | |||
| bullet.Parent!.BulletOfPlayer = BulletType.JumpyDumpty; | |||
| Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0); | |||
| Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0); | |||
| double angle = bullet.FacingDirection.Angle() + Math.PI / 2.0; | |||
| XY pos = bullet.Position + new XY // 子弹紧贴人物生成。 | |||
| ( | |||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | |||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | |||
| ); | |||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos); | |||
| angle = bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0; | |||
| pos = bullet.Position + new XY // 子弹紧贴人物生成。 | |||
| ( | |||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), | |||
| (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) | |||
| ); | |||
| ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos); | |||
| } | |||
| var beAttackedList = new List<IGameObj>(); | |||
| @@ -173,17 +196,17 @@ namespace Gaming | |||
| Debugger.Output(bullet, "Attack in " + bullet.Position.ToString()); | |||
| bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0; | |||
| gameMap.Add(bullet); | |||
| moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | |||
| moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(bullet.TypeOfBullet)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | |||
| if (bullet.CastTime > 0) | |||
| { | |||
| characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| (() => | |||
| { | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming, | |||
| loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| }, | |||
| @@ -195,7 +218,7 @@ namespace Gaming | |||
| if (gameMap.Timer.IsGaming) | |||
| { | |||
| if (threadNum == player.ThreadNum) | |||
| if (threadNum == player.StateNum) | |||
| { | |||
| characterManager.SetPlayerState(player); | |||
| } | |||
| @@ -1,5 +1,4 @@ | |||
| using System; | |||
| using System.Threading; | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using Preparation.Utility; | |||
| using Preparation.Interface; | |||
| @@ -20,7 +19,7 @@ namespace Gaming | |||
| public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) | |||
| { | |||
| lock (player.MoveLock) | |||
| lock (player.ActionLock) | |||
| { | |||
| switch (player.PlayerState) | |||
| { | |||
| @@ -246,7 +245,7 @@ namespace Gaming | |||
| } | |||
| } | |||
| SetPlayerState(player, PlayerStateType.Addicted); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| (() => | |||
| { | |||
| @@ -254,7 +253,7 @@ namespace Gaming | |||
| Debugger.Output(player, " is addicted "); | |||
| #endif | |||
| new FrameRateTaskExecutor<int>( | |||
| () => threadNum == player.ThreadNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, | |||
| () => threadNum == player.StateNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, | |||
| () => | |||
| { | |||
| player.GamingAddiction += (player.PlayerState == PlayerStateType.Addicted) ? GameData.frameDuration : 0; | |||
| @@ -283,9 +282,9 @@ namespace Gaming | |||
| (() => | |||
| { | |||
| SetPlayerState(player, PlayerStateType.Stunned); | |||
| long threadNum = player.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| Thread.Sleep(time); | |||
| if (threadNum == player.ThreadNum) | |||
| if (threadNum == player.StateNum) | |||
| SetPlayerState(player); | |||
| } | |||
| ) | |||
| @@ -373,14 +372,14 @@ namespace Gaming | |||
| 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.ThreadNum; | |||
| long threadNum = player.StateNum; | |||
| new Thread | |||
| (() => | |||
| { | |||
| Thread.Sleep(time); | |||
| if (threadNum == player.ThreadNum) | |||
| if (threadNum == player.StateNum) | |||
| { | |||
| SetPlayerState(player); | |||
| } | |||
| @@ -14,7 +14,7 @@ namespace Preparation.Interface | |||
| public BulletType BulletOfPlayer { get; set; } | |||
| public CharacterType CharacterType { get; } | |||
| public int UpdateBulletNum(int time); | |||
| public long ThreadNum { get; } | |||
| public long StateNum { get; } | |||
| public bool IsGhost(); | |||
| } | |||
| @@ -5,7 +5,7 @@ namespace Preparation.Interface | |||
| { | |||
| public interface IMoveable : IGameObj | |||
| { | |||
| object MoveLock { get; } | |||
| object ActionLock { get; } | |||
| public int MoveSpeed { get; } | |||
| public bool IsMoving { get; set; } | |||
| public bool IsResetting { get; } // reviving | |||