diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index b479ab3..fc3fefe 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -14,6 +14,31 @@ namespace GameClass.GameObj public Dictionary BirthPointList => birthPointList; private object lockForNum = new(); + private void WhenNumChange() + { + if (numOfDeceasedStudent + numOfEscapedStudent == GameData.numOfStudent) + { + Timer.IsGaming = false; + } + + if (GameData.numOfStudent - NumOfDeceasedStudent - NumOfEscapedStudent == 1) + { + GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); + try + { + foreach (EmergencyExit emergencyExit in GameObjDict[GameObjType.EmergencyExit]) + if (emergencyExit.CanOpen) + { + emergencyExit.IsOpen = true; + break; + } + } + finally + { + GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); + } + } + } private uint numOfRepairedGenerators = 0; public uint NumOfRepairedGenerators { @@ -23,6 +48,7 @@ namespace GameClass.GameObj lock (lockForNum) { numOfRepairedGenerators = value; + WhenNumChange(); } } } @@ -35,10 +61,7 @@ namespace GameClass.GameObj lock (lockForNum) { numOfDeceasedStudent = value; - if (numOfDeceasedStudent + numOfEscapedStudent == GameData.numOfStudent) - { - Timer.IsGaming = false; - } + WhenNumChange(); } } } diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs index f1708c9..b579e90 100644 --- a/logic/Gaming/CharacterManager .cs +++ b/logic/Gaming/CharacterManager .cs @@ -297,23 +297,6 @@ namespace Gaming return; } ++gameMap.NumOfDeceasedStudent; - if (GameData.numOfStudent - gameMap.NumOfDeceasedStudent - gameMap.NumOfEscapedStudent == 1) - { - gameMap.GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); - try - { - foreach (EmergencyExit emergencyExit in gameMap.GameObjDict[GameObjType.EmergencyExit]) - if (emergencyExit.CanOpen) - { - emergencyExit.IsOpen = true; - break; - } - } - finally - { - gameMap.GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); - } - } } } diff --git a/logic/规则Logic.md b/logic/规则Logic.md index b13639e..7a3c43c 100644 --- a/logic/规则Logic.md +++ b/logic/规则Logic.md @@ -14,215 +14,30 @@ [对于选手来说,需要提前制定好学生的学习方案以抵御对方捣蛋鬼的干扰,类似地,也需要制定好捣蛋鬼的行动策略以影响对方学生的学习,也即每队至少要写好两份代码以执行不同阵营的不同策略。] [当一局比赛结束(场上的学生有且仅有两种状态:退学或毕业)时,分别记录双方总得分;之后双方换边进行下半场比赛。最终将每队的学生方、捣蛋鬼方的得分相加,比较总得分判断胜负。] -## 地图 -- 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。x坐标轴正方向竖直向下, -- y坐标轴正方向水平向右;极坐标以x坐标轴为极轴,角度逆时针为正方向。 +## 简要规则 + +### 地图 +- 地图为矩形区域,地图上的游戏对象坐标为(x, y),且x和y均为整数。 +- **x坐标轴正方向竖直向下,y坐标轴正方向水平向右**; +- **极坐标以x坐标轴为极轴,角度逆时针为正方向**。 - 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到: - 略 - - 也就是说,地图实际大小是 50000 * 50000 - 地图上的每个格子有自己的区域类型:墙、草地、电机、出口、紧急出口、门、窗、箱子 -- 出生点固定且一定为空地 - -## 游戏内的枚举类型、类与属性 -- 底层实现中的属性,不代表界面全部都需要展示,也可能需要额外展示信息 -- 只展示外部需要的属性,部分属性被省略 - -### BgmType -- 枚举类BgmType - 1. 不详的感觉:监管者进入(求生者的警戒半径/监管者的隐蔽度)时,求生者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) - 2. 期待搞事的感觉:求生者进入(监管者的警戒半径/求生者的隐蔽度)时,监管者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的求生者距离) - 3. 修理电机的声音: 监管者警戒半径内有电机正在被修理时收到;bgmVolume=(警戒半径*电机修理程度/二者距离)/10300000 - ~~~csharp - public enum BgmType - { - Null = 0, - GhostIsComing = 1, - StudentIsApproaching = 2, - GeneratorIsBeingFixed = 3, - } - ~~~ - -### 技能 - ~~~csharp - public enum ActiveSkillType // 主动技能 - { - Null = 0, - BecomeInvisible = 1, - ... - UseKnife = 5, - BeginToCharge = 6 - } - public enum PassiveSkillType - { - Null = 0, - } - ~~~ - -### 物体 -- 位置 -- 位置地形 -- ID -- 类型 -- 面向角度 -- 形状 -- 半径 -- 是否可移动 -- 是否在移动 -- 移动速度 - -### 人物:物体 - -- 装弹CD -- 持有子弹数量 -- 血量 -- 最大血量 -- 玩家状态(不可叠加) - ~~~csharp - public enum PlayerStateType - { - Null = 0, - Addicted = 1, - Escaped = 2, - Swinging = 3,//指后摇 - Deceased = 4, - Moving = 5, - Treating = 6, - Rescuing = 7, - Fixing = 8, - Treated = 9, - Rescued = 10, - Stunned = 11, - TryingToAttack = 12,//指前摇 - LockingOrOpeningTheDoor = 13, - OpeningTheChest = 14, - ClimbingThroughWindows = 15, - UsingSkill = 16, - OpeningTheDoorway = 17, - } - ~~~ -- 可执行指令的(不用给选手) - ~~~csharp - public bool Commandable() => (playerState != PlayerStateType.IsDeceased && playerState != PlayerStateType.IsEscaped - && playerState != PlayerStateType.IsAddicted && playerState != PlayerStateType.IsRescuing - && playerState != PlayerStateType.IsSwinging && playerState != PlayerStateType.IsTryingToAttack - && playerState != PlayerStateType.IsClimbingThroughWindows && playerState != PlayerStateType.IsStunned); - ~~~ -- Bgm(字典) -- 得分 -- ~~回血率/原始回血率~~ -- 当前子弹类型 -- 原始子弹类型 -- 持有道具 (最多三个)(数组) -- 是否隐身 -- 队伍ID -- 玩家ID -- 当前Buff -- 职业类型 -- 拥有的被动技能(列表) -- 拥有的主动技能(列表) -- 各个主动技能CD(字典) -- 警戒半径 -- double 隐蔽度 -- 翻窗时间 -- 开锁门速度 -- 开箱速度 -- 视野范围 - -### 学生:人物 -- 修理电机速度 -- 治疗速度 -- ~~救人速度~~ -- ~~自愈次数~~ -- 沉迷游戏程度 -- 最大沉迷游戏程度 -- 被治疗程度 -- *被救援程度* - -### 搞蛋鬼:人物 -无 - -### 队伍: -- 队伍ID -- 队伍得分 -- 队伍成员 - -### 所有物: -- 主人 - -### 子弹:所有物 -- 子弹攻击范围 -- 子弹爆炸范围 -- 子弹攻击力 -- 是否可以穿墙 -- 是否为远程攻击 -- 移动速度 -- 子弹类型 - -### 爆炸中的子弹:物体 -- 原来的子弹ID -- 爆炸范围 -- 子弹类型 - -### 道具:所有物 -- 道具类型 - -### 被捡起的道具:物体 -- 原来的道具ID -- 道具类型 - -### 出口:物体 -- 电力供应(是否可以被打开) -- 开启进度 - -### 紧急出口:物体 -- 是否显现 -- 是否打开 - -### 墙:物体 - -### 窗:物体 -- 正在翻窗的人 - -### 箱子:物体 -- 开箱进度 - -### 门:物体 -- 属于那个教学区 -- 是否锁上 -- 开锁门进度 -- 不提供是否可以锁上的属性 - -### 电机(建议称为homework):物体 -- 修理程度 - -## 行为逻辑 - -### 初始状态 -- 所有玩家可以立刻使用主动技能 -- 玩家出生点固定 ### 交互 - 除了逃离和翻窗,交互目标与交互者在一个九宫格内则为可交互 - 逃离或翻窗时玩家应当在目标前后左右一个格子内 -- 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 - - 实际上救援或治疗不同的人是有效的 ### 破译与逃脱 -- 每张地图都有10台电机,求生者需要破译其中的7台,并开启任意一个大门后从任意一个开启的大门逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱; -- 求生者和监管者在靠近电机时,可以看到电机的破译进度条。 +- 每张地图都有10台电机,求生者需要破译其中的7台,并开启任意一个大门(总所需时间为18秒)后从任意一个开启的大门逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱; - 紧急出口会在电机破译完成3台的情况下在地图的3-5个固定紧急出口刷新点之一随机刷新。 -- 紧急出口与大门对于人有碰撞体积 - 当求生者只剩1名时,紧急出口将会自动打开,该求生者可从紧急出口逃脱。 -- 开启大门所需时间为18秒。 - 大门开启的进度不清空 -- 一个大门同时最多可以由一人开启 ### 攻击 -- 每次求生者收到攻击后会损失对应子弹的攻击力的血量 -- 小部分求生者通过手持物可以获得一定程度反击监管者的手段,可使其丧失行动能力(称为击晕),但监管者不会永久丧失行动能力。 -- 无论搞蛋鬼或学生,攻击时,从播放攻击动作到可以开始产生伤害的期间,称为前摇。(前摇阶段,搞蛋鬼产生通常为不可爆炸(部分搞蛋鬼能可以产生可爆炸)子弹(爆炸范围=0),[子弹大小待商榷],期间监管者攻击被打断时,子弹消失)(无论近战远程均产生子弹) +- 攻击时,从播放攻击动作到可以开始产生伤害的期间,称为前摇。 +(前摇阶段,搞蛋鬼产生通常为不可爆炸(部分搞蛋鬼能可以产生可爆炸)子弹(爆炸范围=0),[子弹大小待商榷],期间监管者攻击被打断时,子弹消失)(无论近战远程均产生子弹) - 无论搞蛋鬼或学生,攻击后,通常会出现一段无伤害判定的攻击动作后置时间,称为后摇。击中物体时后摇更长 - - 假如监管者攻击或一些监管者的特定技能击中正在交互或处于攻击前后摇或使用部分技能(指PlayerState==UsingSkill)的求生者,将使求生者眩晕 1. 处于前摇或后摇 2. 治疗或解救他人 @@ -231,6 +46,25 @@ 5. 翻窗 6. 开启箱子 +## 细则 + +### 初始状态 +- 所有玩家可以立刻使用主动技能 + - 虽然一开始会接到仍需的冷却时间,但实际上是CD +- 玩家出生点固定且一定为空地 + +### 交互 +- 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令 + - 实际上救援或治疗不同的人是有效的 + +### 破译与逃脱 +- 紧急出口与大门对于人有碰撞体积 +- 一个大门同时最多可以由一人开启 + +### 攻击 +- 每次求生者受到攻击后会损失对应子弹的攻击力的血量 +- 小部分求生者通过手持物可以获得一定程度反击监管者的手段,可使其丧失行动能力(称为击晕),但监管者不会永久丧失行动能力。 + ### 门 - 门分别属于三个教学区:三教,五教,六教 - 监管者或求生者都需要拿到对应教学区的钥匙才能打开或锁住对应的门 @@ -608,10 +442,181 @@ ## 游戏数据 - -### 基本常数 请自行查看Logic/Preparation/Utility/GameData.cs + +## 游戏内的枚举类型、类与属性 +- 底层实现中的属性,不代表界面全部都需要展示,也可能需要额外展示信息 +- 只展示外部需要的属性,部分属性被省略 + +### BgmType +- 枚举类BgmType + 1. 不详的感觉:监管者进入(求生者的警戒半径/监管者的隐蔽度)时,求生者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离) + 2. 期待搞事的感觉:求生者进入(监管者的警戒半径/求生者的隐蔽度)时,监管者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的求生者距离) + 3. 修理电机的声音: 监管者警戒半径内有电机正在被修理时收到;bgmVolume=(警戒半径*电机修理程度/二者距离)/10300000 + ~~~csharp + public enum BgmType + { + Null = 0, + GhostIsComing = 1, + StudentIsApproaching = 2, + GeneratorIsBeingFixed = 3, + } + ~~~ + +### 技能 + ~~~csharp + public enum ActiveSkillType // 主动技能 + { + Null = 0, + BecomeInvisible = 1, + ... + UseKnife = 5, + BeginToCharge = 6 + } + public enum PassiveSkillType + { + Null = 0, + } + ~~~ + +### 物体 +- 位置 +- 位置地形 +- ID +- 类型 +- 面向角度 +- 形状 +- 半径 +- 是否可移动 +- 是否在移动 +- 移动速度 + +### 人物:物体 + +- 装弹CD +- 持有子弹数量 +- 血量 +- 最大血量 +- 玩家状态(不可叠加) + ~~~csharp + public enum PlayerStateType + { + Null = 0, + Addicted = 1, + Escaped = 2, + Swinging = 3,//指后摇 + Deceased = 4, + Moving = 5, + Treating = 6, + Rescuing = 7, + Fixing = 8, + Treated = 9, + Rescued = 10, + Stunned = 11, + TryingToAttack = 12,//指前摇 + LockingOrOpeningTheDoor = 13, + OpeningTheChest = 14, + ClimbingThroughWindows = 15, + UsingSkill = 16, + OpeningTheDoorway = 17, + } + ~~~ +- 可执行指令的(不用给选手) + ~~~csharp + public bool Commandable() => (playerState != PlayerStateType.IsDeceased && playerState != PlayerStateType.IsEscaped + && playerState != PlayerStateType.IsAddicted && playerState != PlayerStateType.IsRescuing + && playerState != PlayerStateType.IsSwinging && playerState != PlayerStateType.IsTryingToAttack + && playerState != PlayerStateType.IsClimbingThroughWindows && playerState != PlayerStateType.IsStunned); + ~~~ +- Bgm(字典) +- 得分 +- ~~回血率/原始回血率~~ +- 当前子弹类型 +- 原始子弹类型 +- 持有道具 (最多三个)(数组) +- 是否隐身 +- 队伍ID +- 玩家ID +- 当前Buff +- 职业类型 +- 拥有的被动技能(列表) +- 拥有的主动技能(列表) +- 各个主动技能CD(字典) +- 警戒半径 +- double 隐蔽度 +- 翻窗时间 +- 开锁门速度 +- 开箱速度 +- 视野范围 + +### 学生:人物 +- 修理电机速度 +- 治疗速度 +- ~~救人速度~~ +- ~~自愈次数~~ +- 沉迷游戏程度 +- 最大沉迷游戏程度 +- 被治疗程度 +- *被救援程度* + +### 搞蛋鬼:人物 +无 + +### 队伍: +- 队伍ID +- 队伍得分 +- 队伍成员 + +### 所有物: +- 主人 + +### 子弹:所有物 +- 子弹攻击范围 +- 子弹爆炸范围 +- 子弹攻击力 +- 是否可以穿墙 +- 是否为远程攻击 +- 移动速度 +- 子弹类型 + +### 爆炸中的子弹:物体 +- 原来的子弹ID +- 爆炸范围 +- 子弹类型 + +### 道具:所有物 +- 道具类型 + +### 被捡起的道具:物体 +- 原来的道具ID +- 道具类型 + +### 出口:物体 +- 电力供应(是否可以被打开) +- 开启进度 + +### 紧急出口:物体 +- 是否显现 +- 是否打开 + +### 墙:物体 + +### 窗:物体 +- 正在翻窗的人 + +### 箱子:物体 +- 开箱进度 + +### 门:物体 +- 属于那个教学区 +- 是否锁上 +- 开锁门进度 +- 不提供是否可以锁上的属性 + +### 电机(建议称为homework):物体 +- 修理程度 + ## 键鼠控制 | 键位 | 效果 |