Browse Source

Merge pull request #237 from shangfengh/new

build: 📝 edit 规则Logic.md
tags/0.1.0
Shawqeem GitHub 2 years ago
parent
commit
fc85cb9d8e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 181 additions and 375 deletions
  1. +19
    -0
      logic/GameClass/GameObj/Character/Skill.cs
  2. +1
    -1
      logic/Gaming/ActionManager.cs
  3. +1
    -1
      logic/Gaming/AttackManager.cs
  4. +1
    -0
      logic/Gaming/CharacterManager .cs
  5. +31
    -0
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  6. +3
    -0
      logic/Gaming/SkillManager/SkillManager.cs
  7. +3
    -5
      logic/cmd/gameServer.cmd
  8. +122
    -368
      logic/规则Logic.md

+ 19
- 0
logic/GameClass/GameObj/Character/Skill.cs View File

@@ -48,6 +48,21 @@ namespace GameClass.GameObj
}
}

public class Rouse : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD;
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 Howl : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD * 3 / 4;
@@ -196,6 +211,8 @@ namespace GameClass.GameObj
return new SummonGolem();
case ActiveSkillType.UseRobot:
return new UseRobot();
case ActiveSkillType.Rouse:
return new Rouse();
default:
return new NullSkill();
}
@@ -223,6 +240,8 @@ namespace GameClass.GameObj
return ActiveSkillType.SummonGolem;
case UseRobot:
return ActiveSkillType.UseRobot;
case Rouse:
return ActiveSkillType.Rouse;
default:
return ActiveSkillType.Null;
}


+ 1
- 1
logic/Gaming/ActionManager.cs View File

@@ -252,7 +252,7 @@ namespace Gaming
if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue)
{
playerRescued.PlayerState = PlayerStateType.Null;
playerRescued.HP = GameData.RemainHpWhenAddLife;
playerRescued.HP = playerRescued.MaxHp / 2;
player.AddScore(GameData.StudentScoreRescue);
}
else


+ 1
- 1
logic/Gaming/AttackManager.cs View File

@@ -105,7 +105,7 @@ namespace Gaming
if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null)
{
bullet.Parent.BulletOfPlayer = BulletType.JumpyDumpty;
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI);
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0);
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0);
}



+ 1
- 0
logic/Gaming/CharacterManager .cs View File

@@ -328,6 +328,7 @@ namespace Gaming
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp));
bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
}
student.DegreeOfTreatment = 0;
if (student.HP <= 0)
student.TryActivatingLIFE(); // 如果有复活甲



+ 31
- 0
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -51,6 +51,7 @@ namespace Gaming

public static bool JumpyBomb(Character player)
{
if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.JumpyBomb), player, () =>
{
player.BulletOfPlayer = BulletType.BombBomb;
@@ -167,6 +168,36 @@ namespace Gaming
{ });
}

public bool Rouse(Character player)
{
if ((!player.Commandable())) return false;
return ActiveSkillEffect(player.FindIActiveSkill(ActiveSkillType.Rouse), player, () =>
{
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try
{
foreach (Character character in gameMap.GameObjDict[GameObjType.Character])
{
if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character))
{
character.PlayerState = PlayerStateType.Null;
character.HP = GameData.RemainHpWhenAddLife;
((Student)character).TimeOfRescue = 0;
player.AddScore(GameData.StudentScoreRescue);
break;
}
}
}
finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}
Debugger.Output(player, "rouse someone!");
},
() =>
{ });
}

public static bool ActiveSkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill)
{
lock (activeSkill.ActiveSkillLock)


+ 3
- 0
logic/Gaming/SkillManager/SkillManager.cs View File

@@ -43,6 +43,9 @@ namespace Gaming
case ActiveSkillType.UseRobot:
UseRobot(character);
break;
case ActiveSkillType.Rouse:
Rouse(character);
break;
default:
return false;
}


+ 3
- 5
logic/cmd/gameServer.cmd View File

@@ -1,13 +1,11 @@
@echo off

start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName test
start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 2 --trickerCount 1 --gameTimeInSecond 600 --fileName test

ping -n 2 127.0.0.1 > NUL

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 4 --type 2 --occupation 2

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 0 --type 1 --occupation 1

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 1 --type 1 --occupation 2

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 2 --type 1 --occupation 2

start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --cl --port 8888 --characterID 3 --type 1 --occupation 3

+ 122
- 368
logic/规则Logic.md View File

@@ -1,11 +1,8 @@
# 规则Logic

## 说明
- 版本V2.0
- 该规则直接服务于Sever,并非选手版本
- *斜体表示Logic底层尚未(完全)实现*
- []表示待决定
- ~~表示暂不实现~~

## 游戏简介
- 1位监管者对抗4位求生者的非对称竞技模式
@@ -22,24 +19,47 @@
- **极坐标以x坐标轴为极轴,角度逆时针为正方向**。
- 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到:
- 略
- 地图上的每个格子有自己的区域类型:墙、草地、电机、出口、紧急出口、门、窗、箱子
- 地图上的每个格子有自己的区域类型:陆地、墙、草地、电机、出口、紧急出口、门、窗、箱子

### 人物状态
游戏人物共有17种不可叠加的状态:(加*为学生独有)
1.普通状态
2*.学习
3*.被治疗
4*.在治疗
5.开或锁门
6.翻箱
7.使用技能
8*.正在毕业
9*.唤醒他人中

10*.被唤醒中(从沉迷状态中)
11*.沉迷
12*.退学
13*.毕业
14.被眩晕
15.前摇
16.后摇
17.翻窗

其中后8项为不可行动状态
-不加声明,不可行动状态中的玩家各项指令是无效的

### 交互
- 除了翻窗,交互目标与交互者在一个九宫格内则为可交互
- 翻窗时玩家应当在目标前后左右一个格子内

### 破译与逃脱
#### 破译与逃脱
- 每张地图都有10台电机,求生者需要破译其中的7台,并开启任意一个大门(总所需时间为18秒)后从任意一个开启的大门逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱;
- 紧急出口会在电机破译完成3台的情况下在地图的3-5个固定紧急出口刷新点之一随机刷新。
- 当求生者只剩1名时,紧急出口将会自动打开,该求生者可从紧急出口逃脱。
- 大门开启的进度不清空

### 攻击
#### 攻击
- 无论近战远程均产生子弹以表示攻击所至距离
- 攻击时,从播放攻击动作到可以开始产生伤害的期间,称为前摇。
(前摇阶段,搞蛋鬼产生通常为不可爆炸(部分搞蛋鬼能可以产生可爆炸)子弹(爆炸范围=0),[子弹大小待商榷],期间监管者攻击被打断时,子弹消失)()
- 攻击时,从播放攻击动作到可以开始产生伤害的期间,称为前摇。前摇期间攻击被打断时,子弹消失。
- 无论搞蛋鬼或学生,攻击后,通常会出现一段无伤害判定的攻击动作后置时间,称为后摇。击中物体时后摇更长
- 假如监管者攻击或一些监管者的特定技能击中正在交互或处于攻击前后摇或使用部分技能(指PlayerState==UsingSkill)的求生者,将使求生者眩晕
- 捣蛋鬼攻击或一些特定技能击中以下状态的求生者,将使求生者眩晕4.13s
1. 处于前摇或后摇
2. 治疗或解救他人
3. 修理电机
@@ -47,139 +67,63 @@
5. 翻窗
6. 开启箱子

## 细则

### 初始状态
- 所有玩家可以立刻使用主动技能
- 虽然一开始会接到仍需的冷却时间,但实际上是CD
- 玩家出生点固定且一定为空地

### 交互
- 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令
- 实际上救援或治疗不同的人是有效的

### 破译与逃脱
- 紧急出口与大门对于人有碰撞体积
- 一个大门同时最多可以由一人开启

### 攻击
- 每次求生者受到攻击后会损失对应子弹的攻击力的血量
- 小部分求生者通过手持物可以获得一定程度反击监管者的手段,可使其丧失行动能力(称为击晕),但监管者不会永久丧失行动能力。

### 门
- 门分别属于三个教学区:三教,五教,六教
- 监管者或求生者都需要拿到对应教学区的钥匙才能打开或锁住对应的门
- 锁门和开门都需要一定时间,进出门为正常移动过程
- 门只有开、锁两种状态,锁住时门有碰撞体积
- 当门所在格子内有人时,无法锁门(必须从门外锁门)
- 锁门时其他人可以进入门所在格子,锁门过程中断
- 钥匙只会出现在箱子中,每个教学区都有2把钥匙
- 一扇门只允许同时一个人开锁门
- 开锁门未完成前,门状态表现为原来的状态
- 开锁门进度中断后清空

### 窗
- 求生者和监管者都可以翻越窗户,但通常情况下监管者翻越窗户的速度**高于**求生者。
- 在求生者或监管者正在翻越窗户时,其他玩家均不可以翻越该窗户。
- 攻击可以穿过窗,道具可以在窗上
- 翻窗时玩家应当在窗前后一个格子内
- 翻越窗户是一种交互行为,翻窗一共有两个过程
- 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度,中断时,停留在原位置
- 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度,中断时,停留在另一侧格子中心
- 窗必须在两个墙之间,另外两侧不能为墙

### 箱子
- 监管者和求生者都能与箱子交互,同一时刻只允许一人进行开启
- 开启箱子有不同概率获得不同道具。
- 开启箱子的基础持续时间为10秒。
- 未开启完成的箱子在下一次需要重新开始开启。
- 箱子开启后其中道具才可以被观测和拿取
- [箱子道具不刷新]
- [箱子不可被关闭]
- [箱子内道具最多两个]

### 治疗
- 可行动的求生者可以对受伤的其他求生者进行治疗,治疗完成后会回复被治疗程度的血量。
#### 治疗
- 治疗时每毫秒增加相当于治疗者治疗速度的被治疗程度
- 当达到被治疗程度达到1500000或者最大血量与当前血量的差值时,治疗结束。
- 治疗他人未完成时重新发出治疗指令是无效的(无论是否要求治疗同一人)
- 治疗中断时,被治疗程度保留;被治疗者遭到攻击时被治疗程度清空

### 沉迷
#### 沉迷与唤醒
- 当求生者血量归零时,求生者自动原地进入沉迷状态,每毫秒增加1沉迷度
- 在被救时沉迷度不增加
- 该求生者可由其他的求生者救下,救下后,*血量恢复至1/2并可以重新行动*。沉迷程度不清空。
- 进入沉迷状态时,如果求生者原本沉迷程度在【10003,30000】中,求生者沉迷程度直接变为30000
- 当求生者沉迷程度达到该玩家最大沉迷程度(学生有的属性)时,从游戏中出局

### 救人
- 一般情况下,救人时间为1秒。
- 不能两人同时救一个人

## 得分

### 屠夫

#### 伤害得分
[Tricker对Student造成伤害时,得伤害*100/基本伤害(1500000)分。]

#### *[使用道具/技能得分]*

——需要造成一定效果才能获取分数,仅使用不得分

- 不同道具/技能有不同得分

#### 沉迷
使Student进入沉迷状态时,得50分。

#### 眩晕
使人类进入眩晕状态时,得25分。
- 该学生可由其他的求生者唤醒,唤醒后,血量恢复至1/2并可以重新行动。沉迷程度不清空。
- 一般情况下,唤醒时间为1秒。
- 进入沉迷状态时。如果求生者原本沉迷程度在(0,20900)中,求生者沉迷程度直接变为20900;如果求生者原本沉迷程度在【20900,40300)中,求生者沉迷程度直接变为40300;如果求生者原本沉迷程度大于40300,从游戏中出局;
- 当求生者沉迷程度达到该玩家最大沉迷程度时,从游戏中出局

#### 淘汰
每淘汰一个Student,得1000分

#### ~~主动/被动解除特殊状态得分(如解除眩晕)~~
~~解除眩晕,得15分~~

### 人类

#### 修机得分
- 人类每修n%的电机,得n分
- 修完一台电机,额外得?分

#### [牵制得分]

#### 使用道具/技能得分
- 不同道具/技能有不同得分

#### 使屠夫进入特殊状态得分(如使之眩晕)

#### 救人

#### 治疗

#### 逃脱
#### 门
- 门分别属于三个教学区:三教,五教,六教
- 需要拿到对应教学区的钥匙才能打开或锁住对应的门
- 钥匙只会出现在箱子中,每个教学区都有2把钥匙
- 当门所在格子内有人时,无法锁门
- 锁门时其他人可以进入门所在格子,锁门过程中断

#### ~~解除眩晕~~
#### 窗
- 通常情况下监管者翻越窗户的速度高于求生者。
- 有人正在翻越窗户时,其他玩家均不可以翻越该窗户。

#### ~~自愈~~
#### 箱子
- 开启箱子后将有2个随机道具掉落在玩家位置。
- 开启箱子的基础持续时间为10秒。
- 箱子道具不刷新

### 得分

#### 屠夫

- [Tricker对Student造成伤害时,得伤害*100/基本伤害(1500000)分。]
- *[使用道具/技能得分]*
- 需要造成一定效果才能获取分数,仅使用不得分
- 不同道具/技能有不同得分
- 使Student进入沉迷状态时,得50分。
- 使人类进入眩晕状态时,得25分。
- 每淘汰一个Student,得1000分
- 主动解除眩晕,得15分
- 开锁门

#### 人类
- 修机得分
- 人类每修n%的电机,得n分
- 修完一台电机,额外得?分
- [牵制得分]
- 使用道具/技能得分
- 不同道具/技能有不同得分
- 使屠夫进入特殊状态得分(如使之眩晕)
- 救人
- 治疗
- 逃脱
- 解除眩晕
- 开锁门

## 道具
- 每次玩家试图捡起道具时,需要确保道具栏有空位
- indexing指道具栏数组下标从0开始
- 扔道具
- Logic内实现
~~~csharp
public void ThrowProp(long playerID, int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序
- 使用道具
- Logic内实现
~~~csharp
public void UseProp(long playerID,int indexing)
~~~
- 对应下标出现空位,不会对数组进行重新排序

| 道具 | 对学生增益 | [学生得分条件] | 对搞蛋鬼增益 | [搞蛋鬼得分条件] |
| :-------- | :-------------------------------------- | :-----------------| :-------------------------------------- |:-----------------|
| Key3 | 能开启3教的门 |不得分| 能开启3教的门 |不得分|
@@ -195,177 +139,20 @@

### 捣蛋鬼
#### 刺客
~~~csharp
public class Assassin : IGhost
{
private const int moveSpeed = GameData.basicMoveSpeed * 473 / 380;
private const int maxHp = GameData.basicHp;

public BulletType InitBullet => BulletType.CommonAttackOfGhost;

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.BecomeInvisible, ActiveSkillType.UseKnife });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public double concealment = GameData.basicConcealment * 1.5;
public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.3);
public int viewRange = (int)(GameData.basicViewRange * 1.3);
public int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking;
public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows;
public int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
}
~~~
- 普通攻击为 CommonAttackOfGhost
~~~csharp
public CommonAttackOfGhost...
{
public override double BulletBombRange => 0;
public override double BulletAttackRange => GameData.basicAttackShortRange;
public 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 const int cd = GameData.basicBackswing;
public override bool CanBeBombed(GameObjType gameObjType)
{
switch (gameObjType)
{
case GameObjType.Character:
case GameObjType.Generator:
return true;
default:
return false;
}
}
}
~~~
- 主动技能
- 隐身
~~~csharp
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 6;
~~~
在DurationTime时间内玩家隐身
- 使用飞刀
~~~csharp
public int SkillCD => GameData.commonSkillCD* 2 / 3 ;
public int DurationTime => GameData.commonSkillTime / 10;
~~~
在DurationTime时间内,攻击类型变为飞刀
~~~csharp
internal sealed class FlyingKnife : Bullet
{
public override double BulletBombRange => 0;
public override double BulletAttackRange => GameData.basicRemoteAttackRange * 13;
public int ap = GameData.basicApOfGhost * 4 / 5;
public override int Speed => GameData.basicBulletMoveSpeed * 2;
public override bool IsToBomb => false;
public override int CastTime => GameData.basicCastTime;
public override int Backswing => GameData.basicBackswing * 2 / 5;
public override int RecoveryFromHit => GameData.basicBackswing * 3 / 4;
public const int cd = GameData.basicBackswing * 2 / 5 + 100;
public override bool CanBeBombed(GameObjType gameObjType)
{
if (gameObjType == GameObjType.Character) return true;
return false;
}
}
~~~

#### Klee
- 普通攻击为 CommonAttackOfGhost
~~~csharp
int moveSpeed = (int)(GameData.basicMoveSpeed * 155 / 127);
int maxHp = GameData.basicHp;
int maxBulletNum = 1;
BulletType InitBullet => BulletType.CommonAttackOfGhost;
List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb });
List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

double concealment = GameData.basicConcealment;
int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.069);
int viewRange = (int)(GameData.basicViewRange * 1.1);
int timeOfOpeningOrLocking = (int)(GameData.basicSpeedOfOpeningOrLocking / 1.1);
int speedOfClimbingThroughWindows = (int)(GameData.basicGhostSpeedOfClimbingThroughWindows / 1.1);
int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1);
~~~
- 主动技能
- 蹦蹦炸弹
~~~csharp
public int SkillCD => GameData.commonSkillCD / 30 * 5;
public int DurationTime => GameData.commonSkillTime / 2;
~~~
- 在DurationTime内,攻击类型变为蹦蹦炸弹
~~~csharp
internal sealed class BombBomb : Bullet
{
public override double BulletBombRange => GameData.basicBulletBombRange;
public override double BulletAttackRange => GameData.basicAttackShortRange;
public int ap = (int)(GameData.basicApOfGhost * 6.0 / 5);
public override int Speed => (int)(GameData.basicBulletMoveSpeed * 0.8);
public override bool IsRemoteAttack => false;

public override int CastTime => (int)BulletAttackRange / Speed;
public override int Backswing => 0;
public override int RecoveryFromHit => 0;
public const int cd = GameData.basicCD;

public override bool CanAttack(GameObj target)
{
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}
public override bool CanBeBombed(GameObjType gameObjType)
{
switch (gameObjType)
{
case GameObjType.Character:
case GameObjType.Generator:
return true;
default:
return false;
}
}
}
~~~
- 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上0°,90°,180°,270° 发出四个小炸弹
- 四个小炸弹只会因为碰撞爆炸,停止运动后学生碰撞会造成眩晕(AP / GameData.timeFactorOfGhostFainting)ms
~~~csharp
internal sealed class JumpyDumpty : Bullet
{
public override double BulletBombRange => GameData.basicBulletBombRange / 2;
public override double BulletAttackRange => GameData.basicAttackShortRange * 2;
public int ap = (int)(GameData.basicApOfGhost * 0.6);

public override int Speed => (int)(GameData.basicBulletMoveSpeed * 1.2);
public override bool IsRemoteAttack => false;

public override int CastTime => 0;
public override int Backswing => 0;
public override int RecoveryFromHit => 0;
public const int cd = 0;
public override int CD => cd;

public override bool CanAttack(GameObj target)
{
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}
public override bool CanBeBombed(GameObjType gameObjType)
{
switch (gameObjType)
{
case GameObjType.Character:
case GameObjType.Generator:
return true;
default:
return false;
}
}
}
~~~
- 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上90°,270° 发出2个小炸弹
- 2个小炸弹运动停止前会因为碰撞爆炸,停止运动后学生碰撞会造成眩晕(AP / GameData.timeFactorOfGhostFainting)ms

#### 喧哗者
- 主动技能
@@ -378,58 +165,13 @@
### 学生(&老师)

#### 运动员
~~~csharp
private const int moveSpeed = GameData.basicMoveSpeed * 40 / 38;
private const int maxHp = GameData.basicHp * 32 / 30;
public const int maxBulletNum = 0;
public BulletType InitBullet => BulletType.Null;
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.CanBeginToCharge });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });
public const int fixSpeed = GameData.basicFixSpeed * 6 / 10;
int treatSpeed = GameData.basicTreatSpeed * 8 / 10;
public const double concealment = GameData.basicConcealment * 0.9;
int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9);
int viewRange = (int)(GameData.basicViewRange * 1.1);
int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking * 12 / 10;
int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 12 / 10;
int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
~~~
- 主动技能
- 冲撞
~~~csharp
public int SkillCD => GameData.commonSkillCD / 5;
public int DurationTime => GameData.commonSkillTime * 6 / 10;
~~~
在DurationTime内,速度变为三倍,期间撞到捣蛋鬼,会导致捣蛋鬼眩晕7.22s,学生眩晕2.09s

#### 教师
~~~csharp
private const int moveSpeed = GameData.basicMoveSpeed * 3 / 4;
int maxHp = GameData.basicHp * 10;
int maxBulletNum = 0;
BulletType InitBullet => BulletType.Null;
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });
public const int fixSpeed = 0;
int treatSpeed = GameData.basicTreatSpeed;
double concealment = GameData.basicConcealment * 0.5;
int alertnessRadius = GameData.basicAlertnessRadius / 2;
int viewRange = GameData.basicViewRange * 9 / 10;
int timeOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking;
int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows /2;
int timeOfOpenChest = GameData.basicSpeedOfOpenChest;
~~~
- 主动技能
- 惩罚
~~~csharp
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => 0;
~~~
使用瞬间,在可视范围内的使用技能状态中、攻击前后摇的捣蛋鬼会被眩晕(3070)ms,
- 特性
教师无法获得牵制得分
@@ -438,7 +180,7 @@
- 被动技能
- 冥想
-当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为(GameData.basicFixSpeed / 4)/ms
-受到攻击或眩晕或翻窗(或攻击他人)学习进度清零
-受到攻击(并非伤害)或眩晕或翻窗(或攻击他人)学习进度清零
-主动技能
- 写答案
-使用瞬间,对于可互动范围内的一台电机增加这个学习进度
@@ -448,7 +190,49 @@
请自行查看Logic/Preparation/Utility/GameData.cs


## 游戏内的枚举类型、类与属性
## 细则

### 特殊说明
- 不加说明,这里“学生”往往包括职业“教师”

### 初始状态
- 所有玩家可以立刻使用主动技能
- 虽然一开始会接到仍需的冷却时间,但实际上是CD
- 玩家出生点固定且一定为空地

### 交互
- 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令
- 实际上救援或治疗不同的人是有效的

### 破译与逃脱
- 紧急出口与大门对于人有碰撞体积
- 一个大门同时最多可以由一人开启

### 攻击
- 每次求生者受到攻击后会损失对应子弹的攻击力的血量

### 沉迷与唤醒
- 在被救时沉迷度不增加
- 不能两人同时唤醒一个人

### 门
- 一扇门只允许同时一个人开锁门
- 开锁门未完成前,门状态表现为原来的状态
- 开锁门进度中断后清空

### 窗
- 攻击可以穿过窗,道具可以在窗上
- 翻越窗户是一种交互行为,翻窗一共有两个过程
- 跳上窗:从当前位置到窗边缘中点,位置瞬移,时间=距离/爬窗速度。中断时,停留在原位置
- 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心

### 箱子
- 同一时刻只允许一人进行开启
- 未开启完成的箱子在下一次需要重新开始开启。
- 箱子开启后其中道具才可以被观测和拿取


## 游戏内Logic底层的枚举类型、类与属性
- 底层实现中的属性,不代表界面全部都需要展示,也可能需要额外展示信息
- 只展示外部需要的属性,部分属性被省略

@@ -502,36 +286,6 @@
- 血量
- 最大血量
- 玩家状态(不可叠加)
~~~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(字典)
- 得分
- ~~回血率/原始回血率~~


Loading…
Cancel
Save