| @@ -61,6 +61,7 @@ namespace GameClass.GameObj | |||
| this.CanMove = true; | |||
| this.score = 0; | |||
| this.buffManager = new BuffManager(); | |||
| Debugger.Output(this, characterType.ToString()); | |||
| switch (characterType) | |||
| { | |||
| case CharacterType.Assassin: | |||
| @@ -373,8 +373,8 @@ namespace GameClass.GameObj | |||
| /// <summary> | |||
| /// 角色所属队伍ID | |||
| /// </summary> | |||
| private long teamID = long.MaxValue; | |||
| public long TeamID | |||
| private int teamID = int.MaxValue; | |||
| public int TeamID | |||
| { | |||
| get => teamID; | |||
| set | |||
| @@ -386,8 +386,8 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| private long playerID = long.MaxValue; | |||
| public long PlayerID | |||
| private int playerID = int.MaxValue; | |||
| public int PlayerID | |||
| { | |||
| get => playerID; | |||
| set | |||
| @@ -91,6 +91,20 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| public class UseRobot : IActiveSkill | |||
| { | |||
| public int SkillCD => 0; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| } | |||
| public class WriteAnswers : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| @@ -110,6 +124,32 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| { | |||
| get => isBeingUsed; set => isBeingUsed = value; | |||
| } | |||
| } | |||
| public class SummonGolem : IActiveSkill | |||
| { | |||
| public int SkillCD => GameData.commonSkillCD; | |||
| public int DurationTime => 0; | |||
| private readonly object commonSkillLock = new object(); | |||
| public object ActiveSkillLock => commonSkillLock; | |||
| private Golem? golemSummoned = null; | |||
| public Golem? GolemSummoned | |||
| { | |||
| get => golemSummoned; | |||
| set | |||
| { | |||
| lock (commonSkillLock) | |||
| { | |||
| golemSummoned = value; | |||
| } | |||
| } | |||
| } | |||
| public bool isBeingUsed = false; | |||
| public bool IsBeingUsed | |||
| @@ -152,6 +192,8 @@ namespace GameClass.GameObj | |||
| return new JumpyBomb(); | |||
| case ActiveSkillType.WriteAnswers: | |||
| return new WriteAnswers(); | |||
| case ActiveSkillType.SummonGolem: | |||
| return new SummonGolem(); | |||
| default: | |||
| return new NullSkill(); | |||
| } | |||
| @@ -175,6 +217,8 @@ namespace GameClass.GameObj | |||
| return ActiveSkillType.JumpyBomb; | |||
| case WriteAnswers: | |||
| return ActiveSkillType.WriteAnswers; | |||
| case SummonGolem: | |||
| return ActiveSkillType.SummonGolem; | |||
| default: | |||
| return ActiveSkillType.Null; | |||
| } | |||
| @@ -119,6 +119,38 @@ namespace GameClass.GameObj | |||
| } | |||
| return player; | |||
| } | |||
| public Character? FindPlayerToAction(long playerID) | |||
| { | |||
| Character? player = null; | |||
| gameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Character person in gameObjDict[GameObjType.Character]) | |||
| { | |||
| if (playerID == person.ID) | |||
| { | |||
| if (person.CharacterType == CharacterType.TechOtaku && person.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed) | |||
| { | |||
| foreach (Character character in gameObjDict[GameObjType.Character]) | |||
| { | |||
| if (playerID + GameData.numOfPeople == character.ID) | |||
| { | |||
| player = character; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| else player = person; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| gameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| return player; | |||
| } | |||
| public bool Remove(GameObj gameObj) | |||
| { | |||
| bool flag = false; | |||
| @@ -7,46 +7,33 @@ namespace GameEngine | |||
| { | |||
| internal class CollisionChecker | |||
| { | |||
| /// <summary> | |||
| /// 碰撞检测,如果这样行走是否会与之碰撞,返回与之碰撞的物体 | |||
| /// </summary> | |||
| /// <param name="obj">移动的物体</param> | |||
| /// <param name="moveVec">移动的位移向量</param> | |||
| /// <returns>和它碰撞的物体</returns> | |||
| public IGameObj? CheckCollision(IMoveable obj, XY moveVec) | |||
| public IGameObj? CheckCollision(IMoveable obj, XY Pos) | |||
| { | |||
| XY nextPos = obj.Position + moveVec; | |||
| if (!obj.IsRigid) | |||
| { | |||
| if (gameMap.IsOutOfBound(obj)) | |||
| return gameMap.GetOutOfBound(nextPos); | |||
| return null; | |||
| } | |||
| // 在列表中检查碰撞 | |||
| Func<IEnumerable<IGameObj>, ReaderWriterLockSlim, IGameObj?> CheckCollisionInList = | |||
| (IEnumerable<IGameObj> lst, ReaderWriterLockSlim listLock) => | |||
| { | |||
| IGameObj? collisionObj = null; | |||
| listLock.EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (var listObj in lst) | |||
| IGameObj? collisionObj = null; | |||
| listLock.EnterReadLock(); | |||
| try | |||
| { | |||
| if (obj.WillCollideWith(listObj, nextPos)) | |||
| foreach (var listObj in lst) | |||
| { | |||
| collisionObj = listObj; | |||
| break; | |||
| if (obj.WillCollideWith(listObj, Pos)) | |||
| { | |||
| collisionObj = listObj; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| listLock.ExitReadLock(); | |||
| } | |||
| return collisionObj; | |||
| }; | |||
| finally | |||
| { | |||
| listLock.ExitReadLock(); | |||
| } | |||
| return collisionObj; | |||
| }; | |||
| IGameObj? collisionObj = null; | |||
| IGameObj? collisionObj; | |||
| foreach (var list in lists) | |||
| { | |||
| if ((collisionObj = CheckCollisionInList(list.Item1, list.Item2)) != null) | |||
| @@ -58,6 +45,23 @@ namespace GameEngine | |||
| return null; | |||
| } | |||
| /// <summary> | |||
| /// 碰撞检测,如果这样行走是否会与之碰撞,返回与之碰撞的物体 | |||
| /// </summary> | |||
| /// <param name="obj">移动的物体</param> | |||
| /// <param name="moveVec">移动的位移向量</param> | |||
| /// <returns>和它碰撞的物体</returns> | |||
| public IGameObj? CheckCollisionWhenMoving(IMoveable obj, XY moveVec) | |||
| { | |||
| XY nextPos = obj.Position + moveVec; | |||
| if (!obj.IsRigid) | |||
| { | |||
| if (gameMap.IsOutOfBound(obj)) | |||
| return gameMap.GetOutOfBound(nextPos); | |||
| return null; | |||
| } | |||
| return CheckCollision(obj, nextPos); | |||
| } | |||
| /// <summary> | |||
| /// /// 可移动物体(圆)向矩形物体移动时,可移动且不会碰撞的最大距离。直接用double计算,防止误差 | |||
| /// </summary> | |||
| /// <param name="obj"></param> | |||
| @@ -33,6 +33,12 @@ namespace GameEngine | |||
| return PlaceType.Null; | |||
| } | |||
| } | |||
| public IGameObj? CheckCollision(IMoveable obj, XY Pos) | |||
| { | |||
| return collisionChecker.CheckCollision(obj, Pos); | |||
| } | |||
| private readonly CollisionChecker collisionChecker; | |||
| private readonly Func<IMoveable, IGameObj, XY, AfterCollision> OnCollision; | |||
| /// <summary> | |||
| @@ -65,7 +71,7 @@ namespace GameEngine | |||
| XY nextPos = obj.Position + moveVec; | |||
| double maxLen = collisionChecker.FindMax(obj, nextPos, moveVec); | |||
| maxLen = Math.Min(maxLen, obj.MoveSpeed / GameData.numOfStepPerSecond); | |||
| obj.MovingSetPos(new XY(moveVec.Angle(), maxLen), GetPlaceType(nextPos)); | |||
| obj.MovingSetPos(new XY(moveVec, maxLen), GetPlaceType(nextPos)); | |||
| } | |||
| public void MoveObj(IMoveable obj, int moveTime, double direction) | |||
| @@ -98,7 +104,7 @@ namespace GameEngine | |||
| do | |||
| { | |||
| flag = false; | |||
| collisionObj = collisionChecker.CheckCollision(obj, res); | |||
| collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res); | |||
| if (collisionObj == null) | |||
| break; | |||
| @@ -135,7 +141,7 @@ namespace GameEngine | |||
| { | |||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||
| res = new XY(direction, moveVecLength); | |||
| if ((collisionObj = collisionChecker.CheckCollision(obj, res)) == null) | |||
| if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) | |||
| { | |||
| obj.MovingSetPos(res, GetPlaceType(obj.Position + res)); | |||
| } | |||
| @@ -375,7 +375,7 @@ namespace Gaming | |||
| loopToDo: () => { }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0, | |||
| maxTotalDuration: (int)((windowToPlayer + windowForClimb.Position - player.Position).Length() / player.MoveSpeed) | |||
| maxTotalDuration: (int)((windowToPlayer + windowForClimb.Position - player.Position).Length() * 1000 / player.MoveSpeed) | |||
| ) | |||
| .Start(); | |||
| if (player.PlayerState != PlayerStateType.ClimbingThroughWindows) | |||
| @@ -386,13 +386,13 @@ namespace Gaming | |||
| player.ReSetPos(windowToPlayer + windowForClimb.Position, PlaceType.Window); | |||
| player.MoveSpeed = player.SpeedOfClimbingThroughWindows; | |||
| MovePlayer(player, (int)(windowToPlayer.Length() * 3.0 / player.MoveSpeed), (-1 * windowToPlayer).Angle()); | |||
| MovePlayer(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle()); | |||
| new FrameRateTaskExecutor<int>( | |||
| loopCondition: () => player.PlayerState == PlayerStateType.ClimbingThroughWindows && player.IsMoving && gameMap.Timer.IsGaming, | |||
| loopToDo: () => { }, | |||
| timeInterval: GameData.frameDuration, | |||
| finallyReturn: () => 0, | |||
| maxTotalDuration: (int)(windowToPlayer.Length() * 3.0 / player.MoveSpeed) | |||
| maxTotalDuration: (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed) | |||
| ) | |||
| .Start(); | |||
| XY PosJumpOff = windowForClimb.Position - 2 * windowToPlayer; | |||
| @@ -497,7 +497,7 @@ namespace Gaming | |||
| */ | |||
| private readonly Map gameMap; | |||
| private readonly MoveEngine moveEngine; | |||
| public readonly MoveEngine moveEngine; | |||
| public ActionManager(Map gameMap) | |||
| { | |||
| this.gameMap = gameMap; | |||
| @@ -287,7 +287,15 @@ namespace Gaming | |||
| gameMap.Add(prop); | |||
| } | |||
| } | |||
| if (player.CharacterType == CharacterType.Robot) return; | |||
| if (player.CharacterType == CharacterType.Robot) | |||
| { | |||
| if (((Golem)player).Parent != null && ((Golem)player).Parent.CharacterType == CharacterType.TechOtaku) | |||
| { | |||
| ((SummonGolem)player.FindIActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned = null; | |||
| player.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; | |||
| } | |||
| return; | |||
| } | |||
| ++gameMap.NumOfDeceasedStudent; | |||
| if (GameData.numOfStudent - gameMap.NumOfDeceasedStudent - gameMap.NumOfEscapedStudent == 1) | |||
| { | |||
| @@ -77,7 +77,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| bool res = actionManager.MovePlayer(player, moveTimeInMilliseconds, angle); | |||
| @@ -100,7 +100,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| ICharacter? player = gameMap.FindPlayer(playerID); | |||
| ICharacter? player = gameMap.FindPlayerToAction(playerID); | |||
| if (playerTreatedID == -1) | |||
| { | |||
| if (player != null && !player.IsGhost()) | |||
| @@ -121,7 +121,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| ICharacter? player = gameMap.FindPlayer(playerID); | |||
| ICharacter? player = gameMap.FindPlayerToAction(playerID); | |||
| if (playerRescuedID == -1) | |||
| { | |||
| if (player != null && !player.IsGhost()) | |||
| @@ -143,7 +143,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| ICharacter? player = gameMap.FindPlayer(playerID); | |||
| ICharacter? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null && !player.IsGhost()) | |||
| return actionManager.Fix((Student)player); | |||
| return false; | |||
| @@ -152,7 +152,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| ICharacter? player = gameMap.FindPlayer(playerID); | |||
| ICharacter? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| if (!player.IsGhost()) | |||
| @@ -164,7 +164,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| return ActionManager.Stop(player); | |||
| @@ -175,7 +175,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null && !player.IsGhost()) | |||
| { | |||
| return actionManager.OpenDoorway((Student)player); | |||
| @@ -186,7 +186,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| return actionManager.OpenChest(player); | |||
| @@ -197,7 +197,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| return actionManager.ClimbingThroughWindow(player); | |||
| @@ -208,7 +208,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| return actionManager.LockOrOpenDoor(player); | |||
| @@ -219,7 +219,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| _ = attackManager.Attack(player, angle); | |||
| @@ -229,7 +229,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| PropManager.UseProp(player, propType); | |||
| @@ -239,7 +239,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| propManager.ThrowProp(player, propType); | |||
| @@ -249,7 +249,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return false; | |||
| Character? player = gameMap.FindPlayer(playerID); | |||
| Character? player = gameMap.FindPlayerToAction(playerID); | |||
| if (player != null) | |||
| { | |||
| return propManager.PickProp(player, propType); | |||
| @@ -186,7 +186,7 @@ namespace Gaming | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Chest].ExitWriteLock(); | |||
| } | |||
| /* | |||
| new Thread | |||
| ( | |||
| () => | |||
| @@ -208,6 +208,7 @@ namespace Gaming | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| */ | |||
| } | |||
| public PropManager(Map gameMap) // 道具不能扔过墙 | |||
| { | |||
| @@ -11,20 +11,6 @@ namespace Gaming | |||
| { | |||
| private partial class SkillManager | |||
| { | |||
| public bool BecomeVampire(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.BecomeVampire), 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 bool CanBeginToCharge(Character player) | |||
| { | |||
| @@ -42,9 +28,9 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| public static bool BecomeInvisible(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.BecomeInvisible); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| @@ -55,6 +41,14 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| public static bool UseRobot(Character player) | |||
| { | |||
| if ((!player.Commandable()) || ((SummonGolem)player.FindIActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned == null) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.UseRobot); | |||
| activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true; | |||
| return true; | |||
| } | |||
| public bool JumpyBomb(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.JumpyBomb), player, () => | |||
| @@ -68,6 +62,7 @@ namespace Gaming | |||
| public bool WriteAnswers(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.WriteAnswers); | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| @@ -83,6 +78,22 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| public bool SummonGolem(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.SummonGolem); | |||
| if (((SummonGolem)activeSkill).GolemSummoned != null) return false; | |||
| XY res = player.Position + new XY(player.FacingDirection, player.Radius * 2); | |||
| if (actionManager.moveEngine.CheckCollision(player, res) != null) | |||
| return false; | |||
| return ActiveSkillEffect(activeSkill, player, () => | |||
| { | |||
| characterManager.AddPlayer(res, player.TeamID, player.PlayerID + GameData.numOfPeople, CharacterType.Robot, player); | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| public static bool UseKnife(Character player) | |||
| { | |||
| @@ -97,6 +108,7 @@ namespace Gaming | |||
| public bool Howl(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Howl), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| @@ -125,6 +137,7 @@ namespace Gaming | |||
| public bool Punish(Character player) | |||
| { | |||
| if ((!player.Commandable())) return false; | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Punish), player, () => | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| @@ -153,18 +166,6 @@ namespace Gaming | |||
| { }); | |||
| } | |||
| public bool SuperFast(Character player) | |||
| { | |||
| return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.SuperFast), player, () => | |||
| { | |||
| player.AddMoveSpeed(player.FindIActiveSkill(ActiveSkillType.SuperFast).DurationTime, 3.0); | |||
| Debugger.Output(player, "moves very fast!"); | |||
| }, | |||
| () => | |||
| { }); | |||
| } | |||
| public static bool ActiveSkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) | |||
| { | |||
| lock (activeSkill.ActiveSkillLock) | |||
| @@ -37,6 +37,9 @@ namespace Gaming | |||
| case ActiveSkillType.WriteAnswers: | |||
| WriteAnswers(character); | |||
| break; | |||
| case ActiveSkillType.SummonGolem: | |||
| SummonGolem(character); | |||
| break; | |||
| default: | |||
| return false; | |||
| } | |||
| @@ -5,7 +5,7 @@ namespace Preparation.Interface | |||
| { | |||
| public interface ICharacter : IGameObj | |||
| { | |||
| public long TeamID { get; } | |||
| public int TeamID { get; } | |||
| public int HP { get; set; } | |||
| public int Score { get; } | |||
| public void AddScore(int add); | |||
| @@ -295,7 +295,7 @@ namespace Preparation.Interface | |||
| public BulletType InitBullet => BulletType.Null; | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { }); | |||
| public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.SummonGolem, ActiveSkillType.UseRobot }); | |||
| public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { }); | |||
| public const int fixSpeed = (int)(GameData.basicFixSpeed * 1.1); | |||
| @@ -89,12 +89,13 @@ namespace Preparation.Utility | |||
| BecomeInvisible = 1, | |||
| BecomeVampire = 2, | |||
| JumpyBomb = 3, | |||
| SuperFast = 4, | |||
| SummonGolem = 4, | |||
| UseKnife = 5, | |||
| CanBeginToCharge = 6, | |||
| Punish = 7, | |||
| WriteAnswers = 8, | |||
| Howl = 9, | |||
| UseRobot = 10, | |||
| } | |||
| public enum PassiveSkillType | |||
| { | |||
| @@ -16,6 +16,9 @@ namespace Preparation.Utility | |||
| public const int MinSpeed = 1; // 最小速度 | |||
| public const int MaxSpeed = int.MaxValue; // 最大速度 | |||
| public const int numOfStudent = 4; | |||
| public const int numOfPeople = 5; | |||
| #endregion | |||
| #region 地图相关 | |||
| public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | |||
| @@ -24,7 +27,7 @@ namespace Preparation.Utility | |||
| public const int cols = 50; // 列数 | |||
| public const int numOfBirthPoint = 5; | |||
| public const int numOfGenerator = 9; | |||
| public const int numOfGenerator = 10; | |||
| public const int numOfChest = 8; | |||
| public static bool IsMap(GameObjType gameObjType) | |||
| @@ -77,7 +80,6 @@ namespace Preparation.Utility | |||
| } | |||
| #endregion | |||
| #region 角色相关 | |||
| public const int numOfStudent = 4; | |||
| public const int characterRadius = numOfPosGridPerCell * 4 / 10; // 人物半径 | |||
| public const int basicTreatSpeed = 100; | |||
| @@ -12,6 +12,6 @@ start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --ch | |||
| ping -n 2 127.0.0.1 > NUL | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 1 --type 1 --occupation 3 | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 1 --type 1 --occupation 5 | |||
| ping -n 2 127.0.0.1 > NUL | |||
| @@ -208,7 +208,7 @@ | |||
| - 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 | |||
| ### 破译与逃脱 | |||
| - 每张地图都会刷新 9台电机,求生者需要破译其中的7台,并开启任意一个大门后从任意一个开启的大门- 逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱; | |||
| - 每张地图都有10台电机,求生者需要破译其中的7台,并开启任意一个大门后从任意一个开启的大门- 逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱; | |||
| - 求生者和监管者在靠近电机时,可以看到电机的破译进度条。 | |||
| - 紧急出口会在电机破译完成3台的情况下在地图的3-5个固定紧急出口刷新点之一随机刷新。 | |||
| - 当求生者只剩1名时,紧急出口盖将会自动打开,该求生者可从紧急出口逃脱。 | |||