From db9f11dc0bf0dd6c52dd04d126b498327783e45f Mon Sep 17 00:00:00 2001
From: shangfengh <3495281661@qq.com>
Date: Mon, 10 Apr 2023 15:39:31 +0800
Subject: [PATCH] perf: :zap: add whatInteractingWith to make a great
optimization
---
.../GameClass/GameObj/Character/Character.cs | 55 +++++++++------
logic/GameClass/GameObj/Map/Chest.cs | 27 ++++---
logic/Gaming/ActionManager.cs | 70 ++++++++-----------
logic/Gaming/AttackManager.cs | 4 +-
logic/Gaming/CharacterManager .cs | 10 +--
logic/Gaming/PropManager.cs | 2 +-
.../SkillManager/SkillManager.ActiveSkill.cs | 27 ++++++-
logic/Preparation/Interface/ICharacter.cs | 2 +-
logic/Preparation/Interface/IOccupation.cs | 31 ++++++++
logic/Preparation/Interface/ISkill.cs | 19 ++++-
logic/Preparation/Utility/EnumType.cs | 1 +
logic/Server/CopyInfo.cs | 10 +--
logic/Server/GameServer.cs | 13 ++--
logic/规则Logic.md | 36 +++++-----
14 files changed, 191 insertions(+), 116 deletions(-)
diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs
index 78e81a4..7340b4f 100644
--- a/logic/GameClass/GameObj/Character/Character.cs
+++ b/logic/GameClass/GameObj/Character/Character.cs
@@ -300,14 +300,6 @@ namespace GameClass.GameObj
if (playerState == PlayerStateType.Null && IsMoving) return PlayerStateType.Moving;
return playerState;
}
- set
- {
- if (value != PlayerStateType.Moving)
- lock (gameObjLock)
- IsMoving = false;
-
- lock (gameObjLock) playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value;
- }
}
public bool NoHp() => (playerState == PlayerStateType.Deceased || playerState == PlayerStateType.Escaped
@@ -323,6 +315,38 @@ namespace GameClass.GameObj
|| playerState == PlayerStateType.Treated || playerState == PlayerStateType.Stunned
|| playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving);
+ private GameObj? whatInteractingWith = null;
+ public GameObj? WhatInteractingWith => whatInteractingWith;
+
+ public void SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
+ {
+ lock (gameObjLock)
+ {
+ switch (playerState)
+ {
+ case PlayerStateType.OpeningTheChest:
+ ((Chest)whatInteractingWith).StopOpen();
+ break;
+ default:
+ break;
+ }
+ whatInteractingWith = gameObj;
+ if (value != PlayerStateType.Moving)
+ IsMoving = false;
+ playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value;
+ //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString());
+ }
+ }
+
+ public void SetPlayerStateNaturally()
+ {
+ lock (gameObjLock)
+ {
+ whatInteractingWith = null;
+ playerState = PlayerStateType.Null;
+ }
+ }
+
private int score = 0;
public int Score
{
@@ -382,21 +406,6 @@ namespace GameClass.GameObj
}
}
}
- ///
- /// 角色携带的信息
- ///
- private string message = "THUAI6";
- public string Message
- {
- get => message;
- set
- {
- lock (gameObjLock)
- {
- message = value;
- }
- }
- }
#region 道具和buff相关属性、方法
private Prop[] propInventory = new Prop[GameData.maxNumOfPropInPropInventory]
diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs
index 23ee8d0..23d9571 100644
--- a/logic/GameClass/GameObj/Map/Chest.cs
+++ b/logic/GameClass/GameObj/Map/Chest.cs
@@ -20,20 +20,25 @@ namespace GameClass.GameObj
private Prop[] propInChest = new Prop[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() };
public Prop[] PropInChest => propInChest;
- private int openDegree = 0;
- public int OpenDegree
+ private int openStartTime = 0;
+ public int OpenStartTime => openStartTime;
+ private Character? whoOpen = null;
+ public Character? WhoOpen => whoOpen;
+ public void Open(int startTime, Character character)
{
- get => openDegree;
- set
+ lock (gameObjLock)
{
- if (value > 0)
- lock (gameObjLock)
- openDegree = (value > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : value;
- else
- lock (gameObjLock)
- openDegree = 0;
+ openStartTime = startTime;
+ whoOpen = character;
+ }
+ }
+ public void StopOpen()
+ {
+ lock (gameObjLock)
+ {
+ openStartTime = 0;
+ whoOpen = null;
}
}
- public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedChest);
}
}
diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs
index 875d1fd..a58efee 100644
--- a/logic/Gaming/ActionManager.cs
+++ b/logic/Gaming/ActionManager.cs
@@ -38,7 +38,7 @@ namespace Gaming
public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{
if (!playerToMove.Commandable()) return false;
- playerToMove.PlayerState = PlayerStateType.Moving;
+ playerToMove.SetPlayerState(PlayerStateType.Moving);
moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection);
return true;
}
@@ -47,7 +47,7 @@ namespace Gaming
{
if (player.Commandable())
{
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
return true;
}
return false;
@@ -63,7 +63,7 @@ namespace Gaming
return false;
++generatorForFix.NumOfFixing;
- player.PlayerState = PlayerStateType.Fixing;
+ player.SetPlayerState(PlayerStateType.Fixing);
new Thread
(
() =>
@@ -74,7 +74,7 @@ namespace Gaming
{
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
{
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
gameMap.NumOfRepairedGenerators++;
}
},
@@ -99,7 +99,7 @@ namespace Gaming
if (doorwayToOpen == null || doorwayToOpen.IsOpening || !doorwayToOpen.PowerSupply)
return false;
- player.PlayerState = PlayerStateType.OpeningTheDoorway;
+ player.SetPlayerState(PlayerStateType.OpeningTheDoorway);
doorwayToOpen.IsOpening = true;
new Thread
(
@@ -120,7 +120,7 @@ namespace Gaming
if (doorwayToOpen.OpenDegree >= GameData.degreeOfOpenedDoorway)
{
if (player.PlayerState == PlayerStateType.OpeningTheDoorway)
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
}
@@ -163,7 +163,7 @@ namespace Gaming
playerTreated = gameMap.StudentForInteract(player.Position);
if (playerTreated == null) return false;
}
- if (player == playerTreated || (!player.Commandable()) || player.PlayerState == PlayerStateType.Treating ||
+ if (player == playerTreated || (!player.Commandable()) || playerTreated.PlayerState == PlayerStateType.Treated ||
(!playerTreated.Commandable()) ||
playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position))
return false;
@@ -172,22 +172,22 @@ namespace Gaming
(
() =>
{
- playerTreated.PlayerState = PlayerStateType.Treated;
- player.PlayerState = PlayerStateType.Treating;
+ playerTreated.SetPlayerState(PlayerStateType.Treated);
+ player.SetPlayerState(PlayerStateType.Treating);
new FrameRateTaskExecutor(
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming,
loopToDo: () =>
{
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
- playerTreated.PlayerState = PlayerStateType.Null;
+ playerTreated.SetPlayerState();
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)
.Start();
- if (player.PlayerState == PlayerStateType.Treating) player.PlayerState = PlayerStateType.Null;
- else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.PlayerState = PlayerStateType.Null;
+ if (player.PlayerState == PlayerStateType.Treating) player.SetPlayerState();
+ else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState();
}
)
{ IsBackground = true }.Start();
@@ -200,11 +200,10 @@ namespace Gaming
playerRescued = gameMap.StudentForInteract(player.Position);
if (playerRescued == null) return false;
}
- if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || player == playerRescued
- || !GameData.ApproachToInteract(playerRescued.Position, player.Position) || playerRescued.TimeOfRescue > 0)
+ if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position))
return false;
- player.PlayerState = PlayerStateType.Rescuing;
- playerRescued.PlayerState = PlayerStateType.Rescued;
+ player.SetPlayerState(PlayerStateType.Rescuing);
+ playerRescued.SetPlayerState(PlayerStateType.Rescued);
new Thread
(
@@ -226,14 +225,14 @@ namespace Gaming
{
if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue)
{
- playerRescued.PlayerState = PlayerStateType.Null;
+ playerRescued.SetPlayerState();
playerRescued.HP = playerRescued.MaxHp / 2;
player.AddScore(GameData.StudentScoreRescue);
}
else
- playerRescued.PlayerState = PlayerStateType.Addicted;
+ playerRescued.SetPlayerState(PlayerStateType.Addicted);
}
- if (player.PlayerState == PlayerStateType.Rescuing) player.PlayerState = PlayerStateType.Null;
+ if (player.PlayerState == PlayerStateType.Rescuing) player.SetPlayerState();
playerRescued.TimeOfRescue = 0;
}
)
@@ -247,30 +246,21 @@ namespace Gaming
return false;
Chest? chestToOpen = (Chest?)gameMap.OneForInteract(player.Position, GameObjType.Chest);
- if (chestToOpen == null || chestToOpen.OpenDegree > 0)
+ if (chestToOpen == null || chestToOpen.OpenStartTime > 0)
return false;
- player.PlayerState = PlayerStateType.OpeningTheChest;
+ player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen);
+ int startTime = gameMap.Timer.nowTime();
+ chestToOpen.Open(startTime, player);
new Thread
(
() =>
{
- new FrameRateTaskExecutor(
- loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()),
- loopToDo: () =>
- {
- chestToOpen.OpenDegree += GameData.frameDuration * player.SpeedOfOpenChest;
- },
- timeInterval: GameData.frameDuration,
- finallyReturn: () => 0
- )
+ Thread.Sleep(GameData.degreeOfOpenedChest / player.SpeedOfOpenChest);
- .Start();
-
- if (chestToOpen.IsOpen())
+ if (chestToOpen.OpenStartTime == startTime)
{
- if (player.PlayerState == PlayerStateType.OpeningTheChest)
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerStateNaturally();
for (int i = 0; i < GameData.maxNumOfPropInChest; ++i)
{
Prop prop = chestToOpen.PropInChest[i];
@@ -279,8 +269,6 @@ namespace Gaming
gameMap.Add(prop);
}
}
- else chestToOpen.OpenDegree = 0;
-
}
)
@@ -312,7 +300,7 @@ namespace Gaming
//Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer);
// gameMap.Add(addWall);
- player.PlayerState = PlayerStateType.ClimbingThroughWindows;
+ player.SetPlayerState(PlayerStateType.ClimbingThroughWindows);
windowForClimb.WhoIsClimbing = player;
new Thread
(
@@ -354,7 +342,7 @@ namespace Gaming
// gameMap.Remove(addWall);
if (player.PlayerState == PlayerStateType.ClimbingThroughWindows)
{
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
}
@@ -394,7 +382,7 @@ namespace Gaming
}
if (!flag) return false;
- player.PlayerState = PlayerStateType.LockingOrOpeningTheDoor;
+ player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor);
new Thread
(
() =>
@@ -417,7 +405,7 @@ namespace Gaming
doorToLock.IsOpen = (!doorToLock.IsOpen);
}
if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor)
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
doorToLock.OpenOrLockDegree = 0;
}
diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs
index 1d77685..842d53a 100644
--- a/logic/Gaming/AttackManager.cs
+++ b/logic/Gaming/AttackManager.cs
@@ -174,7 +174,7 @@ namespace Gaming
if (bullet.CastTime > 0)
{
- player.PlayerState = PlayerStateType.TryingToAttack;
+ player.SetPlayerState(PlayerStateType.TryingToAttack);
new Thread
(() =>
@@ -195,7 +195,7 @@ namespace Gaming
{
if (player.PlayerState == PlayerStateType.TryingToAttack)
{
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
else
bullet.IsMoving = false;
diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs
index 8ec3d2c..5d0d062 100644
--- a/logic/Gaming/CharacterManager .cs
+++ b/logic/Gaming/CharacterManager .cs
@@ -216,7 +216,7 @@ namespace Gaming
return;
}
}
- player.PlayerState = PlayerStateType.Addicted;
+ player.SetPlayerState(PlayerStateType.Addicted);
new Thread
(() =>
{
@@ -252,10 +252,10 @@ namespace Gaming
new Thread
(() =>
{
- player.PlayerState = PlayerStateType.Stunned;
+ player.SetPlayerState(PlayerStateType.Stunned);
Thread.Sleep(time);
if (player.PlayerState == PlayerStateType.Stunned)
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
)
{ IsBackground = true }.Start();
@@ -341,7 +341,7 @@ namespace Gaming
{
if (player == null || time <= 0) return false;
if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false;
- player.PlayerState = PlayerStateType.Swinging;
+ player.SetPlayerState(PlayerStateType.Swinging);
new Thread
(() =>
@@ -350,7 +350,7 @@ namespace Gaming
if (player.PlayerState == PlayerStateType.Swinging)
{
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
}
)
diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs
index ac14bb1..3914b87 100644
--- a/logic/Gaming/PropManager.cs
+++ b/logic/Gaming/PropManager.cs
@@ -57,7 +57,7 @@ namespace Gaming
if (player.PlayerState == PlayerStateType.Stunned)
{
player.AddScore(GameData.ScorePropRecoverFromDizziness);
- player.PlayerState = PlayerStateType.Null;
+ player.SetPlayerState();
}
break;
default:
diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
index 2f2f72e..5496e79 100644
--- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
+++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
@@ -28,6 +28,31 @@ namespace Gaming
{ });
}
+ public static bool ShowTime(Character player)
+ {
+ if ((!player.Commandable())) return false;
+ IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime);
+ Debugger.Output(player, ": It's show time!");
+
+ return ActiveSkillEffect(skill, player, () =>
+ {
+ /* Thread
+ * new FrameRateTaskExecutor(
+ loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()),
+ loopToDo: () =>
+ {
+ chestToOpen.OpenStartTime += GameData.frameDuration * player.SpeedOfOpenChest;
+ },
+ timeInterval: GameData.frameDuration,
+ finallyReturn: () => 0
+ )
+
+ .Start();*/
+ },
+ () =>
+ { });
+ }
+
public static bool BecomeInvisible(Character player)
{
if ((!player.Commandable())) return false;
@@ -180,7 +205,7 @@ namespace Gaming
{
if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character))
{
- character.PlayerState = PlayerStateType.Null;
+ character.SetPlayerState();
character.HP = GameData.RemainHpWhenAddLife;
((Student)character).TimeOfRescue = 0;
player.AddScore(GameData.StudentScoreRescue);
diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs
index c4b175c..5975b8c 100644
--- a/logic/Preparation/Interface/ICharacter.cs
+++ b/logic/Preparation/Interface/ICharacter.cs
@@ -10,7 +10,7 @@ namespace Preparation.Interface
public int Score { get; }
public void AddScore(int add);
public double Vampire { get; }
- public PlayerStateType PlayerState { get; set; }
+ public PlayerStateType PlayerState { get; }
public BulletType BulletOfPlayer { get; set; }
public bool IsGhost();
diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs
index 3e3eb70..b37bda6 100644
--- a/logic/Preparation/Interface/IOccupation.cs
+++ b/logic/Preparation/Interface/IOccupation.cs
@@ -91,6 +91,37 @@ namespace Preparation.Interface
public int speedOfOpenChest = (int)(GameData.basicSpeedOfOpenChest * 1.1);
public int SpeedOfOpenChest => speedOfOpenChest;
}
+ public class Idol : IGhostType
+ {
+ private const int moveSpeed = GameData.basicGhostMoveSpeed;
+ public int MoveSpeed => moveSpeed;
+
+ private const int maxHp = GameData.basicHp;
+ public int MaxHp => maxHp;
+
+ public BulletType InitBullet => BulletType.CommonAttackOfGhost;
+
+ public List ListOfIActiveSkill => new(new ActiveSkillType[] { });
+ public List ListOfIPassiveSkill => new(new PassiveSkillType[] { });
+
+ public double concealment = GameData.basicConcealment;
+ public double Concealment => concealment;
+
+ public int alertnessRadius = GameData.basicGhostAlertnessRadius;
+ public int AlertnessRadius => alertnessRadius;
+
+ public int viewRange = GameData.basicGhostViewRange * 11 / 10;
+ public int ViewRange => viewRange;
+
+ public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking;
+ public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking;
+
+ public int speedOfClimbingThroughWindows = GameData.basicGhostSpeedOfClimbingThroughWindows;
+ public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows;
+
+ public int speedOfOpenChest = GameData.basicSpeedOfOpenChest;
+ public int SpeedOfOpenChest => speedOfOpenChest;
+ }
public class ANoisyPerson : IGhostType
{
private const int moveSpeed = (int)(GameData.basicGhostMoveSpeed * 1.07);
diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs
index f0a16f6..04950e8 100644
--- a/logic/Preparation/Interface/ISkill.cs
+++ b/logic/Preparation/Interface/ISkill.cs
@@ -33,7 +33,7 @@ namespace Preparation.Interface
public class BecomeInvisible : IActiveSkill
{
- public int SkillCD => GameData.commonSkillCD;
+ public int SkillCD => GameData.commonSkillCD * 2;
public int DurationTime => GameData.commonSkillTime * 6 / 10;
private readonly object commonSkillLock = new object();
@@ -121,6 +121,21 @@ namespace Preparation.Interface
}
}
+ public class ShowTime : IActiveSkill
+ {
+ public int SkillCD => GameData.commonSkillCD * 3;
+ public int DurationTime => GameData.commonSkillTime;
+
+ private readonly object commonSkillLock = new object();
+ public object ActiveSkillLock => commonSkillLock;
+
+ public bool isBeingUsed = false;
+ public bool IsBeingUsed
+ {
+ get => isBeingUsed; set => isBeingUsed = value;
+ }
+ }
+
public class JumpyBomb : IActiveSkill
{
public int SkillCD => GameData.commonSkillCD / 2;
@@ -137,7 +152,7 @@ namespace Preparation.Interface
public class UseKnife : IActiveSkill
{
- public int SkillCD => GameData.commonSkillCD * 2 / 3;
+ public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object ActiveSkillLock => commonSkillLock;
diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs
index cbc4028..fc9b4d7 100644
--- a/logic/Preparation/Utility/EnumType.cs
+++ b/logic/Preparation/Utility/EnumType.cs
@@ -100,6 +100,7 @@ namespace Preparation.Utility
Rouse = 11,
Encourage = 12,
Inspire = 13,
+ ShowTime = 14,
}
public enum PassiveSkillType
{
diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs
index 8cf0a76..a192063 100644
--- a/logic/Server/CopyInfo.cs
+++ b/logic/Server/CopyInfo.cs
@@ -3,13 +3,14 @@ using System.Collections.Generic;
using GameClass.GameObj;
using System.Numerics;
using Preparation.Utility;
+using Gaming;
namespace Server
{
public static class CopyInfo
{
- public static MessageOfObj? Auto(GameObj gameObj)
+ public static MessageOfObj? Auto(GameObj gameObj, int time)
{
switch (gameObj.Type)
{
@@ -29,7 +30,7 @@ namespace Server
case Preparation.Utility.GameObjType.Generator:
return Classroom((Generator)gameObj);
case Preparation.Utility.GameObjType.Chest:
- return Chest((Chest)gameObj);
+ return Chest((Chest)gameObj, time);
case Preparation.Utility.GameObjType.Doorway:
return Gate((Doorway)gameObj);
case Preparation.Utility.GameObjType.EmergencyExit:
@@ -223,13 +224,14 @@ namespace Server
msg.DoorMessage.IsOpen = door.IsOpen;
return msg;
}
- private static MessageOfObj Chest(Chest chest)
+ private static MessageOfObj Chest(Chest chest, int time)
{
MessageOfObj msg = new MessageOfObj();
msg.ChestMessage = new();
msg.ChestMessage.X = chest.Position.x;
msg.ChestMessage.Y = chest.Position.y;
- msg.ChestMessage.Progress = chest.OpenDegree;
+ int progress = (chest.OpenStartTime > 0) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0;
+ msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress;
return msg;
}
}
diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs
index c0a1abf..b997885 100644
--- a/logic/Server/GameServer.cs
+++ b/logic/Server/GameServer.cs
@@ -135,22 +135,23 @@ namespace Server
currentGameInfo.ObjMessage.Add(currentMapMsg);
IsSpectatorJoin = false;
}
+ int time = game.GameMap.Timer.nowTime();
foreach (GameObj gameObj in gameObjList)
{
- MessageOfObj? msg = CopyInfo.Auto(gameObj);
- if (msg != null) currentGameInfo.ObjMessage.Add(CopyInfo.Auto(gameObj));
+ MessageOfObj? msg = CopyInfo.Auto(gameObj, time);
+ if (msg != null) currentGameInfo.ObjMessage.Add(msg);
}
lock (newsLock)
{
foreach (var news in currentNews)
{
MessageOfObj? msg = CopyInfo.Auto(news);
- if (msg != null) currentGameInfo.ObjMessage.Add(CopyInfo.Auto(news));
+ if (msg != null) currentGameInfo.ObjMessage.Add(msg);
}
currentNews.Clear();
}
currentGameInfo.GameState = gameState;
- currentGameInfo.AllMessage = GetMessageOfAll();
+ currentGameInfo.AllMessage = GetMessageOfAll(time);
mwr?.WriteOne(currentGameInfo);
break;
default:
@@ -211,10 +212,10 @@ namespace Server
return false;
}
- private MessageOfAll GetMessageOfAll()
+ private MessageOfAll GetMessageOfAll(int time)
{
MessageOfAll msg = new MessageOfAll();
- msg.GameTime = game.GameMap.Timer.nowTime();
+ msg.GameTime = time;
msg.SubjectFinished = (int)game.GameMap.NumOfRepairedGenerators;
msg.StudentGraduated = (int)game.GameMap.NumOfEscapedStudent;
msg.StudentQuited = (int)game.GameMap.NumOfDeceasedStudent;
diff --git a/logic/规则Logic.md b/logic/规则Logic.md
index 7f9bbe0..af2fc86 100644
--- a/logic/规则Logic.md
+++ b/logic/规则Logic.md
@@ -8,10 +8,10 @@
- **极坐标以x坐标轴为极轴,角度逆时针为正方向**。
- 地图由50 * 50个格子构成,其中每个格子代表1000 * 1000的正方形。每个格子的编号(CellX,CellY)可以计算得到:
- 略
-- 地图上的每个格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子
+- 地图上格子有自己的区域类型:陆地、墙、草地、教室、校门、隐藏校门、门、窗、箱子
### 移动
-- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动的方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴**
+- `std::future Move(int64_t timeInMilliseconds, double angleInRadian)`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为x轴,水平向右方向为y轴**
### 使用技能
- `std::future UseSkill(int32_t skillID)`:使用对应序号的主动技能
@@ -20,6 +20,7 @@
- 人物半径为800
- 人物共有17种不可叠加的状态:
1. (可)移动状态
+- `std::future EndAllAction()`:可以使处在下者八项状态中的玩家终止交互
2. 学习
3. 被勉励
4. 在勉励
@@ -28,7 +29,7 @@
7. 使用技能
8. 开启校门
9. 唤醒他人中
-
+- 之后八项为不可行动状态
10. 被唤醒中
11. 沉迷
12. 退学
@@ -38,9 +39,6 @@
16. 后摇
17. 翻窗
-- 其中后8项为不可行动状态
-- `std::future EndAllAction()`:可以使处在2-9状态的玩家终止对应交互,对于后8项状态无效
-
### 攻击
- `std::future Attack(double angleInRadian)`:`angleInRadian`为攻击方向,无论近战远程均产生bullet表示攻击
- 攻击类型CommonAttackOfGhost攻击未写完的作业,会造成对应攻击力的损坏
@@ -67,17 +65,17 @@
- 每张地图都有10间教室,学生需要完成其中的**7间**教室的作业,才可以开启任意校门。
- `std::future StartLearning()`:在教室(旁)做作业
- `std::future StartOpenGate()`:开启校门,所需时间为18秒,开启的进度不清空
-- 隐藏校门会在**3间**教室的作业完成的情况下在3-5个隐藏校门刷新点之一随机显现,当学生只剩1名时,隐藏校门将会自动打开。
+- 当**3间**教室的作业完成时,隐藏校门在3-5个刷新点之一随机显现;当只剩1名学生时,隐藏校门自动打开。
- `std::future Graduate()`:从开启的校门或隐藏校门毕业。
#### 勉励(Treat)
-- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大血量与当前血量的差值时,勉励结束。
+- `std::future StartTreatMate(int64_t mateID)`:勉励对应玩家ID的学生,当达到被勉励程度达到1500000或者最大学习毅力与当前学习毅力的差值时,勉励完成,学生毅力增加对应被勉励程度。
- 勉励中断时,被勉励程度保留;遭到攻击时被勉励程度清空
#### 沉迷与唤醒
-- 当学生血量归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度
-- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后血量恢复至1/2。沉迷程度不清空。
-- 进入沉迷状态时。如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局;
+- 当学生学习毅力归零时,学生原地进入沉迷状态,每毫秒增加1沉迷度
+- `std::future StartRescueMate(int64_t mateID)`:唤醒对应玩家ID的沉迷的学生,需要时间1秒,之后学习毅力恢复至1/2。沉迷程度不清空。
+- 进入沉迷状态时,如果学生原沉迷程度在(0,该玩家最大沉迷度/3)中,沉迷程度直接变为其最大沉迷度/3;原沉迷程度在[其最大沉迷度/3,其最大沉迷度x2/3)中,沉迷程度直接变为其最大沉迷度x2/3;原沉迷程度大于其最大沉迷度x2/3,从游戏中出局;
- 当学生沉迷程度达到其最大沉迷程度时,从游戏中出局
#### 门
@@ -99,12 +97,12 @@
3. 学习的声音: 捣蛋鬼警戒半径内有人学习时收到;bgmVolume=(警戒半径x学习进度百分比)/二者距离
### 队内信息
-- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。`toPlayerID`指定发送的对象,`message`指定发送的内容。`message`的长度不能超过 64,否则将发送失败!
+- `std::future SendMessage(int64_t, std::string)`:给同队的队友发送消息。第一个参数指定发送的对象,第二个参数指定发送的内容。
- `bool HaveMessage()`:是否有队友发来的尚未接收的信息。
+- `std::pair GetMessage()`:从玩家ID为第一个参数的队友获取信息。
-### 信息受限
-- 主动行为每 50ms 最多总共可以调用 50 次;
-- `bool Wait()`:asynchronous 为 true 的情况下,选手可以调用此函数,阻塞当前线程,直到下一次消息更新时继续运行。
+### 线程控制
+- `bool Wait()`:阻塞当前线程,直到下一次消息更新时继续运行。
### 信息获取
`std::vector> GetStudents() const` :返回所有可视学生的信息。
@@ -189,11 +187,11 @@
- 普通攻击为 搞蛋鬼的一般攻击
- 主动技能
- 隐身
- - CD:30s 持续时间:6s
+ - CD:60s 持续时间:6s
- 在持续时间内玩家隐身
- 使用瞬间得分
- 使用飞刀
- - CD:20s 持续时间:1s
+ - CD:30s 持续时间:1s
- 在持续时间内,攻击类型变为飞刀
- 不直接得分
@@ -412,14 +410,14 @@ public:
### 交互
- 在指令仍在进行时,重复发出同一类型的交互指令是无效的,你需要先发出Stop指令终止进行的指令
- - 实际上救援或勉励不同的人是有效的
+ - 实际上唤醒或勉励不同的人是有效的
### 破译与逃脱
- 隐藏校门与校门对于人有碰撞体积
- 一个校门同时最多可以由一人开启
### 攻击
-- 每次学生受到攻击后会损失对应子弹的攻击力的血量
+- 每次学生受到攻击后会损失对应子弹的攻击力的学习毅力
- 前摇期间攻击被打断时,子弹消失。
- 此处,前摇指 从播放攻击动作开始 攻击者不能交互 的时间