diff --git a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs index 122e71d..ed9fc2b 100644 --- a/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs @@ -15,6 +15,7 @@ namespace GameClass.GameObj public override int AP => GameData.basicApOfGhost; public override int Speed => GameData.basicBulletMoveSpeed; public override bool IsToBomb => false; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing; public override int RecoveryFromHit => GameData.basicRecoveryFromHit; public override bool CanAttack(GameObj target) @@ -36,6 +37,7 @@ namespace GameClass.GameObj public override int AP => GameData.basicApOfGhost / 5 * 4; public override int Speed => GameData.basicBulletMoveSpeed * 2; public override bool IsToBomb => false; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing / 5 * 3; public override int RecoveryFromHit => GameData.basicRecoveryFromHit / 4 * 3; public override bool CanAttack(GameObj target) @@ -57,6 +59,7 @@ namespace GameClass.GameObj public override double BulletAttackRange => GameData.basicAttackShortRange / 9 * 7; public override int AP => GameData.basicApOfGhost / 3 * 7; public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing; public override int RecoveryFromHit => GameData.basicRecoveryFromHit; public override bool IsToBomb => true; @@ -80,6 +83,7 @@ namespace GameClass.GameObj public override double BulletAttackRange => GameData.basicAttackShortRange / 2; public override int AP => GameData.basicApOfGhost / 6 * 5; public override int Speed => GameData.basicBulletMoveSpeed / 6 * 5; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing; public override int RecoveryFromHit => GameData.basicRecoveryFromHit; public override bool IsToBomb => true; @@ -102,6 +106,7 @@ namespace GameClass.GameObj public override double BulletAttackRange => GameData.basicAttackShortRange; public override int AP => (int)(0.5 * GameData.basicApOfGhost); public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing; public override int RecoveryFromHit => GameData.basicRecoveryFromHit; public override bool IsToBomb => true; @@ -125,6 +130,7 @@ namespace GameClass.GameObj public override double BulletAttackRange => 0.1 * GameData.basicAttackShortRange; public override int AP => GameData.basicApOfGhost / 3 * 2; public override int Speed => GameData.basicBulletMoveSpeed / 3; + public override int CastTime => GameData.basicCastTime; public override int Backswing => GameData.basicBackswing; public override int RecoveryFromHit => GameData.basicRecoveryFromHit; public override bool IsToBomb => true; diff --git a/logic/GameClass/GameObj/Bullet/Bullet.cs b/logic/GameClass/GameObj/Bullet/Bullet.cs index be38fa7..18a4d30 100644 --- a/logic/GameClass/GameObj/Bullet/Bullet.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.cs @@ -14,6 +14,7 @@ namespace GameClass.GameObj public abstract int AP { get; } public abstract int Speed { get; } public abstract bool IsToBomb { get; } + public abstract int CastTime { get; } public abstract int Backswing { get; } public abstract int RecoveryFromHit { get; } @@ -32,7 +33,7 @@ namespace GameClass.GameObj protected override bool IgnoreCollideExecutor(IGameObj targetObj) { - if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) + if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) return true; return false; } diff --git a/logic/GameClass/GameObj/Character/Character.Ghost.cs b/logic/GameClass/GameObj/Character/Character.Ghost.cs new file mode 100644 index 0000000..e58d057 --- /dev/null +++ b/logic/GameClass/GameObj/Character/Character.Ghost.cs @@ -0,0 +1,28 @@ +using GameClass.Skill; +using Preparation.Interface; +using Preparation.Utility; +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Threading; + +namespace GameClass.GameObj +{ + public class Ghost : Character + { + public Ghost(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType) : base(initPos, initRadius, initPlace) + { + switch (characterType) + { + case CharacterType.Assassin: + this.Occupation = new Assassin(); + break; + default: + this.Occupation = null; + break; + } + this.CharacterType = characterType; + } + } +} diff --git a/logic/GameClass/GameObj/Character/Character.SkillManager.cs b/logic/GameClass/GameObj/Character/Character.SkillManager.cs index 25e6abf..2d8a41a 100644 --- a/logic/GameClass/GameObj/Character/Character.SkillManager.cs +++ b/logic/GameClass/GameObj/Character/Character.SkillManager.cs @@ -7,11 +7,8 @@ namespace GameClass.GameObj { public partial class Character { - - private readonly CharacterType characterType; - public CharacterType CharacterType => characterType; - private readonly IOccupation occupation; - public IOccupation Occupation => occupation; + public CharacterType CharacterType { protected set; get; } + public IOccupation Occupation { protected set; get; } private Dictionary timeUntilActiveSkillAvailable; public Dictionary TimeUntilActiveSkillAvailable => timeUntilActiveSkillAvailable; @@ -53,39 +50,30 @@ namespace GameClass.GameObj public bool IsGhost() { - return this.characterType switch + return this.CharacterType switch { CharacterType.Assassin => true, _ => false, }; } - public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) : + protected Character(XY initPos, int initRadius, PlaceType initPlace) : base(initPos, initRadius, initPlace, GameObjType.Character) { this.CanMove = true; this.score = 0; this.propInventory = null; this.buffManager = new BuffManager(); - switch (characterType) - { - case CharacterType.Assassin: - this.occupation = new Assassin(); - break; - default: - this.occupation = null; - break; - } - this.MaxHp = occupation.MaxHp; - this.hp = occupation.MaxHp; - this.OrgMoveSpeed = occupation.MoveSpeed; - this.moveSpeed = occupation.MoveSpeed; - this.cd = occupation.CD; - this.maxBulletNum = occupation.MaxBulletNum; + + this.MaxHp = Occupation.MaxHp; + this.hp = Occupation.MaxHp; + this.OrgMoveSpeed = Occupation.MoveSpeed; + this.moveSpeed = Occupation.MoveSpeed; + this.cd = Occupation.CD; + this.maxBulletNum = Occupation.MaxBulletNum; this.bulletNum = maxBulletNum; - this.bulletOfPlayer = occupation.InitBullet; - this.OriBulletOfPlayer = occupation.InitBullet; - this.characterType = characterType; + this.bulletOfPlayer = Occupation.InitBullet; + this.OriBulletOfPlayer = Occupation.InitBullet; foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) { diff --git a/logic/GameClass/GameObj/Character/Character.Student.cs b/logic/GameClass/GameObj/Character/Character.Student.cs new file mode 100644 index 0000000..6fc3306 --- /dev/null +++ b/logic/GameClass/GameObj/Character/Character.Student.cs @@ -0,0 +1,119 @@ +using GameClass.Skill; +using Preparation.Utility; + +namespace GameClass.GameObj +{ + public class Student : Character + { + protected int fixSpeed; + /// + /// 修理电机速度 + /// + public int FixSpeed + { + get => fixSpeed; + set + { + lock (gameObjLock) + { + fixSpeed = value; + } + } + } + /// + /// 原初修理电机速度 + /// + public int OrgFixSpeed { get; protected set; } = GameData.basicFixSpeed; + + protected int treatSpeed = GameData.basicTreatSpeed; + public int TreatSpeed + { + get => treatSpeed; + set + { + lock (gameObjLock) + { + treatSpeed = value; + } + } + } + public int OrgTreatSpeed { get; protected set; } = GameData.basicTreatSpeed; + + protected int rescueSpeed = GameData.basicRescueSpeed; + public int RescueSpeed + { + get => rescueSpeed; + set + { + lock (gameObjLock) + { + rescueSpeed = value; + } + } + } + public int OrgRescueSpeed { get; protected set; } = GameData.basicRescueSpeed; + + public int MaxGamingAddiction { get; protected set; } + private int gamingAddiction; + public int GamingAddiction + { + get => gamingAddiction; + set + { + if (gamingAddiction > 0) + lock (gameObjLock) + gamingAddiction = value <= MaxGamingAddiction ? value : MaxGamingAddiction; + else + lock (gameObjLock) + gamingAddiction = 0; + } + } + + private int selfHealingTimes = 1;//剩余的自愈次数 + public int SelfHealingTimes + { + get => selfHealingTimes; + set + { + lock (gameObjLock) + selfHealingTimes = (value > 0) ? value : 0; + } + } + + private int degreeOfTreatment = 0; + public int DegreeOfTreatment + { + get => degreeOfTreatment; + set + { + if (value > 0) + lock (gameObjLock) + degreeOfTreatment = (value < MaxHp - HP) ? value : MaxHp - HP; + else + lock (gameObjLock) + degreeOfTreatment = 0; + } + } + + public void Escape() + { + lock (gameObjLock) + IsResetting = true; + PlayerState = PlayerStateType.IsEscaped; + } + public Student(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType) : base(initPos, initRadius, initPlace) + { + switch (characterType) + { + case CharacterType.Athlete: + this.Occupation = new Athlete(); + break; + default: + this.Occupation = null; + break; + } + this.fixSpeed = ((IStudent)Occupation).FixSpeed; + this.CharacterType = characterType; + } + } +} diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index f5ca394..c43939a 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -31,54 +31,6 @@ namespace GameClass.GameObj } public int OrgCD { get; protected set; } - protected int fixSpeed = GameData.basicFixSpeed; - /// - /// 修理电机速度 - /// - public int FixSpeed - { - get => fixSpeed; - set - { - lock (gameObjLock) - { - fixSpeed = value; - } - } - } - /// - /// 原初修理电机速度 - /// - public int OrgFixSpeed { get; protected set; } = GameData.basicFixSpeed; - - protected int treatSpeed = GameData.basicTreatSpeed; - public int TreatSpeed - { - get => treatSpeed; - set - { - lock (gameObjLock) - { - treatSpeed = value; - } - } - } - public int OrgTreatSpeed { get; protected set; } = GameData.basicTreatSpeed; - - protected int rescueSpeed = GameData.basicRescueSpeed; - public int RescueSpeed - { - get => rescueSpeed; - set - { - lock (gameObjLock) - { - rescueSpeed = value; - } - } - } - public int OrgRescueSpeed { get; protected set; } = GameData.basicRescueSpeed; - protected int maxBulletNum; public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 protected int bulletNum; @@ -102,22 +54,6 @@ namespace GameClass.GameObj } } - public int MaxGamingAddiction { get; protected set; } - private int gamingAddiction; - public int GamingAddiction - { - get => gamingAddiction; - set - { - if (gamingAddiction > 0) - lock (gameObjLock) - gamingAddiction = value <= MaxGamingAddiction ? value : MaxGamingAddiction; - else - lock (gameObjLock) - gamingAddiction = 0; - } - } - private PlayerStateType playerState = PlayerStateType.Null; public PlayerStateType PlayerState { @@ -129,11 +65,11 @@ namespace GameClass.GameObj } set { - if (value != PlayerStateType.IsMoving && value != PlayerStateType.Null) + if (!(value == PlayerStateType.IsMoving || value == PlayerStateType.Null)) lock (gameObjLock) - CanMove = false; + IsMoving = false; - lock (gameObjLock) playerState = value; + lock (gameObjLock) playerState = (value == PlayerStateType.IsMoving) ? PlayerStateType.Null : value; } } @@ -183,32 +119,6 @@ namespace GameClass.GameObj } } - private int selfHealingTimes = 1;//剩余的自愈次数 - public int SelfHealingTimes - { - get => selfHealingTimes; - set - { - lock (gameObjLock) - selfHealingTimes = (value > 0) ? value : 0; - } - } - - private int degreeOfTreatment = 0; - public int DegreeOfTreatment - { - get => degreeOfTreatment; - set - { - if (value > 0) - lock (gameObjLock) - degreeOfTreatment = (value < MaxHp - HP) ? value : MaxHp - HP; - else - lock (gameObjLock) - degreeOfTreatment = 0; - } - } - public readonly BulletType OriBulletOfPlayer; private BulletType bulletOfPlayer; public BulletType BulletOfPlayer @@ -561,24 +471,11 @@ namespace GameClass.GameObj } } - public void Escape() - { - lock (gameObjLock) - IsResetting = true; - PlayerState = PlayerStateType.IsEscaped; - } public override bool IsRigid => true; public override ShapeType Shape => ShapeType.Circle; protected override bool IgnoreCollideExecutor(IGameObj targetObj) { - if (targetObj.Type == GameObjType.BirthPoint) - { - if (object.ReferenceEquals(((BirthPoint)targetObj).Parent, this)) // 自己的出生点可以忽略碰撞 - { - return true; - } - } - else if (targetObj.Type == GameObjType.Prop) // 自己队的地雷忽略碰撞 + if (targetObj.Type == GameObjType.Prop) // 自己队的地雷忽略碰撞 { return true; } diff --git a/logic/GameClass/GameObj/Map/BirthPoint.cs b/logic/GameClass/GameObj/Map/BirthPoint.cs deleted file mode 100644 index b0ddd8d..0000000 --- a/logic/GameClass/GameObj/Map/BirthPoint.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Preparation.Interface; -using Preparation.Utility; - -namespace GameClass.GameObj -{ - /// - /// 出生点 - /// - public class BirthPoint : ObjOfCharacter - { - public BirthPoint(XY initPos) : - base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.BirthPoint) - { - this.CanMove = false; - } - // 修改建议:需要避免非自己的玩家进入出生点,否则会重叠 - public override bool IsRigid => true; - protected override bool IgnoreCollideExecutor(IGameObj targetObj) - { - if (targetObj.Type != GameObjType.Character) - return true; // 非玩家不碰撞 - else if (targetObj.Type == GameObjType.Character && targetObj.ID == this.Parent.ID) - return true; // 出生点所属的玩家不碰撞 - return false; - } - public override ShapeType Shape => ShapeType.Square; - } -} \ No newline at end of file diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs index 2a6c2f1..81e985b 100644 --- a/logic/GameClass/GameObj/Map/Doorway.cs +++ b/logic/GameClass/GameObj/Map/Doorway.cs @@ -9,7 +9,7 @@ namespace GameClass.GameObj public class Doorway : GameObj { public Doorway(XY initPos) : - base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.Doorway) + base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Null, GameObjType.Doorway) { this.CanMove = false; } diff --git a/logic/GameClass/GameObj/Map/EmergencyExit.cs b/logic/GameClass/GameObj/Map/EmergencyExit.cs index bc20980..a392f1a 100644 --- a/logic/GameClass/GameObj/Map/EmergencyExit.cs +++ b/logic/GameClass/GameObj/Map/EmergencyExit.cs @@ -9,7 +9,7 @@ namespace GameClass.GameObj public class EmergencyExit : GameObj { public EmergencyExit(XY initPos) : - base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.EmergencyExit) + base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Null, GameObjType.EmergencyExit) { this.CanMove = false; } diff --git a/logic/GameClass/GameObj/Map/Generator.cs b/logic/GameClass/GameObj/Map/Generator.cs index c8eaa69..a1dfdfb 100644 --- a/logic/GameClass/GameObj/Map/Generator.cs +++ b/logic/GameClass/GameObj/Map/Generator.cs @@ -8,7 +8,7 @@ namespace GameClass.GameObj public class Generator : GameObj { public Generator(XY initPos) : - base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.Generator) + base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Null, GameObjType.Generator) { this.CanMove = false; } diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index 03fbb05..fd3d8ad 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -9,8 +9,8 @@ namespace GameClass.GameObj public partial class Map : IMap { - private readonly Dictionary birthPointList; // 出生点列表 - public Dictionary BirthPointList => birthPointList; + private readonly Dictionary birthPointList; // 出生点列表 + public Dictionary BirthPointList => birthPointList; private Dictionary> gameObjDict; public Dictionary> GameObjDict => gameObjDict; @@ -22,19 +22,11 @@ namespace GameClass.GameObj { try { - uint type = ProtoGameMap[obj.Position.x / GameData.numOfPosGridPerCell, obj.Position.y / GameData.numOfPosGridPerCell]; - if (type == 2) - return PlaceType.Grass1; - else if (type == 3) - return PlaceType.Grass2; - else if (type == 4) - return PlaceType.Grass3; - else - return PlaceType.Land; // 其他情况均返回land + return (PlaceType)ProtoGameMap[obj.Position.x / GameData.numOfPosGridPerCell, obj.Position.y / GameData.numOfPosGridPerCell]; } catch { - return PlaceType.Land; + return PlaceType.Null; } } @@ -42,21 +34,11 @@ namespace GameClass.GameObj { try { - switch (ProtoGameMap[pos.x / GameData.numOfPosGridPerCell, pos.y / GameData.numOfPosGridPerCell]) - { - case 2: - return PlaceType.Grass1; - case 3: - return PlaceType.Grass2; - case 4: - return PlaceType.Grass3; - default: - return PlaceType.Land; - } + return (PlaceType)ProtoGameMap[pos.x / GameData.numOfPosGridPerCell, pos.y / GameData.numOfPosGridPerCell]; } catch { - return PlaceType.Land; + return PlaceType.Null; } } @@ -106,7 +88,7 @@ namespace GameClass.GameObj ProtoGameMap = new uint[mapResource.GetLength(0), mapResource.GetLength(1)]; Array.Copy(mapResource, ProtoGameMap, mapResource.Length); - birthPointList = new Dictionary(GameData.numOfBirthPoint); + birthPointList = new Dictionary(GameData.numOfBirthPoint); for (int i = 0; i < GameData.rows; ++i) { @@ -114,7 +96,7 @@ namespace GameClass.GameObj { switch (mapResource[i, j]) { - case (uint)MapInfoObjType.Wall: + case (uint)PlaceType.Wall: { GameObjLockDict[GameObjType.Wall].EnterWriteLock(); try @@ -127,7 +109,7 @@ namespace GameClass.GameObj } break; } - case (uint)MapInfoObjType.Doorway: + case (uint)PlaceType.Doorway: { GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); try @@ -141,7 +123,7 @@ namespace GameClass.GameObj break; } - case (uint)MapInfoObjType.EmergencyExit: + case (uint)PlaceType.EmergencyExit: { GameObjLockDict[GameObjType.EmergencyExit].EnterWriteLock(); try @@ -154,7 +136,7 @@ namespace GameClass.GameObj } break; } - case (uint)MapInfoObjType.Generator: + case (uint)PlaceType.Generator: { GameObjLockDict[GameObjType.Generator].EnterWriteLock(); try @@ -167,23 +149,13 @@ namespace GameClass.GameObj } break; } - case (uint)MapInfoObjType.BirthPoint1: - case (uint)MapInfoObjType.BirthPoint2: - case (uint)MapInfoObjType.BirthPoint3: - case (uint)MapInfoObjType.BirthPoint4: - case (uint)MapInfoObjType.BirthPoint5: + case (uint)PlaceType.BirthPoint1: + case (uint)PlaceType.BirthPoint2: + case (uint)PlaceType.BirthPoint3: + case (uint)PlaceType.BirthPoint4: + case (uint)PlaceType.BirthPoint5: { - BirthPoint newBirthPoint = new BirthPoint(GameData.GetCellCenterPos(i, j)); - birthPointList.Add(mapResource[i, j], newBirthPoint); - GameObjLockDict[GameObjType.BirthPoint].EnterWriteLock(); - try - { - GameObjDict[GameObjType.BirthPoint].Add(newBirthPoint); - } - finally - { - GameObjLockDict[GameObjType.BirthPoint].ExitWriteLock(); - } + birthPointList.Add(mapResource[i, j], GameData.GetCellCenterPos(i, j)); break; } } diff --git a/logic/GameClass/GameObj/Map/MapInfo.cs b/logic/GameClass/GameObj/Map/MapInfo.cs index 5c4c19c..5efceec 100644 --- a/logic/GameClass/GameObj/Map/MapInfo.cs +++ b/logic/GameClass/GameObj/Map/MapInfo.cs @@ -12,56 +12,56 @@ namespace GameClass.GameObj /// 50*50 /// public static uint[,] defaultMap = new uint[,] { - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 1, 1, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 13, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 9, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 7, 5, 7, 7, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 6, 6, 6, 0, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 6 }, + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 }, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 } }; } } diff --git a/logic/GameClass/GameObj/Map/Wall.cs b/logic/GameClass/GameObj/Map/Wall.cs index 7066fed..f738d25 100644 --- a/logic/GameClass/GameObj/Map/Wall.cs +++ b/logic/GameClass/GameObj/Map/Wall.cs @@ -8,7 +8,7 @@ namespace GameClass.GameObj public class Wall : GameObj { public Wall(XY initPos) : - base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.Wall) + base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Null, GameObjType.Wall) { this.CanMove = false; } diff --git a/logic/GameClass/GameObj/OutOfBoundBlock.cs b/logic/GameClass/GameObj/OutOfBoundBlock.cs index 9ac2a84..810d913 100644 --- a/logic/GameClass/GameObj/OutOfBoundBlock.cs +++ b/logic/GameClass/GameObj/OutOfBoundBlock.cs @@ -9,7 +9,7 @@ namespace GameClass.GameObj public class OutOfBoundBlock : GameObj, IOutOfBound { public OutOfBoundBlock(XY initPos) : - base(initPos, int.MaxValue, PlaceType.Land, GameObjType.OutOfBoundBlock) + base(initPos, int.MaxValue, PlaceType.Null, GameObjType.OutOfBoundBlock) { this.CanMove = false; } diff --git a/logic/GameClass/GameObj/Prop.cs b/logic/GameClass/GameObj/Prop.cs index 8e6dfbc..c4067e6 100644 --- a/logic/GameClass/GameObj/Prop.cs +++ b/logic/GameClass/GameObj/Prop.cs @@ -12,7 +12,7 @@ namespace GameClass.GameObj protected override bool IgnoreCollideExecutor(IGameObj targetObj) { - if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character) + if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character) return true; return false; } @@ -22,7 +22,7 @@ namespace GameClass.GameObj public abstract PropType GetPropType(); public Prop(XY initPos, int radius = GameData.PropRadius) : - base(initPos, radius, PlaceType.Land, GameObjType.Prop) + base(initPos, radius, PlaceType.Null, GameObjType.Prop) { this.CanMove = false; this.moveSpeed = GameData.PropMoveSpeed; diff --git a/logic/GameClass/Skill/ActiveSkill.cs b/logic/GameClass/Skill/ActiveSkill.cs index 6d7d18f..97ef015 100644 --- a/logic/GameClass/Skill/ActiveSkill.cs +++ b/logic/GameClass/Skill/ActiveSkill.cs @@ -29,6 +29,29 @@ namespace GameClass.Skill }); } } + + public class BeginToCharge : IActiveSkill + { + public int SkillCD => GameData.commonSkillCD / 3 * 4; + public int DurationTime => GameData.commonSkillTime; + + private readonly object commonSkillLock = new object(); + public object ActiveSkillLock => commonSkillLock; + + public bool SkillEffect(Character player) + { + return ActiveSkillFactory.SkillEffect(this, player, () => + { + player.Vampire += 0.5; + Debugger.Output(player, "becomes vampire!"); + }, + () => + { + double tempVam = player.Vampire - 0.5; + player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; + }); + } + } public class BecomeInvisible : IActiveSkill { public int SkillCD => GameData.commonSkillCD; diff --git a/logic/GameClass/Skill/Occupation.cs b/logic/GameClass/Skill/Occupation.cs index c2186af..18d7abf 100644 --- a/logic/GameClass/Skill/Occupation.cs +++ b/logic/GameClass/Skill/Occupation.cs @@ -14,7 +14,17 @@ namespace GameClass.Skill public List ListOfIActiveSkill { get; } public List ListOfIPassiveSkill { get; } } - public class Assassin : IOccupation + + public interface IGhost : IOccupation + { + } + + public interface IStudent : IOccupation + { + public int FixSpeed { get; } + } + + public class Assassin : IGhost { private const int moveSpeed = GameData.basicMoveSpeed / 380 * 473; public int MoveSpeed => moveSpeed; @@ -33,5 +43,23 @@ namespace GameClass.Skill public List ListOfIActiveSkill => new(new IActiveSkill[] { new BecomeInvisible(), new UseKnife() }); public List ListOfIPassiveSkill => new(new IPassiveSkill[] { }); } + public class Athlete : IOccupation + { + private const int moveSpeed = GameData.basicMoveSpeed; + public int MoveSpeed => moveSpeed; + + private const int maxHp = GameData.basicHp; + public int MaxHp => maxHp; + public const int cd = 0; + public int CD => cd; + + public const int maxBulletNum = 1; + public int MaxBulletNum => maxBulletNum; + + public BulletType InitBullet => BulletType.CommonAttackOfGhost; + + public List ListOfIActiveSkill => new(new IActiveSkill[] { new BecomeInvisible(), new UseKnife() }); + public List ListOfIPassiveSkill => new(new IPassiveSkill[] { }); + } } diff --git a/logic/GameClass/Skill/PassiveSkill.cs b/logic/GameClass/Skill/PassiveSkill.cs index baf00ac..9c72517 100644 --- a/logic/GameClass/Skill/PassiveSkill.cs +++ b/logic/GameClass/Skill/PassiveSkill.cs @@ -89,7 +89,7 @@ namespace GameClass.Skill // 被动技能开局时就释放,持续到游戏 { lastPlace = nowPlace; nowPlace = player.Place; - if ((lastPlace == PlaceType.Grass1 || lastPlace == PlaceType.Grass2 || lastPlace == PlaceType.Grass3) && nowPlace == PlaceType.Land) + if ((lastPlace == PlaceType.Grass) && nowPlace == PlaceType.Null) { if (!speedup) { diff --git a/logic/GameEngine/MoveEngine.cs b/logic/GameEngine/MoveEngine.cs index 4bd1dad..6df1548 100644 --- a/logic/GameEngine/MoveEngine.cs +++ b/logic/GameEngine/MoveEngine.cs @@ -63,7 +63,7 @@ namespace GameEngine ( () => { - if (!obj.IsAvailable && gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况 + if (!obj.IsAvailable && gameTimer.IsGaming) return; lock (obj.MoveLock) obj.IsMoving = true; @@ -73,7 +73,7 @@ namespace GameEngine IGameObj? collisionObj = null; bool isDestroyed = false; new FrameRateTaskExecutor( - () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, + () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting && obj.IsMoving, () => { moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; @@ -141,7 +141,7 @@ namespace GameEngine } } } while (flag); - if (leftTime > 0) + if (leftTime > 0 && obj.IsMoving) { Thread.Sleep(leftTime); // 多移动的在这里补回来 } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 5fe3625..99f81b7 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -15,12 +15,14 @@ namespace Gaming { // 人物移动 - public void MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) + public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { + if (playerToMove.PlayerState != PlayerStateType.Null) return false; moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); + return true; } - public bool Fix(Character player)// 自动检查有无发电机可修 + public bool Fix(Student player)// 自动检查有无发电机可修 { if (player.PlayerState != PlayerStateType.Null || player.IsGhost()) return false; @@ -53,7 +55,7 @@ namespace Gaming () => { new FrameRateTaskExecutor( - loopCondition: () => player.PlayerState == PlayerStateType.IsFixing && generatorForFix.DegreeOfFRepair < GameData.degreeOfFixedGenerator && GameData.ApproachToInteract(player.Position, generatorForFix.Position), + loopCondition: () => player.PlayerState == PlayerStateType.IsFixing && gameMap.Timer.IsGaming && generatorForFix.DegreeOfFRepair < GameData.degreeOfFixedGenerator && GameData.ApproachToInteract(player.Position, generatorForFix.Position), loopToDo: () => { return !generatorForFix.Repair(player.FixSpeed * GameData.frameDuration); @@ -63,48 +65,48 @@ namespace Gaming ) .Start(); + if (generatorForFix.DegreeOfFRepair == GameData.degreeOfFixedGenerator) + { + gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); + try + { + Doorway exit = (Doorway)gameMap.GameObjDict[GameObjType.Doorway][1]; + if (!exit.PowerSupply) + { + int numOfFixedGenerator = 0; + foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) + if (generator.DegreeOfFRepair == GameData.degreeOfFixedGenerator) + ++numOfFixedGenerator; + if (numOfFixedGenerator >= GameData.numOfGeneratorRequiredForRepair) + { + gameMap.GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); + try + { + foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) + doorway.PowerSupply = true; + } + finally + { + gameMap.GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); + } + } + } + } + + finally + { + gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); + } + } } + ) { IsBackground = true }.Start(); - if (generatorForFix.DegreeOfFRepair == GameData.degreeOfFixedGenerator) - { - gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); - try - { - Doorway exit = (Doorway)gameMap.GameObjDict[GameObjType.Doorway][1]; - if (!exit.PowerSupply) - { - int numOfFixedGenerator = 0; - foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) - if (generator.DegreeOfFRepair == GameData.degreeOfFixedGenerator) - ++numOfFixedGenerator; - if (numOfFixedGenerator >= GameData.numOfGeneratorRequiredForRepair) - { - gameMap.GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); - try - { - foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) - doorway.PowerSupply = true; - } - finally - { - gameMap.GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); - } - } - } - } - - finally - { - gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); - } - return true; - } - return false; + return true; } - public bool Escape(Character player) + public bool Escape(Student player) { if (!(player.PlayerState == PlayerStateType.Null || player.PlayerState == PlayerStateType.IsMoving) || player.IsGhost()) return false; @@ -137,7 +139,7 @@ namespace Gaming return false; } - public bool Treat(Character player, Character playerTreated) + public bool Treat(Student player, Student playerTreated) { if (playerTreated.PlayerState == PlayerStateType.Null || player.PlayerState == PlayerStateType.Null || playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position)) return false; @@ -146,21 +148,21 @@ namespace Gaming { playerTreated.HP = playerTreated.MaxHp; playerTreated.DegreeOfTreatment = 0; - return true; + return false; } if (playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree) { playerTreated.HP += GameData.basicTreatmentDegree; playerTreated.DegreeOfTreatment = 0; - return true; + return false; } new Thread ( () => { new FrameRateTaskExecutor( - loopCondition: () => playerTreated.PlayerState == PlayerStateType.IsTreated && player.PlayerState == PlayerStateType.IsTreating && playerTreated.HP + playerTreated.DegreeOfTreatment < playerTreated.MaxHp && playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree && GameData.ApproachToInteract(playerTreated.Position, player.Position), + loopCondition: () => playerTreated.PlayerState == PlayerStateType.IsTreated && player.PlayerState == PlayerStateType.IsTreating && gameMap.Timer.IsGaming && playerTreated.HP + playerTreated.DegreeOfTreatment < playerTreated.MaxHp && playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree && GameData.ApproachToInteract(playerTreated.Position, player.Position), loopToDo: () => { playerTreated.DegreeOfTreatment += GameData.frameDuration * player.TreatSpeed; @@ -170,30 +172,28 @@ namespace Gaming ) .Start(); + + if (playerTreated.PlayerState == PlayerStateType.IsTreated) playerTreated.PlayerState = PlayerStateType.Null; + if (player.PlayerState == PlayerStateType.IsTreating) player.PlayerState = PlayerStateType.Null; + + if (playerTreated.HP + playerTreated.DegreeOfTreatment >= playerTreated.MaxHp) + { + playerTreated.HP = playerTreated.MaxHp; + playerTreated.DegreeOfTreatment = 0; + } + else + if (playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree) + { + playerTreated.HP += GameData.basicTreatmentDegree; + playerTreated.DegreeOfTreatment = 0; + } } ) { IsBackground = true }.Start(); - - if (playerTreated.PlayerState == PlayerStateType.IsTreated) playerTreated.PlayerState = PlayerStateType.Null; - if (player.PlayerState == PlayerStateType.IsTreating) player.PlayerState = PlayerStateType.Null; - - if (playerTreated.HP + playerTreated.DegreeOfTreatment >= playerTreated.MaxHp) - { - playerTreated.HP = playerTreated.MaxHp; - playerTreated.DegreeOfTreatment = 0; - return true; - } - - if (playerTreated.DegreeOfTreatment >= GameData.basicTreatmentDegree) - { - playerTreated.HP += GameData.basicTreatmentDegree; - playerTreated.DegreeOfTreatment = 0; - return true; - } - return false; + return true; } - public bool Rescue(Character player, Character playerRescued) + public bool Rescue(Student player, Student playerRescued) { if (player.PlayerState != PlayerStateType.Null || playerRescued.PlayerState != PlayerStateType.IsAddicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position)) return false; @@ -205,7 +205,7 @@ namespace Gaming () => { new FrameRateTaskExecutor( - loopCondition: () => playerRescued.PlayerState == PlayerStateType.IsRescued && player.PlayerState == PlayerStateType.IsRescuing && GameData.ApproachToInteract(playerRescued.Position, player.Position), + loopCondition: () => playerRescued.PlayerState == PlayerStateType.IsRescued && player.PlayerState == PlayerStateType.IsRescuing && gameMap.Timer.IsGaming && GameData.ApproachToInteract(playerRescued.Position, player.Position), loopToDo: () => { rescuedDegree += GameData.frameDuration; @@ -216,21 +216,22 @@ namespace Gaming ) .Start(); + + if (rescuedDegree == 1000) + { + if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; + if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.Null; + } + else + { + if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; + if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.IsAddicted; + } } ) { IsBackground = true }.Start(); - if (rescuedDegree == 1000) - { - if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; - if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.Null; - return true; - } - else - { - if (playerRescued.PlayerState == PlayerStateType.IsRescued) playerRescued.PlayerState = PlayerStateType.Null; - if (player.PlayerState == PlayerStateType.IsRescuing) player.PlayerState = PlayerStateType.IsAddicted; - return false; - } + + return true; } /* diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 0eaca15..9ae8cce 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -6,6 +6,7 @@ using Preparation.Utility; using GameEngine; using Preparation.Interface; using Timothy.FrameRateTask; +using System.Numerics; namespace Gaming { @@ -37,7 +38,7 @@ namespace Gaming ); } - public void BeAddictedToGame(Character player) + public void BeAddictedToGame(Student player) { new Thread (() => @@ -46,7 +47,7 @@ namespace Gaming player.GamingAddiction = GameData.MidGamingAddiction; player.PlayerState = PlayerStateType.IsAddicted; new FrameRateTaskExecutor( - () => player.PlayerState == PlayerStateType.IsAddicted && player.GamingAddiction < player.MaxGamingAddiction, + () => player.PlayerState == PlayerStateType.IsAddicted && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, () => { player.GamingAddiction += GameData.frameDuration; @@ -54,12 +55,10 @@ namespace Gaming timeInterval: GameData.frameDuration, () => { - if (player.GamingAddiction == player.MaxGamingAddiction) + if (player.GamingAddiction == player.MaxGamingAddiction && gameMap.Timer.IsGaming) { - player.PlayerState = PlayerStateType.Null; Die(player); } - else player.CanMove = true; return 0; } ) @@ -140,11 +139,11 @@ namespace Gaming switch (objBeingShot.Type) { case GameObjType.Character: - Character playerBeingShot = (Character)objBeingShot; - if (playerBeingShot.BeAttacked(bullet)) - { - BeAddictedToGame(playerBeingShot); - } + if (!((Character)objBeingShot).IsGhost()) + if (((Character)objBeingShot).BeAttacked(bullet)) + { + BeAddictedToGame((Student)objBeingShot); + } break; } } @@ -187,17 +186,16 @@ namespace Gaming { if (bullet.Backswing > 0) { - bullet.Parent.CanMove = false; - bullet.Parent.IsMoving = false; + bullet.Parent.PlayerState = PlayerStateType.IsSwinging; new Thread (() => { Thread.Sleep(bullet.Backswing); - if (gameMap.Timer.IsGaming) + if (gameMap.Timer.IsGaming && bullet.Parent.PlayerState == PlayerStateType.IsSwinging) { - bullet.Parent.CanMove = true; + bullet.Parent.PlayerState = PlayerStateType.Null; } } ) @@ -210,8 +208,7 @@ namespace Gaming BombObj(bullet, objBeingShot); if (bullet.RecoveryFromHit > 0) { - bullet.Parent.CanMove = false; - bullet.Parent.IsMoving = false; + bullet.Parent.PlayerState = PlayerStateType.IsSwinging; new Thread (() => @@ -219,9 +216,9 @@ namespace Gaming Thread.Sleep(bullet.RecoveryFromHit); - if (gameMap.Timer.IsGaming) + if (gameMap.Timer.IsGaming && bullet.Parent.PlayerState == PlayerStateType.IsSwinging) { - bullet.Parent.CanMove = true; + bullet.Parent.PlayerState = PlayerStateType.Null; } } ) @@ -270,17 +267,16 @@ namespace Gaming { if (bullet.Backswing > 0) { - bullet.Parent.CanMove = false; - bullet.Parent.IsMoving = false; + bullet.Parent.PlayerState = PlayerStateType.IsSwinging; new Thread (() => { Thread.Sleep(bullet.Backswing); - if (gameMap.Timer.IsGaming) + if (gameMap.Timer.IsGaming && bullet.Parent.PlayerState == PlayerStateType.IsSwinging) { - bullet.Parent.CanMove = true; + bullet.Parent.PlayerState = PlayerStateType.Null; } } ) @@ -291,8 +287,7 @@ namespace Gaming { if (bullet.RecoveryFromHit > 0) { - bullet.Parent.CanMove = false; - bullet.Parent.IsMoving = false; + bullet.Parent.PlayerState = PlayerStateType.IsSwinging; new Thread (() => @@ -300,9 +295,9 @@ namespace Gaming Thread.Sleep(bullet.RecoveryFromHit); - if (gameMap.Timer.IsGaming) + if (gameMap.Timer.IsGaming && bullet.Parent.PlayerState == PlayerStateType.IsSwinging) { - bullet.Parent.CanMove = true; + bullet.Parent.PlayerState = PlayerStateType.Null; } } ) @@ -322,8 +317,9 @@ namespace Gaming return false; } - if (player.IsResetting) + if (player.PlayerState != PlayerStateType.Null || player.PlayerState != PlayerStateType.IsMoving) return false; + Bullet? bullet = player.RemoteAttack( new XY // 子弹紧贴人物生成。 ( @@ -331,6 +327,24 @@ namespace Gaming (int)((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle)) ) ); + if (bullet.CastTime > 0) + { + player.PlayerState = PlayerStateType.IsTryingToAttack; + + new Thread + (() => + { + + Thread.Sleep(bullet.CastTime); + + if (gameMap.Timer.IsGaming && player.PlayerState == PlayerStateType.IsTryingToAttack) + { + player.PlayerState = PlayerStateType.Null; + } + } + ) + { IsBackground = true }.Start(); + } if (bullet != null) { bullet.CanMove = true; diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 24de635..cf905e7 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -16,13 +16,11 @@ namespace Gaming public long teamID; public long playerID; public CharacterType characterType; - public ActiveSkillType commonSkill; - public PlayerInitInfo(uint birthPointIndex, long teamID, long playerID, CharacterType characterType, ActiveSkillType commonSkill) + public PlayerInitInfo(uint birthPointIndex, long teamID, long playerID, CharacterType characterType) { this.birthPointIndex = birthPointIndex; this.teamID = teamID; this.characterType = characterType; - this.commonSkill = commonSkill; this.playerID = playerID; } } @@ -39,10 +37,9 @@ namespace Gaming || gameMap.BirthPointList[playerInitInfo.birthPointIdx].Parent != null)*/ return GameObj.invalidID; - XY pos = gameMap.BirthPointList[playerInitInfo.birthPointIndex].Position; + XY pos = gameMap.BirthPointList[playerInitInfo.birthPointIndex]; // Console.WriteLine($"x,y: {pos.x},{pos.y}"); - Character newPlayer = new(pos, GameData.characterRadius, gameMap.GetPlaceType(pos), playerInitInfo.characterType, playerInitInfo.commonSkill); - gameMap.BirthPointList[playerInitInfo.birthPointIndex].Parent = newPlayer; + Character newPlayer = (GameData.IsGhost(playerInitInfo.characterType)) ? new Ghost(pos, GameData.characterRadius, gameMap.GetPlaceType(pos), playerInitInfo.characterType) : new Student(pos, GameData.characterRadius, gameMap.GetPlaceType(pos), playerInitInfo.characterType); gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); try { @@ -175,20 +172,21 @@ namespace Gaming }*/ gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } - public void MovePlayer(long playerID, int moveTimeInMilliseconds, double angle) + public bool MovePlayer(long playerID, int moveTimeInMilliseconds, double angle) { if (!gameMap.Timer.IsGaming) - return; + return false; Character? player = gameMap.FindPlayer(playerID); if (player != null) { - actionManager.MovePlayer(player, moveTimeInMilliseconds, angle); + return actionManager.MovePlayer(player, moveTimeInMilliseconds, angle); #if DEBUG Console.WriteLine($"PlayerID:{playerID} move to ({player.Position.x},{player.Position.y})!"); #endif } else { + return false; #if DEBUG Console.WriteLine($"PlayerID:{playerID} player does not exists!"); #endif @@ -198,11 +196,12 @@ namespace Gaming { if (!gameMap.Timer.IsGaming) return false; - Character? player = gameMap.FindPlayer(playerID); - Character? playerTreated = gameMap.FindPlayer(playerTreatedID); + ICharacter? player = gameMap.FindPlayer(playerID); + ICharacter? playerTreated = gameMap.FindPlayer(playerTreatedID); if (player != null && playerTreated != null) { - return actionManager.Treat(player, playerTreated); + if (!playerTreated.IsGhost() && !player.IsGhost()) + return actionManager.Treat((Student)player, (Student)playerTreated); } return false; } @@ -210,11 +209,12 @@ namespace Gaming { if (!gameMap.Timer.IsGaming) return false; - Character? player = gameMap.FindPlayer(playerID); - Character? playerRescued = gameMap.FindPlayer(playerRescuedID); + ICharacter? player = gameMap.FindPlayer(playerID); + ICharacter? playerRescued = gameMap.FindPlayer(playerRescuedID); if (player != null && playerRescued != null) { - return actionManager.Treat(player, playerRescued); + if (!playerRescued.IsGhost() && !player.IsGhost()) + return actionManager.Treat((Student)player, (Student)playerRescued); } return false; } @@ -222,10 +222,11 @@ namespace Gaming { if (!gameMap.Timer.IsGaming) return false; - Character? player = gameMap.FindPlayer(playerID); + ICharacter? player = gameMap.FindPlayer(playerID); if (player != null) { - return actionManager.Fix(player); + if (!player.IsGhost()) + return actionManager.Fix((Student)player); } return false; } @@ -233,10 +234,11 @@ namespace Gaming { if (!gameMap.Timer.IsGaming) return false; - Character? player = gameMap.FindPlayer(playerID); + ICharacter? player = gameMap.FindPlayer(playerID); if (player != null) { - return actionManager.Escape(player); + if (!player.IsGhost()) + return actionManager.Escape((Student)player); } return false; } @@ -335,7 +337,7 @@ namespace Gaming { foreach (var keyValuePair in gameMap.GameObjDict) { - if (((uint)keyValuePair.Key) <= GameData.numOfObjNotMap) + if (!GameData.IsMap(keyValuePair.Key)) { gameMap.GameObjLockDict[keyValuePair.Key].EnterWriteLock(); try @@ -366,7 +368,7 @@ namespace Gaming var gameObjList = new List(); foreach (var keyValuePair in gameMap.GameObjDict) { - if (((uint)keyValuePair.Key) <= GameData.numOfObjNotMap) + if (!GameData.IsMap(keyValuePair.Key)) { gameMap.GameObjLockDict[keyValuePair.Key].EnterReadLock(); try diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs index b403cca..f70fe2c 100644 --- a/logic/Gaming/PropManager.cs +++ b/logic/Gaming/PropManager.cs @@ -234,7 +234,7 @@ namespace Gaming { for (int j = 0; j < gameMap.ProtoGameMap.GetLength(1); j++) { - if (gameMap.ProtoGameMap[i, j] == (int)MapInfoObjType.Null) + if (gameMap.ProtoGameMap[i, j] == (int)PlaceType.Null) { availableCellForGenerateProp.Add(GameData.GetCellCenterPos(i, j)); } diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs index a0087f4..ea40d91 100644 --- a/logic/Preparation/Interface/ICharacter.cs +++ b/logic/Preparation/Interface/ICharacter.cs @@ -8,5 +8,7 @@ namespace Preparation.Interface public long TeamID { get; } public int HP { get; set; } public double Vampire { get; } + public PlayerStateType PlayerState { get; set; } + public bool IsGhost(); } } \ No newline at end of file diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index ba70715..19d3a04 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -4,13 +4,12 @@ namespace Preparation.Utility /// /// 存放所有用到的枚举类型 /// - // public const int numOfObjNotMap = 5;在GameData中 public enum PlayerStateType { Null = 0, IsAddicted = 1, IsEscaped = 2, - IsSwinging = 3, + IsSwinging = 3,//指后摇 IsResetting = 4, IsMoving = 5, IsTreating = 6, @@ -18,6 +17,8 @@ namespace Preparation.Utility IsFixing = 8, IsTreated = 9, IsRescued = 10, + IsStunned = 11, + IsTryingToAttack = 12,//指前摇 } public enum GameObjType { @@ -31,10 +32,9 @@ namespace Preparation.Utility Wall = 6, Grass = 7, Generator = 8, // 发电机 - BirthPoint = 9, - Doorway = 10, - EmergencyExit = 11, - OutOfBoundBlock = 12, // 范围外 + Doorway = 9, + EmergencyExit = 10, + OutOfBoundBlock = 11, // 范围外 } public enum ShapeType { @@ -42,14 +42,6 @@ namespace Preparation.Utility Circle = 1, // 子弹和人物为圆形,格子为方形 Square = 2 } - public enum PlaceType // 位置标志,包括陆地,草丛。游戏中每一帧都要刷新各个物体的该属性 - { - Null = 0, - Land = 1, - Grass1 = 2, - Grass2 = 3, - Grass3 = 4, - } public enum BulletType // 子弹类型 { Null = 0, @@ -73,7 +65,7 @@ namespace Preparation.Utility { Null = 0, Assassin = 1, - Vampire = 2, + Athlete = 2, RecoverAfterBattle = 3, SpeedUpWhenLeavingGrass = 4, PSkill4 = 5, @@ -108,7 +100,7 @@ namespace Preparation.Utility Spear = 4 } - public enum MapInfoObjType + public enum PlaceType { Null = 0, BirthPoint1 = 1,//必须从1开始 @@ -117,11 +109,9 @@ namespace Preparation.Utility BirthPoint4 = 4, BirthPoint5 = 5, Wall = 6, - Grass1 = 7, - Grass2 = 8, - Grass3 = 9, - Generator = 10, // 发电机 - Doorway = 11, - EmergencyExit = 12 + Grass = 7, + Generator = 8, // 发电机 + Doorway = 9, + EmergencyExit = 10 } } \ No newline at end of file diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 6e897a9..8429019 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -1,11 +1,13 @@ using System; +using System.Reflection.Metadata.Ecma335; + namespace Preparation.Utility { public static class GameData { #region 基本常数与常方法 public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 - public const int numOfStepPerSecond = 20; // 每秒行走的步数 + public const int numOfStepPerSecond = 100; // 每秒行走的步数 public const int frameDuration = 50; // 每帧时长 public const int lengthOfMap = 50000; // 地图长度 @@ -20,8 +22,11 @@ namespace Preparation.Utility // public const int numOfGenerator = 7; public const int numOfGeneratorRequiredForRepair = 5; - public const int numOfObjNotMap = 5; - + private const int numOfObjNotMap = 5; + public static bool IsMap(GameObjType gameObjType) + { + return (uint)gameObjType > numOfObjNotMap; + } public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 { XY ret = new(x * numOfPosGridPerCell + numOfPosGridPerCell / 2, y * numOfPosGridPerCell + numOfPosGridPerCell / 2); @@ -43,6 +48,7 @@ namespace Preparation.Utility { return Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2)) <= 1 && Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2)) <= 1; } + #endregion #region 角色相关 public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 @@ -57,6 +63,7 @@ namespace Preparation.Utility public const int basicRescueDegree = 100000; public const int basicHp = 3000000; // 初始血量 public const int basicCD = 3000; // 初始子弹冷却 + public const int basicCastTime = 500;//基本前摇时间 public const int basicBackswing = 500;//基本后摇时间 public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 public const int basicBulletNum = 3; // 基本初始子弹量 @@ -74,7 +81,15 @@ namespace Preparation.Utility public const int bulletRadius = 200; // 默认子弹半径 public const int reviveTime = 30000; // 复活时间 public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间 - public const int gemToScore = 4; // 一个宝石的标准加分 + + public static bool IsGhost(CharacterType characterType) + { + return characterType switch + { + CharacterType.Assassin => true, + _ => false, + }; + } #endregion #region 道具相关 public const int MinPropTypeNum = 1; @@ -82,7 +97,6 @@ namespace Preparation.Utility public const int PropRadius = numOfPosGridPerCell / 2; public const int PropMoveSpeed = 3000; public const int PropMaxMoveDistance = 15 * numOfPosGridPerCell; - public const int MaxGemSize = 5; // 随机生成的宝石最大size public const long GemProduceTime = 10000; public const long PropProduceTime = 10000; public const int PropDuration = 10000; diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index 1455b69..70f42d6 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -77,23 +77,23 @@ namespace Server } switch (player.Place) { - case Preparation.Utility.PlaceType.Land: - msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.Land; + case Preparation.Utility.PlacccceType.Land: + msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.Land; break; - case Preparation.Utility.PlaceType.Grass1: - msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.Grass1; + case Preparation.Utility.PlacccceType.Grass1: + msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.Grass1; break; - case Preparation.Utility.PlaceType.Grass2: - msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.Grass2; + case Preparation.Utility.PlacccceType.Grass2: + msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.Grass2; break; - case Preparation.Utility.PlaceType.Grass3: - msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.Grass3; + case Preparation.Utility.PlacccceType.Grass3: + msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.Grass3; break; - // case Preparation.Utility.PlaceType.Invisible: - // msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.Invisible; + // case Preparation.Utility.PlacccceType.Invisible: + // msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.Invisible; // break; default: - msg.MessageOfCharacter.Place = Communication.Proto.PlaceType.NullPlaceType; + msg.MessageOfCharacter.Place = Communication.Proto.PlacccceType.NullPlaceType; break; } @@ -212,20 +212,20 @@ namespace Server msg.MessageOfBullet.ParentTeamID = bullet.Parent.TeamID; switch (bullet.Place) { - case Preparation.Utility.PlaceType.Land: - msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Land; + case Preparation.Utility.PlacccceType.Land: + msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Land; break; - case Preparation.Utility.PlaceType.Grass1: - msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass1; + case Preparation.Utility.PlacccceType.Grass1: + msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass1; break; - case Preparation.Utility.PlaceType.Grass2: - msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass2; + case Preparation.Utility.PlacccceType.Grass2: + msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass2; break; - case Preparation.Utility.PlaceType.Grass3: - msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass3; + case Preparation.Utility.PlacccceType.Grass3: + msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.Grass3; break; default: - msg.MessageOfBullet.Place = Communication.Proto.PlaceType.NullPlaceType; + msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.NullPlaceType; break; } return msg; @@ -271,20 +271,20 @@ namespace Server } switch (prop.Place) { - case Preparation.Utility.PlaceType.Land: - msg.MessageOfProp.Place = Communication.Proto.PlaceType.Land; + case Preparation.Utility.PlacccceType.Land: + msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Land; break; - case Preparation.Utility.PlaceType.Grass1: - msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass1; + case Preparation.Utility.PlacccceType.Grass1: + msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass1; break; - case Preparation.Utility.PlaceType.Grass2: - msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass2; + case Preparation.Utility.PlacccceType.Grass2: + msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass2; break; - case Preparation.Utility.PlaceType.Grass3: - msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass3; + case Preparation.Utility.PlacccceType.Grass3: + msg.MessageOfProp.Place = Communication.Proto.PlacccceType.Grass3; break; default: - msg.MessageOfProp.Place = Communication.Proto.PlaceType.NullPlaceType; + msg.MessageOfProp.Place = Communication.Proto.PlacccceType.NullPlaceType; break; } return msg;