| @@ -13,16 +13,6 @@ namespace GameClass.GameObj | |||
| { | |||
| public Ghost(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType) : base(initPos, initRadius, initPlace, characterType) | |||
| { | |||
| switch (characterType) | |||
| { | |||
| case CharacterType.Assassin: | |||
| this.Occupation = new Assassin(); | |||
| break; | |||
| default: | |||
| this.Occupation = null; | |||
| break; | |||
| } | |||
| this.CharacterType = characterType; | |||
| } | |||
| } | |||
| } | |||
| @@ -7,9 +7,10 @@ namespace GameClass.GameObj | |||
| { | |||
| public partial class Character | |||
| { | |||
| public CharacterType CharacterType { protected set; get; } | |||
| public IOccupation Occupation { protected set; get; } | |||
| private readonly CharacterType characterType; | |||
| public CharacterType CharacterType => characterType; | |||
| private readonly IOccupation occupation; | |||
| public IOccupation Occupation => occupation; | |||
| private Dictionary<ActiveSkillType, int> timeUntilActiveSkillAvailable; | |||
| public Dictionary<ActiveSkillType, int> TimeUntilActiveSkillAvailable => timeUntilActiveSkillAvailable; | |||
| @@ -65,7 +66,18 @@ namespace GameClass.GameObj | |||
| this.score = 0; | |||
| this.propInventory = null; | |||
| this.buffManager = new BuffManager(); | |||
| switch (characterType) | |||
| { | |||
| case CharacterType.Assassin: | |||
| this.occupation = new Assassin(); | |||
| break; | |||
| case CharacterType.Athlete: | |||
| this.occupation = new Athlete(); | |||
| break; | |||
| default: | |||
| this.occupation = null; | |||
| break; | |||
| } | |||
| this.MaxHp = Occupation.MaxHp; | |||
| this.hp = Occupation.MaxHp; | |||
| this.OrgMoveSpeed = Occupation.MoveSpeed; | |||
| @@ -75,6 +87,7 @@ namespace GameClass.GameObj | |||
| this.bulletNum = maxBulletNum; | |||
| this.bulletOfPlayer = Occupation.InitBullet; | |||
| this.OriBulletOfPlayer = Occupation.InitBullet; | |||
| this.characterType = characterType; | |||
| foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | |||
| { | |||
| @@ -95,7 +95,7 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public void Escape() | |||
| public Student(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType) : base(initPos, initRadius, initPlace, characterType) | |||
| { | |||
| lock (gameObjLock) | |||
| IsResetting = true; | |||
| @@ -113,7 +113,6 @@ namespace GameClass.GameObj | |||
| break; | |||
| } | |||
| this.fixSpeed = ((IStudent)Occupation).FixSpeed; | |||
| this.CharacterType = characterType; | |||
| } | |||
| } | |||
| } | |||
| @@ -470,11 +470,22 @@ namespace GameClass.GameObj | |||
| this.Vampire = this.OriVampire; | |||
| } | |||
| } | |||
| public void Die(PlayerStateType playerStateType) | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| playerState = playerStateType; | |||
| CanMove = false; | |||
| IsResetting = true; | |||
| } | |||
| } | |||
| public override bool IsRigid => true; | |||
| public override ShapeType Shape => ShapeType.Circle; | |||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||
| { | |||
| if (IsResetting) | |||
| return true; | |||
| if (targetObj.Type == GameObjType.Prop) // 自己队的地雷忽略碰撞 | |||
| { | |||
| return true; | |||
| @@ -3,6 +3,7 @@ using System.Threading; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using System; | |||
| using GameClass.GameObj; | |||
| namespace GameClass.GameObj | |||
| { | |||
| @@ -72,6 +73,40 @@ namespace GameClass.GameObj | |||
| } | |||
| return player; | |||
| } | |||
| public bool Remove(GameObj gameObj) | |||
| { | |||
| bool flag = false; | |||
| GameObjLockDict[gameObj.Type].EnterWriteLock(); | |||
| try | |||
| { | |||
| foreach (GameObj obj in GameObjDict[gameObj.Type]) | |||
| { | |||
| if (gameObj.ID == obj.ID) | |||
| { | |||
| GameObjDict[gameObj.Type].Remove(obj); | |||
| flag = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[gameObj.Type].ExitWriteLock(); | |||
| } | |||
| return flag; | |||
| } | |||
| public void Add(GameObj gameObj) | |||
| { | |||
| GameObjLockDict[gameObj.Type].EnterWriteLock(); | |||
| try | |||
| { | |||
| GameObjDict[gameObj.Type].Add(gameObj); | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[gameObj.Type].ExitWriteLock(); | |||
| } | |||
| } | |||
| public Map(uint[,] mapResource) | |||
| { | |||
| gameObjDict = new Dictionary<GameObjType, IList<IGameObj>>(); | |||
| @@ -132,7 +132,7 @@ namespace Gaming | |||
| if (doorwayForEscape != null && doorwayForEscape.IsOpen) | |||
| { | |||
| player.Escape(); | |||
| player.Die(PlayerStateType.IsEscaped); | |||
| return true; | |||
| } | |||
| else | |||
| @@ -100,7 +100,7 @@ namespace Gaming | |||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||
| } | |||
| player.Reset(); | |||
| // player.Reset(); | |||
| // ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 | |||
| /* new Thread | |||
| @@ -154,31 +154,9 @@ namespace Gaming | |||
| Debugger.Output(bullet, "bombed!"); | |||
| #endif | |||
| bullet.CanMove = false; | |||
| gameMap.GameObjLockDict[GameObjType.Bullet].EnterWriteLock(); | |||
| try | |||
| { | |||
| foreach (ObjOfCharacter _bullet in gameMap.GameObjDict[GameObjType.Bullet]) | |||
| { | |||
| if (_bullet.ID == bullet.ID) | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.BombedBullet].EnterWriteLock(); | |||
| try | |||
| { | |||
| gameMap.GameObjDict[GameObjType.BombedBullet].Add(new BombedBullet(bullet)); | |||
| } | |||
| finally | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.BombedBullet].ExitWriteLock(); | |||
| } | |||
| gameMap.GameObjDict[GameObjType.Bullet].Remove(_bullet); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); | |||
| } | |||
| if (gameMap.Remove(bullet) && bullet.IsToBomb) | |||
| gameMap.Add(new BombedBullet(bullet)); | |||
| if (!bullet.IsToBomb) | |||
| { | |||
| @@ -334,12 +312,27 @@ namespace Gaming | |||
| new Thread | |||
| (() => | |||
| { | |||
| Thread.Sleep(bullet.CastTime); | |||
| if (gameMap.Timer.IsGaming && player.PlayerState == PlayerStateType.IsTryingToAttack) | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => player.PlayerState == PlayerStateType.IsTryingToAttack && gameMap.Timer.IsGaming, | |||
| loopToDo: () => | |||
| { | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0, | |||
| maxTotalDuration: bullet.CastTime | |||
| ) | |||
| .Start(); | |||
| if (gameMap.Timer.IsGaming) | |||
| { | |||
| player.PlayerState = PlayerStateType.Null; | |||
| if (player.PlayerState == PlayerStateType.IsTryingToAttack) | |||
| { | |||
| player.PlayerState = PlayerStateType.Null; | |||
| } | |||
| else | |||
| bullet.IsMoving = false; | |||
| gameMap.Remove(bullet); | |||
| } | |||
| } | |||
| ) | |||
| @@ -81,6 +81,7 @@ namespace Preparation.Utility | |||
| public const int bulletRadius = 200; // 默认子弹半径 | |||
| public const int reviveTime = 30000; // 复活时间 | |||
| public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间 | |||
| public static XY PosWhoDie = new XY(1, 1); | |||
| public static bool IsGhost(CharacterType characterType) | |||
| { | |||
| @@ -392,17 +392,17 @@ namespace Server | |||
| msg.MessageOfBullet.ParentTeamID = bullet.Parent.TeamID; | |||
| switch (bullet.Place) | |||
| { | |||
| case Preparation.Utility.PlacccceType.Land: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Land; | |||
| case Preparation.Utility.PlaceType.Null: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Null; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass1: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass1; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass2: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass2; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass3: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass3; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| default: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||
| @@ -459,17 +459,17 @@ namespace Server | |||
| } | |||
| switch (prop.Place) | |||
| { | |||
| case Preparation.Utility.PlacccceType.Land: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Land; | |||
| case Preparation.Utility.PlaceType.Null: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Null; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass1: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass1; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass2: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass2; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlacccceType.Grass3: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass3; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| default: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||