Browse Source

fix: 🐛 add the attack of ClimbingWindows

tags/0.1.0
shangfengh 2 years ago
parent
commit
8317ac9ce5
12 changed files with 126 additions and 109 deletions
  1. +4
    -4
      logic/Client/MainWindow.xaml.cs
  2. +0
    -63
      logic/GameClass/GameObj/Character/Character.Student.cs
  3. +1
    -1
      logic/GameClass/GameObj/Character/Character.cs
  4. +22
    -7
      logic/Gaming/ActionManager.cs
  5. +1
    -14
      logic/Gaming/AttackManager.cs
  6. +76
    -1
      logic/Gaming/CharacterManager .cs
  7. +1
    -1
      logic/Gaming/Game.cs
  8. +2
    -2
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  9. +9
    -9
      logic/Preparation/Interface/IOccupation.cs
  10. +4
    -3
      logic/Preparation/Utility/GameData.cs
  11. +1
    -1
      logic/cmd/gameServer.cmd
  12. +5
    -3
      logic/规则Logic.md

+ 4
- 4
logic/Client/MainWindow.xaml.cs View File

@@ -976,7 +976,7 @@ namespace Client
MoveMsg msgW = new()
{
PlayerId = playerID,
TimeInMilliseconds = 50,
TimeInMilliseconds = 25,
Angle = Math.PI
};
client.Move(msgW);
@@ -986,7 +986,7 @@ namespace Client
MoveMsg msgS = new()
{
PlayerId = playerID,
TimeInMilliseconds = 50,
TimeInMilliseconds = 25,
Angle = 0
};
client.Move(msgS);
@@ -996,7 +996,7 @@ namespace Client
MoveMsg msgD = new()
{
PlayerId = playerID,
TimeInMilliseconds = 50,
TimeInMilliseconds = 25,
Angle = Math.PI / 2
};
client.Move(msgD);
@@ -1006,7 +1006,7 @@ namespace Client
MoveMsg msgA = new()
{
PlayerId = playerID,
TimeInMilliseconds = 50,
TimeInMilliseconds = 25,
Angle = 3 * Math.PI / 2
};
client.Move(msgA);


+ 0
- 63
logic/GameClass/GameObj/Character/Character.Student.cs View File

@@ -6,69 +6,6 @@ namespace GameClass.GameObj
{
public class Student : Character
{
/// <summary>
/// 遭受攻击
/// </summary>
/// <param name="subHP"></param>
/// <param name="hasSpear"></param>
/// <param name="attacker">伤害来源</param>
/// <returns>人物在受到攻击后死了吗</returns>
public bool BeAttacked(Bullet bullet)
{
#if DEBUG
Debugger.Output(this, "is being shot!");
#endif
lock (beAttackedLock)
{
if (hp <= 0 || NoHp())
return false; // 原来已经死了
if (bullet.Parent.IsGhost() != this.IsGhost())
{
#if DEBUG
Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString());
#endif
if (TryUseShield())
{
if (bullet.HasSpear)
{
int subHp = TrySubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + HP.ToString());
#endif
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear);
bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
}
else
return false;
}
else
{
int subHp;
if (bullet.HasSpear)
{
subHp = TrySubHp(bullet.AP + GameData.ApSpearAdd);
#if DEBUG
Debugger.Output(this, "is being shot with Spear! Now his hp is" + HP.ToString());
#endif
}
else
{
subHp = TrySubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + HP.ToString());
#endif
}
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp));
bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
}

if (hp <= 0)
TryActivatingLIFE(); // 如果有复活甲
}
return hp <= 0;
}
}

protected int fixSpeed;
/// <summary>
/// 修理电机速度


+ 1
- 1
logic/GameClass/GameObj/Character/Character.cs View File

@@ -541,7 +541,7 @@ namespace GameClass.GameObj
return false;
}
}
protected void TryActivatingLIFE()
public void TryActivatingLIFE()
{
if (buffManager.TryActivatingLIFE())
{


+ 22
- 7
logic/Gaming/ActionManager.cs View File

@@ -164,7 +164,7 @@ namespace Gaming
{
if (!(player.Commandable()) || player.CharacterType == CharacterType.Robot)
return false;
Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteractInACross(player.Position, GameObjType.Doorway);
Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway);
if (doorwayForEscape != null && doorwayForEscape.IsOpen())
{
player.AddScore(GameData.StudentScoreEscape);
@@ -174,7 +174,7 @@ namespace Gaming
}
else
{
EmergencyExit? emergencyExit = (EmergencyExit?)gameMap.OneForInteractInACross(player.Position, GameObjType.EmergencyExit);
EmergencyExit? emergencyExit = (EmergencyExit?)gameMap.OneForInteract(player.Position, GameObjType.EmergencyExit);
if (emergencyExit != null && emergencyExit.IsOpen)
{
++gameMap.NumOfEscapedStudent;
@@ -353,12 +353,23 @@ namespace Gaming
if (windowForClimb == null || windowForClimb.WhoIsClimbing != null)
return false;

XY windowToPlayer = new(
(Math.Abs(player.Position.x - windowForClimb.Position.x) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.x > windowForClimb.Position.x ? 1 : -1)) : 0,
(Math.Abs(player.Position.y - windowForClimb.Position.y) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.y > windowForClimb.Position.y ? 1 : -1)) : 0);

Character? characterInWindow = (Character?)gameMap.OneInTheSameCell(windowForClimb.Position - 2 * windowToPlayer, GameObjType.Character);
if (characterInWindow != null)
{
if (player.IsGhost() && !characterInWindow.IsGhost())
characterManager.BeAttacked((Student)(characterInWindow), player.Attack(characterInWindow.Position, PlaceType.Null));
return false;
}

Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer);
gameMap.Add(addWall);

player.PlayerState = PlayerStateType.ClimbingThroughWindows;
windowForClimb.WhoIsClimbing = player;
XY windowToPlayer = new XY(
(Math.Abs(player.Position.x - windowForClimb.Position.x) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.x > windowForClimb.Position.x ? 1 : -1)) : 0,
(Math.Abs(player.Position.y - windowForClimb.Position.y) > GameData.numOfPosGridPerCell / 2) ? (GameData.numOfPosGridPerCell / 2 * (player.Position.y > windowForClimb.Position.y ? 1 : -1)) : 0)
;
new Thread
(
() =>
@@ -396,6 +407,7 @@ namespace Gaming
player.ReSetPos(PosJumpOff, gameMap.GetPlaceType(PosJumpOff));
player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed);
windowForClimb.WhoIsClimbing = null;
gameMap.Remove(addWall);
if (player.PlayerState == PlayerStateType.ClimbingThroughWindows)
{
player.PlayerState = PlayerStateType.Null;
@@ -494,10 +506,12 @@ namespace Gaming
*/

private readonly Map gameMap;
private readonly CharacterManager characterManager;
public readonly MoveEngine moveEngine;
public ActionManager(Map gameMap)
public ActionManager(Map gameMap, CharacterManager characterManager)
{
this.gameMap = gameMap;

this.moveEngine = new MoveEngine(
gameMap: gameMap,
OnCollision: (obj, collisionObj, moveVec) =>
@@ -516,6 +530,7 @@ namespace Gaming
// Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);
}
);
this.characterManager = characterManager;
}
}
}


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

@@ -50,20 +50,7 @@ namespace Gaming

if ((!(((Character)objBeingShot).IsGhost())) && bullet.Parent.IsGhost())
{
Student whoBeAttacked = (Student)objBeingShot;
if (whoBeAttacked.CharacterType == CharacterType.StraightAStudent)
{
((WriteAnswers)whoBeAttacked.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0;
}
if (whoBeAttacked.BeAttacked(bullet))
{
characterManager.BeAddictedToGame(whoBeAttacked, (Ghost)bullet.Parent);
}
if (whoBeAttacked.CanBeAwed())
{
if (CharacterManager.BeStunned(whoBeAttacked, GameData.basicStunnedTimeOfStudent))
bullet.Parent.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent));
}
characterManager.BeAttacked((Student)objBeingShot, bullet);
}
// if (((Character)objBeingShot).IsGhost() && !bullet.Parent.IsGhost() && bullet.TypeOfBullet == BulletType.Ram)
// BeStunned((Character)objBeingShot, bullet.AP);


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

@@ -134,7 +134,7 @@ namespace Gaming
{
if (!noise && XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment))
newPlayer.AddBgm(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position));
if (XY.Distance(newPlayer.Position, person.Position) <= GameData.basicViewRange)
if (newPlayer.CharacterType != CharacterType.Teacher && XY.Distance(newPlayer.Position, person.Position) <= GameData.basicViewRange)
{
TimePinningDown += GameData.checkInterval;
newPlayer.AddScore(GameData.StudentScorePinDown(TimePinningDown) - ScoreAdded);
@@ -250,6 +250,81 @@ namespace Gaming
{ IsBackground = true }.Start();
return true;
}

public static bool TryBeAwed(Student character, Bullet bullet)
{
if (character.CanBeAwed())
{
if (BeStunned(character, GameData.basicStunnedTimeOfStudent))
bullet.Parent.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent));
return true;
}
return false;
}

/// <summary>
/// 遭受攻击
/// </summary>
/// <param name="subHP"></param>
/// <param name="hasSpear"></param>
/// <param name="attacker">伤害来源</param>
/// <returns>人物在受到攻击后死了吗</returns>
public void BeAttacked(Student student, Bullet bullet)
{
#if DEBUG
Debugger.Output(student, "is being shot!");
#endif
if (student.NoHp()) return; // 原来已经死了
if (!bullet.Parent.IsGhost()) return;

if (student.CharacterType == CharacterType.StraightAStudent)
{
((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0;
}
#if DEBUG
Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString());
#endif
if (student.TryUseShield())
{
if (bullet.HasSpear)
{
int subHp = student.TrySubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear);
bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
}
else return;
}
else
{
int subHp;
if (bullet.HasSpear)
{
subHp = student.TrySubHp(bullet.AP + GameData.ApSpearAdd);
#if DEBUG
Debugger.Output(this, "is being shot with Spear! Now his hp is" + student.HP.ToString());
#endif
}
else
{
subHp = student.TrySubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
}
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp));
bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
}
if (student.HP <= 0)
student.TryActivatingLIFE(); // 如果有复活甲

if (student.HP <= 0)
BeAddictedToGame(student, (Ghost)bullet.Parent);
else TryBeAwed(student, bullet);
}

public static bool BackSwing(Character? player, int time)
{
if (player == null || time <= 0) return false;


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

@@ -393,7 +393,7 @@ namespace Gaming

characterManager = new CharacterManager(gameMap);
attackManager = new AttackManager(gameMap, characterManager);
actionManager = new ActionManager(gameMap);
actionManager = new ActionManager(gameMap, characterManager);
propManager = new PropManager(gameMap);
skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager, characterManager);
}


+ 2
- 2
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -147,10 +147,10 @@ namespace Gaming
{
if (character.IsGhost() &&
(character.PlayerState == PlayerStateType.TryingToAttack || character.PlayerState == PlayerStateType.Swinging
|| character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.OpeningTheChest)
|| character.PlayerState == PlayerStateType.UsingSkill)
&& gameMap.CanSee(player, character))
{
if (CharacterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting))
if (CharacterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish))
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish + (player.MaxHp - player.HP) / GameData.timeFactorOfGhostFainting));
break;
}


+ 9
- 9
logic/Preparation/Interface/IOccupation.cs View File

@@ -31,7 +31,7 @@ namespace Preparation.Interface

public class Assassin : IGhost
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 473.0 / 380);
private const int moveSpeed = (int)(GameData.basicGhostMoveSpeed * 1.1);
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
@@ -62,7 +62,7 @@ namespace Preparation.Interface
}
public class Klee : IGhost
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 155 / 127);
private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 155 / 127);
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
@@ -93,7 +93,7 @@ namespace Preparation.Interface
}
public class ANoisyPerson : IGhost
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 1.1);
private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 1.07);
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp * 12 / 10;
@@ -124,7 +124,7 @@ namespace Preparation.Interface
}
public class Teacher : IStudent
{
private const int moveSpeed = GameData.basicMoveSpeed * 3 / 4;
private const int moveSpeed = GameData.basicStudentMoveSpeed * 3 / 4;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp * 10;
@@ -164,7 +164,7 @@ namespace Preparation.Interface
}
public class Athlete : IStudent
{
private const int moveSpeed = GameData.basicMoveSpeed * 40 / 38;
private const int moveSpeed = GameData.basicStudentMoveSpeed * 40 / 38;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp * 32 / 30;
@@ -204,7 +204,7 @@ namespace Preparation.Interface
}
public class StraightAStudent : IStudent
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 0.8);
private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 0.8);
public int MoveSpeed => moveSpeed;

private const int maxHp = (int)(GameData.basicHp * 1.1);
@@ -244,7 +244,7 @@ namespace Preparation.Interface
}
public class Robot : IStudent
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed);
private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed);
public int MoveSpeed => moveSpeed;

private const int maxHp = (int)(GameData.basicHp / 2.5);
@@ -284,7 +284,7 @@ namespace Preparation.Interface
}
public class TechOtaku : IStudent
{
private const int moveSpeed = (int)(GameData.basicMoveSpeed * 0.75);
private const int moveSpeed = (int)(GameData.basicStudentMoveSpeed * 0.75);
public int MoveSpeed => moveSpeed;

private const int maxHp = (int)(GameData.basicHp * 0.9);
@@ -324,7 +324,7 @@ namespace Preparation.Interface
}
public class Sunshine : IStudent
{
private const int moveSpeed = GameData.basicMoveSpeed;
private const int moveSpeed = GameData.basicStudentMoveSpeed;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp * 32 / 30;


+ 4
- 3
logic/Preparation/Utility/GameData.cs View File

@@ -97,10 +97,11 @@ namespace Preparation.Utility
public const int basicTimeOfRescue = 1000;

#if DEBUG
public const int basicMoveSpeed = 9000;// 基本移动速度,单位:s-1
public const int basicStudentMoveSpeed = 9000;// 基本移动速度,单位:s-1
#else
public const int basicMoveSpeed = 1270;
public const int basicStudentMoveSpeed = 1270;
#endif
public const int basicGhostMoveSpeed = (int)(basicStudentMoveSpeed * 45.0 / 38);

public const int characterMaxSpeed = 12000; // 最大速度

@@ -181,7 +182,7 @@ namespace Preparation.Utility

public const int basicBulletMoveSpeed = 1800; // 基本子弹移动速度,单位:s-1
public const double basicRemoteAttackRange = 3000; // 基本远程攻击范围
public const double basicAttackShortRange = 900; // 基本近程攻击范围
public const double basicAttackShortRange = 1100; // 基本近程攻击范围
public const double basicBulletBombRange = 1000; // 基本子弹爆炸范围
#endregion
#region 技能相关


+ 1
- 1
logic/cmd/gameServer.cmd View File

@@ -1,6 +1,6 @@
@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



+ 5
- 3
logic/规则Logic.md View File

@@ -25,8 +25,8 @@
- 地图上的每个格子有自己的区域类型:墙、草地、电机、出口、紧急出口、门、窗、箱子

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

### 破译与逃脱
- 每张地图都有10台电机,求生者需要破译其中的7台,并开启任意一个大门(总所需时间为18秒)后从任意一个开启的大门逃脱,亦或者在只剩1名求生者的情况下从紧急出口逃脱;
@@ -430,7 +430,9 @@
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => 0;
~~~
使用瞬间,在可视范围内的使用技能状态中、攻击前后摇、开锁门、开箱的捣蛋鬼会被眩晕(3070+ 玩家损失的血量 / 1000)ms,
使用瞬间,在可视范围内的使用技能状态中、攻击前后摇的捣蛋鬼会被眩晕(3070)ms,
- 特性
教师无法获得牵制得分

#### 学霸
- 被动技能


Loading…
Cancel
Save