Browse Source

Merge pull request #257 from shangfengh/new

perf: 🔒 add a limit of call the Stop or Move fuction
tags/0.1.0
Gao Siyan GitHub 2 years ago
parent
commit
d34aecc614
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 313 additions and 206 deletions
  1. +1
    -1
      dependency/proto/MessageType.proto
  2. +1
    -1
      logic/Client/MainWindow.xaml.cs
  3. +2
    -2
      logic/Client/StatusBarOfHunter.xaml.cs
  4. +1
    -9
      logic/GameClass/GameObj/Character/Character.cs
  5. +5
    -5
      logic/GameClass/GameObj/Map/Doorway.cs
  6. +59
    -42
      logic/Gaming/ActionManager.cs
  7. +6
    -6
      logic/Gaming/AttackManager.cs
  8. +26
    -8
      logic/Gaming/CharacterManager .cs
  9. +3
    -3
      logic/Gaming/Game.cs
  10. +5
    -4
      logic/Gaming/PropManager.cs
  11. +41
    -18
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  12. +3
    -0
      logic/Gaming/SkillManager/SkillManager.cs
  13. +4
    -2
      logic/Preparation/Interface/IOccupation.cs
  14. +5
    -1
      logic/Preparation/Interface/ISkill.cs
  15. +1
    -0
      logic/Preparation/Utility/EnumType.cs
  16. +3
    -0
      logic/Preparation/Utility/GameData.cs
  17. +4
    -0
      logic/Preparation/Utility/Transformation.cs
  18. +1
    -4
      logic/Preparation/Utility/XY.cs
  19. +140
    -99
      logic/Server/CopyInfo.cs
  20. +2
    -1
      logic/规则Logic.md

+ 1
- 1
dependency/proto/MessageType.proto View File

@@ -118,7 +118,7 @@ enum TrickerType
ASSASSIN = 1;
KLEE = 2;
A_NOISY_PERSON = 3;
TRICKERTYPE4 = 4;
IDOL = 4;
}

// 游戏进行状态


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

@@ -241,7 +241,7 @@ namespace Client
playerMsg.TrickerType = TrickerType.ANoisyPerson;
break;
case 4:
playerMsg.TrickerType = TrickerType._4;
playerMsg.TrickerType = TrickerType.Idol;
break;
case 0:
default:


+ 2
- 2
logic/Client/StatusBarOfHunter.xaml.cs View File

@@ -49,8 +49,8 @@ namespace Client
case TrickerType.ANoisyPerson:
serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nANoisyPerson";
break;
case TrickerType._4:
serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nTrickerType4";
case TrickerType.Idol:
serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nIdol";
break;
case TrickerType.NullTrickerType:
serial.Text = "👥" + Convert.ToString(1) + "👻" + Convert.ToString(obj.PlayerId) + "\nNullTrickerType";


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

@@ -318,18 +318,10 @@ namespace GameClass.GameObj
private GameObj? whatInteractingWith = null;
public GameObj? WhatInteractingWith => whatInteractingWith;

public void SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
public void ChangePlayerState(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;


+ 5
- 5
logic/GameClass/GameObj/Map/Doorway.cs View File

@@ -35,14 +35,14 @@ namespace GameClass.GameObj
}
}

private bool isOpening = false;
public bool IsOpening
private int openStartTime = 0;
public int OpenStartTime
{
get => isOpening;
get => openStartTime;
set
{
lock (gameObjLock)
isOpening = value;
openStartTime = value;
}
}

@@ -61,6 +61,6 @@ namespace GameClass.GameObj
}
}

public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway);
public bool IsOpen() => (openDegree == GameData.degreeOfOpenedDoorway);
}
}

+ 59
- 42
logic/Gaming/ActionManager.cs View File

@@ -23,31 +23,31 @@ namespace Gaming
{
if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty)
{
if (CharacterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty))
if (characterManager.BeStunned((Character)player, GameData.TimeOfStunnedWhenJumpyDumpty))
player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStunnedWhenJumpyDumpty));
gameMap.Remove((GameObj)collisionObj);
}
}
if (player.FindIActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost())
{
if (CharacterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge))
if (characterManager.BeStunned((Character)collisionObj, GameData.TimeOfGhostFaintingWhenCharge))
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenCharge));
CharacterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge);
characterManager.BeStunned(player, GameData.TimeOfStudentFaintingWhenCharge);
}
}
public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{
if (!playerToMove.Commandable()) return false;
playerToMove.SetPlayerState(PlayerStateType.Moving);
if (!playerToMove.Commandable() || !TryToStop()) return false;
characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving);
moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection);
return true;
}

public static bool Stop(Character player)
public bool Stop(Character player)
{
if (player.Commandable())
if (player.Commandable() || !TryToStop())
{
player.SetPlayerState();
characterManager.SetPlayerState(player);
return true;
}
return false;
@@ -63,7 +63,7 @@ namespace Gaming
return false;

++generatorForFix.NumOfFixing;
player.SetPlayerState(PlayerStateType.Fixing);
characterManager.SetPlayerState(player, PlayerStateType.Fixing);
new Thread
(
() =>
@@ -74,7 +74,7 @@ namespace Gaming
{
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
{
player.SetPlayerState();
characterManager.SetPlayerState(player);
gameMap.NumOfRepairedGenerators++;
}
},
@@ -96,31 +96,21 @@ namespace Gaming
if (!(player.Commandable()) || player.PlayerState == PlayerStateType.OpeningTheDoorway)
return false;
Doorway? doorwayToOpen = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway);
if (doorwayToOpen == null || doorwayToOpen.IsOpening || !doorwayToOpen.PowerSupply)
if (doorwayToOpen == null || doorwayToOpen.OpenStartTime > 0 || !doorwayToOpen.PowerSupply)
return false;

player.SetPlayerState(PlayerStateType.OpeningTheDoorway);
doorwayToOpen.IsOpening = true;
characterManager.SetPlayerState(player, PlayerStateType.OpeningTheDoorway, doorwayToOpen);
int startTime = doorwayToOpen.OpenStartTime = gameMap.Timer.nowTime();
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheDoorway && gameMap.Timer.IsGaming && doorwayToOpen.OpenDegree < GameData.degreeOfOpenedDoorway,
loopToDo: () =>
{
doorwayToOpen.OpenDegree += GameData.frameDuration;
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)
Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree);

.Start();
doorwayToOpen.IsOpening = false;
if (doorwayToOpen.OpenDegree >= GameData.degreeOfOpenedDoorway)
if (doorwayToOpen.OpenStartTime == startTime)
{
if (player.PlayerState == PlayerStateType.OpeningTheDoorway)
player.SetPlayerState();
doorwayToOpen.OpenDegree = GameData.degreeOfOpenedDoorway;
player.SetPlayerStateNaturally();
}
}

@@ -172,22 +162,22 @@ namespace Gaming
(
() =>
{
playerTreated.SetPlayerState(PlayerStateType.Treated);
player.SetPlayerState(PlayerStateType.Treating);
characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated);
characterManager.SetPlayerState(player, PlayerStateType.Treating);
new FrameRateTaskExecutor<int>(
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming,
loopToDo: () =>
{
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
playerTreated.SetPlayerState();
characterManager.SetPlayerState(playerTreated);
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)
.Start();

if (player.PlayerState == PlayerStateType.Treating) player.SetPlayerState();
else if (playerTreated.PlayerState == PlayerStateType.Treated) playerTreated.SetPlayerState();
if (player.PlayerState == PlayerStateType.Treating) characterManager.SetPlayerState(player);
else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated);
}
)
{ IsBackground = true }.Start();
@@ -202,8 +192,8 @@ namespace Gaming
}
if ((!player.Commandable()) || playerRescued.PlayerState != PlayerStateType.Addicted || !GameData.ApproachToInteract(playerRescued.Position, player.Position))
return false;
player.SetPlayerState(PlayerStateType.Rescuing);
playerRescued.SetPlayerState(PlayerStateType.Rescued);
characterManager.SetPlayerState(player, PlayerStateType.Rescuing);
characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued);

new Thread
(
@@ -225,14 +215,14 @@ namespace Gaming
{
if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue)
{
playerRescued.SetPlayerState();
characterManager.SetPlayerState(playerRescued);
playerRescued.HP = playerRescued.MaxHp / 2;
player.AddScore(GameData.StudentScoreRescue);
}
else
playerRescued.SetPlayerState(PlayerStateType.Addicted);
characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted);
}
if (player.PlayerState == PlayerStateType.Rescuing) player.SetPlayerState();
if (player.PlayerState == PlayerStateType.Rescuing) characterManager.SetPlayerState(player);
playerRescued.TimeOfRescue = 0;
}
)
@@ -249,7 +239,7 @@ namespace Gaming
if (chestToOpen == null || chestToOpen.OpenStartTime > 0)
return false;

player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen);
characterManager.SetPlayerState(player, PlayerStateType.OpeningTheChest, chestToOpen);
int startTime = gameMap.Timer.nowTime();
chestToOpen.Open(startTime, player);
new Thread
@@ -300,7 +290,7 @@ namespace Gaming
//Wall addWall = new Wall(windowForClimb.Position - 2 * windowToPlayer);
// gameMap.Add(addWall);

player.SetPlayerState(PlayerStateType.ClimbingThroughWindows);
characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows);
windowForClimb.WhoIsClimbing = player;
new Thread
(
@@ -342,7 +332,7 @@ namespace Gaming
// gameMap.Remove(addWall);
if (player.PlayerState == PlayerStateType.ClimbingThroughWindows)
{
player.SetPlayerState();
characterManager.SetPlayerState(player);
}
}

@@ -382,7 +372,7 @@ namespace Gaming
}
if (!flag) return false;

player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor);
characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor);
new Thread
(
() =>
@@ -405,7 +395,7 @@ namespace Gaming
doorToLock.IsOpen = (!doorToLock.IsOpen);
}
if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor)
player.SetPlayerState();
characterManager.SetPlayerState(player);
doorToLock.OpenOrLockDegree = 0;
}

@@ -437,6 +427,33 @@ namespace Gaming
}
}
*/
private object numLock = new object();
private int lastTime = 0;
private int numStop = 0;
private int NumStop => numStop;
private bool TryToStop()
{
lock (numLock)
{
int time = gameMap.Timer.nowTime();
if (time / GameData.frameDuration > lastTime)
{
lastTime = time / GameData.frameDuration;
numStop = 1;
return true;
}
else
{
if (numStop == GameData.LimitOfStopAndMove)
return false;
else
{
++numStop;
return true;
}
}
}
}

private readonly Map gameMap;
private readonly CharacterManager characterManager;


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

@@ -81,14 +81,14 @@ namespace Gaming
{
if (objBeingShot == null)
{
CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing);
characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing);
return;
}

Debugger.Output(bullet, bullet.TypeOfBullet.ToString());

BombObj(bullet, objBeingShot);
CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit);
characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit);
return;
}

@@ -140,10 +140,10 @@ namespace Gaming

if (objBeingShot == null)
{
CharacterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing);
characterManager.BackSwing((Character?)bullet.Parent, bullet.Backswing);
}
else
CharacterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit);
characterManager.BackSwing((Character?)bullet.Parent, bullet.RecoveryFromHit);
}

public bool Attack(Character? player, double angle)
@@ -174,7 +174,7 @@ namespace Gaming

if (bullet.CastTime > 0)
{
player.SetPlayerState(PlayerStateType.TryingToAttack);
characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack);

new Thread
(() =>
@@ -195,7 +195,7 @@ namespace Gaming
{
if (player.PlayerState == PlayerStateType.TryingToAttack)
{
player.SetPlayerState();
characterManager.SetPlayerState(player);
}
else
bullet.IsMoving = false;


+ 26
- 8
logic/Gaming/CharacterManager .cs View File

@@ -7,6 +7,7 @@ using GameEngine;
using Preparation.Interface;
using Timothy.FrameRateTask;
using System.Numerics;
using System.Timers;

namespace Gaming
{
@@ -21,6 +22,23 @@ namespace Gaming
this.gameMap = gameMap;
}

public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
switch (player.PlayerState)
{
case PlayerStateType.OpeningTheChest:
((Chest)player.WhatInteractingWith).StopOpen();
break;
case PlayerStateType.OpeningTheDoorway:
Doorway doorway = (Doorway)player.WhatInteractingWith;
doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime;
doorway.OpenStartTime = 0;
break;
default:
break;
}
player.ChangePlayerState(value, gameObj);
}

public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null)
{
@@ -216,7 +234,7 @@ namespace Gaming
return;
}
}
player.SetPlayerState(PlayerStateType.Addicted);
SetPlayerState(player, PlayerStateType.Addicted);
new Thread
(() =>
{
@@ -246,23 +264,23 @@ namespace Gaming
{ IsBackground = true }.Start();
}

public static bool BeStunned(Character player, int time)
public bool BeStunned(Character player, int time)
{
if (player.PlayerState == PlayerStateType.Stunned || player.NoHp() || player.CharacterType == CharacterType.Robot) return false;
new Thread
(() =>
{
player.SetPlayerState(PlayerStateType.Stunned);
SetPlayerState(player, PlayerStateType.Stunned);
Thread.Sleep(time);
if (player.PlayerState == PlayerStateType.Stunned)
player.SetPlayerState();
SetPlayerState(player);
}
)
{ IsBackground = true }.Start();
return true;
}

public static bool TryBeAwed(Student character, Bullet bullet)
public bool TryBeAwed(Student character, Bullet bullet)
{
if (character.CanBeAwed())
{
@@ -337,11 +355,11 @@ namespace Gaming
else TryBeAwed(student, bullet);
}

public static bool BackSwing(Character? player, int time)
public bool BackSwing(Character? player, int time)
{
if (player == null || time <= 0) return false;
if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false;
player.SetPlayerState(PlayerStateType.Swinging);
SetPlayerState(player, PlayerStateType.Swinging);

new Thread
(() =>
@@ -350,7 +368,7 @@ namespace Gaming

if (player.PlayerState == PlayerStateType.Swinging)
{
player.SetPlayerState();
SetPlayerState(player);
}
}
)


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

@@ -167,7 +167,7 @@ namespace Gaming
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
return ActionManager.Stop(player);
return actionManager.Stop(player);
}
return false;
}
@@ -233,7 +233,7 @@ namespace Gaming
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
PropManager.UseProp(player, propType);
propManager.UseProp(player, propType);
}
}
public void ThrowProp(long playerID, PropType propType = PropType.Null)
@@ -375,7 +375,7 @@ namespace Gaming
characterManager = new CharacterManager(gameMap);
attackManager = new AttackManager(gameMap, characterManager);
actionManager = new ActionManager(gameMap, characterManager);
propManager = new PropManager(gameMap);
propManager = new PropManager(gameMap, characterManager);
skillManager = new SkillManager(gameMap, actionManager, attackManager, propManager, characterManager);
}
}


+ 5
- 4
logic/Gaming/PropManager.cs View File

@@ -16,10 +16,10 @@ namespace Gaming
private class PropManager
{
private readonly Map gameMap;
private readonly CharacterManager characterManager;
private readonly List<XY> availableCellForGenerateProp;

public static void UseProp(Character player, PropType propType)
public void UseProp(Character player, PropType propType)
{
if (player.IsResetting || player.CharacterType == CharacterType.Robot)
return;
@@ -57,7 +57,7 @@ namespace Gaming
if (player.PlayerState == PlayerStateType.Stunned)
{
player.AddScore(GameData.ScorePropRecoverFromDizziness);
player.SetPlayerState();
player.SetPlayerStateNaturally();
}
break;
default:
@@ -210,8 +210,9 @@ namespace Gaming
{ IsBackground = true }.Start();
*/
}
public PropManager(Map gameMap) // 道具不能扔过墙
public PropManager(Map gameMap, CharacterManager characterManager) // 道具不能扔过墙
{
this.characterManager = characterManager;
this.gameMap = gameMap;
/* this.moveEngine = new MoveEngine(
gameMap: gameMap,


+ 41
- 18
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -4,6 +4,7 @@ using Preparation.Interface;
using Preparation.Utility;
using System;
using Timothy.FrameRateTask;
using Google.Protobuf.Compiler;

namespace Gaming
{
@@ -28,29 +29,51 @@ namespace Gaming
{ });
}

public static bool ShowTime(Character player)
public bool ShowTime(Character player)
{
if ((!player.Commandable())) return false;
IActiveSkill skill = player.FindIActiveSkill(ActiveSkillType.ShowTime);
Debugger.Output(player, ": It's show time!");
characterManager.SetPlayerState(player, PlayerStateType.UsingSkill);

return ActiveSkillEffect(skill, player, () =>
{
/* Thread
* new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.OpeningTheChest && gameMap.Timer.IsGaming && (!chestToOpen.IsOpen()),
loopToDo: () =>
{
chestToOpen.OpenStartTime += GameData.frameDuration * player.SpeedOfOpenChest;
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.UsingSkill && gameMap.Timer.IsGaming,
loopToDo: () =>
{
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try
{
foreach (Character person in gameMap.GameObjDict[GameObjType.Character])
{
if (!person.IsGhost())
actionManager.MovePlayer(person, GameData.frameDuration, (player.Position - person.Position).Angle());
}
}
finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)

.Start();*/
.Start();
}
)
{ IsBackground = true }.Start();
},
() =>
{ });
{
if (player.PlayerState == PlayerStateType.UsingSkill)
player.SetPlayerStateNaturally();
}
);
}

public static bool BecomeInvisible(Character player)
@@ -145,7 +168,7 @@ namespace Gaming
{
if (!character.IsGhost() && XY.Distance(character.Position, player.Position) <= player.ViewRange)
{
if (CharacterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl))
if (characterManager.BeStunned(character, GameData.TimeOfStudentFaintingWhenHowl))
player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.TimeOfStudentFaintingWhenHowl));
break;
}
@@ -155,7 +178,7 @@ namespace Gaming
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}
CharacterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl);
characterManager.BackSwing(player, GameData.TimeOfGhostSwingingAfterHowl);
Debugger.Output(player, "howled!");
},
() =>
@@ -177,7 +200,7 @@ namespace Gaming
|| character.PlayerState == PlayerStateType.UsingSkill)
&& gameMap.CanSee(player, character))
{
if (CharacterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish))
if (characterManager.BeStunned(character, GameData.TimeOfGhostFaintingWhenPunish))
player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.TimeOfGhostFaintingWhenPunish));
break;
}
@@ -205,7 +228,7 @@ namespace Gaming
{
if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character))
{
character.SetPlayerState();
characterManager.SetPlayerState(character);
character.HP = GameData.RemainHpWhenAddLife;
((Student)character).TimeOfRescue = 0;
player.AddScore(GameData.StudentScoreRescue);


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

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


+ 4
- 2
logic/Preparation/Interface/IOccupation.cs View File

@@ -101,10 +101,10 @@ namespace Preparation.Interface

public BulletType InitBullet => BulletType.CommonAttackOfGhost;

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

public double concealment = GameData.basicConcealment;
public double concealment = GameData.basicConcealment * 3 / 4;
public double Concealment => concealment;

public int alertnessRadius = GameData.basicGhostAlertnessRadius;
@@ -414,6 +414,8 @@ namespace Preparation.Interface
return new ANoisyPerson();
case CharacterType.TechOtaku:
return new TechOtaku();
case CharacterType.Idol:
return new Idol();
case CharacterType.Athlete:
default:
return new Athlete();


+ 5
- 1
logic/Preparation/Interface/ISkill.cs View File

@@ -126,7 +126,7 @@ namespace Preparation.Interface
public int SkillCD => GameData.commonSkillCD * 3;
public int DurationTime => GameData.commonSkillTime;

private readonly object commonSkillLock = new object();
private readonly object commonSkillLock = new();
public object ActiveSkillLock => commonSkillLock;

public bool isBeingUsed = false;
@@ -275,6 +275,8 @@ namespace Preparation.Interface
return new Rouse();
case ActiveSkillType.Inspire:
return new Inspire();
case ActiveSkillType.ShowTime:
return new ShowTime();
default:
return new NullSkill();
}
@@ -308,6 +310,8 @@ namespace Preparation.Interface
return ActiveSkillType.UseRobot;
case Rouse:
return ActiveSkillType.Rouse;
case ShowTime:
return ActiveSkillType.ShowTime;
default:
return ActiveSkillType.Null;
}


+ 1
- 0
logic/Preparation/Utility/EnumType.cs View File

@@ -83,6 +83,7 @@ namespace Preparation.Utility
ANoisyPerson = 7,
Robot = 8,
Sunshine = 9,
Idol = 10,
}
public enum ActiveSkillType // 主动技能
{


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

@@ -15,6 +15,8 @@ namespace Preparation.Utility
public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长
public const long gameDuration = 600000; // 游戏时长600000ms = 10min

public const int LimitOfStopAndMove = 15;

public const int MinSpeed = 1; // 最小速度
public const int MaxSpeed = int.MaxValue; // 最大速度

@@ -127,6 +129,7 @@ namespace Preparation.Utility
CharacterType.Assassin => true,
CharacterType.Klee => true,
CharacterType.ANoisyPerson => true,
CharacterType.Idol => true,
_ => false,
};
}


+ 4
- 0
logic/Preparation/Utility/Transformation.cs View File

@@ -233,6 +233,8 @@ namespace Preparation.Utility
return Protobuf.TrickerType.Klee;
case Preparation.Utility.CharacterType.ANoisyPerson:
return Protobuf.TrickerType.ANoisyPerson;
case CharacterType.Idol:
return TrickerType.Idol;
default:
return Protobuf.TrickerType.NullTrickerType;
}
@@ -247,6 +249,8 @@ namespace Preparation.Utility
return Preparation.Utility.CharacterType.Klee;
case Protobuf.TrickerType.ANoisyPerson:
return Preparation.Utility.CharacterType.ANoisyPerson;
case TrickerType.Idol:
return CharacterType.Idol;
default:
return Preparation.Utility.CharacterType.Null;
}


+ 1
- 4
logic/Preparation/Utility/XY.cs View File

@@ -75,10 +75,7 @@ namespace Preparation.Utility
return Math.Atan2(y, x);
}

public override bool Equals(object obj)
{
throw new NotImplementedException();
}
public override bool Equals(object obj) => throw new NotImplementedException();

public override int GetHashCode()
{


+ 140
- 99
logic/Server/CopyInfo.cs View File

@@ -32,7 +32,7 @@ namespace Server
case Preparation.Utility.GameObjType.Chest:
return Chest((Chest)gameObj, time);
case Preparation.Utility.GameObjType.Doorway:
return Gate((Doorway)gameObj);
return Gate((Doorway)gameObj, time);
case Preparation.Utility.GameObjType.EmergencyExit:
if (((EmergencyExit)gameObj).CanOpen)
return HiddenGate((EmergencyExit)gameObj);
@@ -44,133 +44,153 @@ namespace Server
}
public static MessageOfObj? Auto(MessageOfNews news)
{
MessageOfObj objMsg = new();
objMsg.NewsMessage = news;
MessageOfObj objMsg = new()
{
NewsMessage = news
};
return objMsg;
}

private static MessageOfObj? Student(Student player)
{
MessageOfObj msg = new MessageOfObj();
if (player.IsGhost()) return null;
msg.StudentMessage = new();
MessageOfObj msg = new()
{
StudentMessage = new()
{
X = player.Position.x,
Y = player.Position.y,
Speed = player.MoveSpeed,
Determination = player.HP,
Addiction = player.GamingAddiction,
Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place),
Guid = player.ID,

PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState),
PlayerId = player.PlayerID,
ViewRange = player.ViewRange,
Radius = player.Radius,
DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0,
Score = player.Score,
TreatProgress = player.DegreeOfTreatment,
RescueProgress = player.TimeOfRescue,

msg.StudentMessage.X = player.Position.x;
msg.StudentMessage.Y = player.Position.y;
msg.StudentMessage.Speed = player.MoveSpeed;
msg.StudentMessage.Determination = player.HP;
msg.StudentMessage.Addiction = player.GamingAddiction;
BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer),
LearningSpeed = player.FixSpeed,
TreatSpeed = player.TreatSpeed,
FacingDirection = player.FacingDirection.Angle(),
StudentType = Transformation.ToStudentType(player.CharacterType)
}
};

foreach (var keyValue in player.TimeUntilActiveSkillAvailable)
msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value);
for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count(); ++i)
for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i)
msg.StudentMessage.TimeUntilSkillAvailable.Add(-1);

foreach (var value in player.PropInventory)
msg.StudentMessage.Prop.Add(Transformation.ToPropType(value.GetPropType()));

msg.StudentMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place);
msg.StudentMessage.Guid = player.ID;

msg.StudentMessage.PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState);
msg.StudentMessage.PlayerId = player.PlayerID;
msg.StudentMessage.ViewRange = player.ViewRange;
msg.StudentMessage.Radius = player.Radius;
msg.StudentMessage.DangerAlert = (player.BgmDictionary.ContainsKey(BgmType.GhostIsComing)) ? player.BgmDictionary[BgmType.GhostIsComing] : 0;
msg.StudentMessage.Score = player.Score;
msg.StudentMessage.TreatProgress = player.DegreeOfTreatment;
msg.StudentMessage.RescueProgress = player.TimeOfRescue;

foreach (KeyValuePair<Preparation.Utility.BuffType, bool> kvp in player.Buff)
{
if (kvp.Value)
msg.StudentMessage.Buff.Add(Transformation.ToStudentBuffType(kvp.Key));
}

msg.StudentMessage.BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer);
msg.StudentMessage.LearningSpeed = player.FixSpeed;
msg.StudentMessage.TreatSpeed = player.TreatSpeed;
msg.StudentMessage.FacingDirection = player.FacingDirection.Angle();
msg.StudentMessage.StudentType = Transformation.ToStudentType(player.CharacterType);
return msg;
}

private static MessageOfObj? Tricker(Character player)
{
MessageOfObj msg = new MessageOfObj();
if (!player.IsGhost()) return null;
msg.TrickerMessage = new();
MessageOfObj msg = new()
{
TrickerMessage = new()
{
X = player.Position.x,
Y = player.Position.y,
Speed = player.MoveSpeed,
Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place),

TrickerType = Transformation.ToTrickerType(player.CharacterType),
Guid = player.ID,
Score = player.Score,
PlayerId = player.PlayerID,
ViewRange = player.ViewRange,
Radius = player.Radius,
PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState),
TrickDesire = (player.BgmDictionary.ContainsKey(BgmType.StudentIsApproaching)) ? player.BgmDictionary[BgmType.StudentIsApproaching] : 0,
ClassVolume = (player.BgmDictionary.ContainsKey(BgmType.GeneratorIsBeingFixed)) ? player.BgmDictionary[BgmType.GeneratorIsBeingFixed] : 0,
FacingDirection = player.FacingDirection.Angle(),
BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer)
}
};

msg.TrickerMessage.X = player.Position.x;
msg.TrickerMessage.Y = player.Position.y;
msg.TrickerMessage.Speed = player.MoveSpeed;
foreach (var keyValue in player.TimeUntilActiveSkillAvailable)
msg.TrickerMessage.TimeUntilSkillAvailable.Add(keyValue.Value);
for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count(); ++i)
for (int i = 0; i < GameData.maxNumOfSkill - player.TimeUntilActiveSkillAvailable.Count; ++i)
msg.TrickerMessage.TimeUntilSkillAvailable.Add(-1);

msg.TrickerMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place);
foreach (var value in player.PropInventory)
msg.TrickerMessage.Prop.Add(Transformation.ToPropType(value.GetPropType()));

msg.TrickerMessage.TrickerType = Transformation.ToTrickerType(player.CharacterType);
msg.TrickerMessage.Guid = player.ID;
msg.TrickerMessage.Score = player.Score;
msg.TrickerMessage.PlayerId = player.PlayerID;
msg.TrickerMessage.ViewRange = player.ViewRange;
msg.TrickerMessage.Radius = player.Radius;
msg.TrickerMessage.PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState);
msg.TrickerMessage.TrickDesire = (player.BgmDictionary.ContainsKey(BgmType.StudentIsApproaching)) ? player.BgmDictionary[BgmType.StudentIsApproaching] : 0;
msg.TrickerMessage.ClassVolume = (player.BgmDictionary.ContainsKey(BgmType.GeneratorIsBeingFixed)) ? player.BgmDictionary[BgmType.GeneratorIsBeingFixed] : 0;
msg.TrickerMessage.FacingDirection = player.FacingDirection.Angle();
msg.TrickerMessage.BulletType = Transformation.ToBulletType((Preparation.Utility.BulletType)player.BulletOfPlayer);
foreach (KeyValuePair<Preparation.Utility.BuffType, bool> kvp in player.Buff)
{
if (kvp.Value)
msg.TrickerMessage.Buff.Add(Transformation.ToTrickerBuffType(kvp.Key));
}


return msg;
}

private static MessageOfObj Bullet(Bullet bullet)
{
MessageOfObj msg = new MessageOfObj();
msg.BulletMessage = new();
msg.BulletMessage.X = bullet.Position.x;
msg.BulletMessage.Y = bullet.Position.y;
msg.BulletMessage.FacingDirection = bullet.FacingDirection.Angle();
msg.BulletMessage.Guid = bullet.ID;
msg.BulletMessage.Team = (bullet.Parent.IsGhost()) ? PlayerType.TrickerPlayer : PlayerType.StudentPlayer;
msg.BulletMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)bullet.Place);
msg.BulletMessage.BombRange = bullet.BulletBombRange;
msg.BulletMessage.Speed = bullet.Speed;
MessageOfObj msg = new()
{
BulletMessage = new()
{
X = bullet.Position.x,
Y = bullet.Position.y,
FacingDirection = bullet.FacingDirection.Angle(),
Guid = bullet.ID,
Team = (bullet.Parent.IsGhost()) ? PlayerType.TrickerPlayer : PlayerType.StudentPlayer,
Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)bullet.Place),
BombRange = bullet.BulletBombRange,
Speed = bullet.Speed
}
};
return msg;
}

private static MessageOfObj Prop(Prop prop)
{
MessageOfObj msg = new MessageOfObj();
msg.PropMessage = new();
msg.PropMessage.Type = Transformation.ToPropType(prop.GetPropType());
msg.PropMessage.X = prop.Position.x;
msg.PropMessage.Y = prop.Position.y;
msg.PropMessage.FacingDirection = prop.FacingDirection.Angle();
msg.PropMessage.Guid = prop.ID;
msg.PropMessage.Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)prop.Place);
MessageOfObj msg = new()
{
PropMessage = new()
{
Type = Transformation.ToPropType(prop.GetPropType()),
X = prop.Position.x,
Y = prop.Position.y,
FacingDirection = prop.FacingDirection.Angle(),
Guid = prop.ID,
Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)prop.Place)
}
};
return msg;
}

private static MessageOfObj BombedBullet(BombedBullet bombedBullet)
{
MessageOfObj msg = new MessageOfObj();
msg.BombedBulletMessage = new();
msg.BombedBulletMessage.X = bombedBullet.bulletHasBombed.Position.x;
msg.BombedBulletMessage.Y = bombedBullet.bulletHasBombed.Position.y;
msg.BombedBulletMessage.FacingDirection = bombedBullet.FacingDirection.Angle();
msg.BombedBulletMessage.MappingId = bombedBullet.MappingID;
msg.BombedBulletMessage.BombRange = bombedBullet.bulletHasBombed.BulletBombRange;
MessageOfObj msg = new()
{
BombedBulletMessage = new()
{
X = bombedBullet.bulletHasBombed.Position.x,
Y = bombedBullet.bulletHasBombed.Position.y,
FacingDirection = bombedBullet.FacingDirection.Angle(),
MappingId = bombedBullet.MappingID,
BombRange = bombedBullet.bulletHasBombed.BulletBombRange
}
};
return msg;
}

@@ -188,48 +208,69 @@ namespace Server

private static MessageOfObj Classroom(Generator generator)
{
MessageOfObj msg = new MessageOfObj();
msg.ClassroomMessage = new();
msg.ClassroomMessage.X = generator.Position.x;
msg.ClassroomMessage.Y = generator.Position.y;
msg.ClassroomMessage.Progress = generator.DegreeOfRepair;
MessageOfObj msg = new()
{
ClassroomMessage = new()
{
X = generator.Position.x,
Y = generator.Position.y,
Progress = generator.DegreeOfRepair
}
};
return msg;
}
private static MessageOfObj Gate(Doorway doorway)
private static MessageOfObj Gate(Doorway doorway, int time)
{
MessageOfObj msg = new MessageOfObj();
msg.GateMessage = new();
msg.GateMessage.X = doorway.Position.x;
msg.GateMessage.Y = doorway.Position.y;
msg.GateMessage.Progress = doorway.OpenDegree;
MessageOfObj msg = new()
{
GateMessage = new()
{
X = doorway.Position.x,
Y = doorway.Position.y
}
};
int progress = ((doorway.OpenStartTime > 0) ? (time - doorway.OpenStartTime) : 0) + doorway.OpenDegree;
msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress;
return msg;
}
private static MessageOfObj HiddenGate(EmergencyExit Exit)
{
MessageOfObj msg = new MessageOfObj();
msg.HiddenGateMessage = new();
msg.HiddenGateMessage.X = Exit.Position.x;
msg.HiddenGateMessage.Y = Exit.Position.y;
msg.HiddenGateMessage.Opened = Exit.IsOpen;
MessageOfObj msg = new()
{
HiddenGateMessage = new()
{
X = Exit.Position.x,
Y = Exit.Position.y,
Opened = Exit.IsOpen
}
};
return msg;
}

private static MessageOfObj Door(Door door)
{
MessageOfObj msg = new MessageOfObj();
msg.DoorMessage = new();
msg.DoorMessage.X = door.Position.x;
msg.DoorMessage.Y = door.Position.y;
msg.DoorMessage.Progress = door.OpenOrLockDegree;
msg.DoorMessage.IsOpen = door.IsOpen;
MessageOfObj msg = new()
{
DoorMessage = new()
{
X = door.Position.x,
Y = door.Position.y,
Progress = door.OpenOrLockDegree,
IsOpen = door.IsOpen
}
};
return msg;
}
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;
MessageOfObj msg = new()
{
ChestMessage = new()
{
X = chest.Position.x,
Y = chest.Position.y
}
};
int progress = (chest.OpenStartTime > 0) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0;
msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress;
return msg;


+ 2
- 1
logic/规则Logic.md View File

@@ -252,7 +252,7 @@
- 特性
- 冥想
- 当玩家处于可接受指令状态且不在修机时,会积累学习进度,速度为0.3%/ms
- 受到攻击(并非伤害)或眩晕或翻窗(或攻击他人)学习进度清零
- 受到攻击(并非伤害)或学习或进入不可接受治疗状态(包括翻窗)学习进度清零
- 主动技能5
- 写答案
- CD:30s
@@ -401,6 +401,7 @@ public:

### 人物
- 被唤醒或被勉励不属于交互状态,翻窗属于交互状态
- EndAllAction()及Move指令调用数总和一帧内不超过10次

### 初始状态
- 玩家出生点固定且一定为空地


Loading…
Cancel
Save