Browse Source

Merge pull request #423 from eesast/dev

fix: 🐛 fix the bug about EndAllAction and CAPI
tags/0.1.0
Timothy Liu GitHub 2 years ago
parent
commit
131b231761
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 113 additions and 61 deletions
  1. +4
    -1
      CAPI/cpp/API/src/Communication.cpp
  2. +12
    -12
      docs/GameRules.md
  3. +32
    -12
      logic/GameClass/GameObj/Character/Character.cs
  4. +5
    -0
      logic/GameEngine/MoveEngine.cs
  5. +17
    -11
      logic/Gaming/ActionManager.cs
  6. +3
    -2
      logic/Gaming/AttackManager.cs
  7. +31
    -15
      logic/Gaming/CharacterManager .cs
  8. +1
    -6
      logic/Gaming/Game.cs
  9. +1
    -0
      logic/Preparation/Interface/ICharacter.cs
  10. +0
    -2
      logic/Server/CopyInfo.cs
  11. +7
    -0
      logic/cmd/gameServerAndClient.cmd

+ 4
- 1
CAPI/cpp/API/src/Communication.cpp View File

@@ -249,10 +249,13 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T
grpc::ClientContext context;
auto MessageReader = THUAI6Stub->AddPlayer(&context, playerMsg);

while (MessageReader->Read(&message2Client))
protobuf::MessageToClient buffer2Client;

while (MessageReader->Read(&buffer2Client))
{
{
std::lock_guard<std::mutex> lock(mtxMessage);
message2Client = std::move(buffer2Client);
haveNewMessage = true;
}
cvMessage.notify_one();


+ 12
- 12
docs/GameRules.md View File

@@ -1,5 +1,5 @@
# 规则
V5.3
V5.4
- [规则](#规则)
- [简则](#简则)
- [地图](#地图)
@@ -201,11 +201,11 @@ $$
#### Assassin
- 普通攻击为 CommonAttackOfGhost
- 主动技能
- 隐身 BecomeInvisible
0. 隐身 BecomeInvisible
- CD:40s 持续时间:10s
- 在持续时间内玩家隐身
- 使用瞬间得分15
- 使用飞刀
1. 使用飞刀
- CD:30s 持续时间:1s
- 在持续时间内,攻击类型变为飞刀
- 不直接得分
@@ -213,7 +213,7 @@ $$
#### Klee
- 普通攻击为 CommonAttackOfGhost
- 主动技能
- 蹦蹦炸弹 JumpyBomb
0. 蹦蹦炸弹 JumpyBomb
- CD:15s 持续时间:3s
- 在持续时间内,攻击类型变为蹦蹦炸弹
- 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上90°,270° 发出2个小炸弹
@@ -223,7 +223,7 @@ $$
#### 喧哗者ANoisyPerson
- 普通攻击为 CommonAttackOfGhost
- 主动技能
- 嚎叫 Howl
0. 嚎叫 Howl
- CD:25s
- 使用瞬间,在视野半径范围内(不是可视区域)的学生被眩晕5500ms,自己进入800ms的后摇
- 通过眩晕获得对应得分
@@ -233,7 +233,7 @@ $$
#### Idol
- 普通攻击为 CommonAttackOfGhost
- 主动技能
- ShowTime
0. ShowTime
- CD: 80s 持续时间:10s
- 持续时间内
- 使警戒范围外的学生眩晕并每200ms发送向自己移动200ms的指令(速度为学生本应速度*二者距离/警戒范围)
@@ -258,14 +258,14 @@ $$

#### 运动员
- 主动技能
- 冲撞 CanBeginToCharge
0. 冲撞 CanBeginToCharge
- CD:60s 持续时间:3s
- 在持续时间内,速度变为三倍,期间撞到捣蛋鬼,会导致捣蛋鬼眩晕7.22s,学生眩晕2.09s
- 通过眩晕获得对应得分

#### 教师
- 主动技能
- 惩罚 Punish
0. 惩罚 Punish
- CD:30s
- 使用瞬间,在可视范围内的翻窗、开锁门、攻击前后摇的捣蛋鬼会被眩晕(3070+300*已受伤害/基本伤害(1500000))ms,
- 通过眩晕获得对应得分
@@ -279,22 +279,22 @@ $$
- 当处于可接受指令状态且不在学习时,会积累“冥想进度”,速度为40/ms
- 受到攻击(并非伤害)、进入学习状态或进入不可接受指令状态(包括翻窗)冥想进度清零
- 主动技能5
- 写答案 WriteAnswers
0. 写答案 WriteAnswers
- CD:30s
- 使用瞬间,对于可交互范围内的一间教室的作业增加冥想进度,冥想进度清零
- 通过学习获得对应得分

#### 开心果
- 主动技能
- 唤醒 Rouse
0. 唤醒 Rouse
- CD:120s
- 使用瞬间,唤醒可视范围内一个沉迷中的人
- 通过唤醒获得对应得分
- 勉励 Encourage
1. 勉励 Encourage
- CD:120s
- 使用瞬间,为可视范围内随机一个毅力不足的人试图补充750000的毅力值
- 获得勉励750000的毅力值对应得分
- 鼓舞 Inspire
2. 鼓舞 Inspire
- CD:120s
- 使用瞬间,可视范围内学生(包括自己)获得持续6秒的1.6倍速Buff
- 每鼓舞一个学生得分10


+ 32
- 12
logic/GameClass/GameObj/Character/Character.cs View File

@@ -291,7 +291,7 @@ namespace GameClass.GameObj
}
}
#endregion
#region 状态相关的基本属性与方法
private PlayerStateType playerState = PlayerStateType.Null;
public PlayerStateType PlayerState
{
@@ -318,7 +318,23 @@ namespace GameClass.GameObj
private GameObj? whatInteractingWith = null;
public GameObj? WhatInteractingWith => whatInteractingWith;

private long threadNum = 0;
public long ThreadNum => threadNum;

public void ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (gameObjLock)
{
++threadNum;
whatInteractingWith = gameObj;
if (value != PlayerStateType.Moving)
IsMoving = false;
playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value;
//Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString());
}
}

public void ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (gameObjLock)
{
@@ -334,11 +350,26 @@ namespace GameClass.GameObj
{
lock (gameObjLock)
{
++threadNum;
whatInteractingWith = null;
IsMoving = false;
playerState = PlayerStateType.Null;
}
}

public void RemoveFromGame(PlayerStateType playerStateType)
{
lock (gameObjLock)
{
playerState = playerStateType;
CanMove = false;
IsResetting = true;
Position = GameData.PosWhoDie;
place = PlaceType.Grass;
}
}
#endregion

private int score = 0;
public int Score
{
@@ -572,17 +603,6 @@ namespace GameClass.GameObj
this.Vampire = this.OriVampire;
}
}*/
public void RemoveFromGame(PlayerStateType playerStateType)
{
lock (gameObjLock)
{
playerState = playerStateType;
CanMove = false;
IsResetting = true;
Position = GameData.PosWhoDie;
place = PlaceType.Grass;
}
}

public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Circle;


+ 5
- 0
logic/GameEngine/MoveEngine.cs View File

@@ -79,6 +79,8 @@ namespace GameEngine
return;
if (!obj.IsAvailable || !gameTimer.IsGaming)
return;

long threadNum = (obj.Type == GameObjType.Character) ? ((ICharacter)obj).ThreadNum : 0;//对人特殊处理
new Thread
(
() =>
@@ -123,6 +125,9 @@ namespace GameEngine
moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond;
res = new XY(direction, moveVecLength);

//对人特殊处理
if (threadNum > 0 && ((ICharacter)obj).ThreadNum != threadNum) return false;

// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
do


+ 17
- 11
logic/Gaming/ActionManager.cs View File

@@ -71,12 +71,13 @@ namespace Gaming

++generatorForFix.NumOfFixing;
characterManager.SetPlayerState(player, PlayerStateType.Fixing);
long threadNum = player.ThreadNum;
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming && player.PlayerState == PlayerStateType.Fixing,
loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.ThreadNum,
loopToDo: () =>
{
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
@@ -170,8 +171,10 @@ namespace Gaming
{
characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated);
characterManager.SetPlayerState(player, PlayerStateType.Treating);
long threadNum = player.ThreadNum;

new FrameRateTaskExecutor<int>(
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && player.PlayerState == PlayerStateType.Treating && gameMap.Timer.IsGaming,
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
@@ -182,7 +185,7 @@ namespace Gaming
)
.Start();

if (player.PlayerState == PlayerStateType.Treating) characterManager.SetPlayerState(player);
if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player);
else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated);
}
)
@@ -200,13 +203,14 @@ namespace Gaming
return false;
characterManager.SetPlayerState(player, PlayerStateType.Rescuing);
characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued);
long threadNum = player.ThreadNum;

new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && player.PlayerState == PlayerStateType.Rescuing && gameMap.Timer.IsGaming,
loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
playerRescued.TimeOfRescue += GameData.frameDuration;
@@ -228,7 +232,7 @@ namespace Gaming
else
characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted);
}
if (player.PlayerState == PlayerStateType.Rescuing) characterManager.SetPlayerState(player);
if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player);
playerRescued.TimeOfRescue = 0;
}
)
@@ -297,13 +301,14 @@ namespace Gaming
// gameMap.Add(addWall);

characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows);
long threadNum = player.ThreadNum;
windowForClimb.WhoIsClimbing = player;
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.ClimbingThroughWindows && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopToDo: () => { },
timeInterval: GameData.frameDuration,
finallyReturn: () => 0,
@@ -322,7 +327,7 @@ namespace Gaming
moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle());

new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.ClimbingThroughWindows && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
},
@@ -336,7 +341,7 @@ namespace Gaming
player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed);
windowForClimb.WhoIsClimbing = null;
// gameMap.Remove(addWall);
if (player.PlayerState == PlayerStateType.ClimbingThroughWindows)
if (threadNum == player.ThreadNum)
{
characterManager.SetPlayerState(player);
}
@@ -379,12 +384,13 @@ namespace Gaming
if (!flag) return false;

characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor);
long threadNum = player.ThreadNum;
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => flag && player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
loopCondition: () => flag && threadNum == player.ThreadNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
loopToDo: () =>
{
flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null);
@@ -399,7 +405,7 @@ namespace Gaming
{
doorToLock.IsOpen = (!doorToLock.IsOpen);
}
if (player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor)
if (threadNum == player.ThreadNum)
characterManager.SetPlayerState(player);
doorToLock.OpenOrLockDegree = 0;
}
@@ -472,7 +478,7 @@ namespace Gaming
OnCollision: (obj, collisionObj, moveVec) =>
{
SkillWhenColliding((Character)obj, collisionObj);
Preparation.Utility.Debugger.Output(obj, " end move with " + collisionObj.ToString());
//Preparation.Utility.Debugger.Output(obj, " end move with " + collisionObj.ToString());
//if (collisionObj is Mine)
//{
// ActivateMine((Character)obj, (Mine)collisionObj);


+ 3
- 2
logic/Gaming/AttackManager.cs View File

@@ -192,12 +192,13 @@ namespace Gaming
if (bullet.CastTime > 0)
{
characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack);
long threadNum = player.ThreadNum;

new Thread
(() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => player.PlayerState == PlayerStateType.TryingToAttack && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
},
@@ -209,7 +210,7 @@ namespace Gaming

if (gameMap.Timer.IsGaming)
{
if (player.PlayerState == PlayerStateType.TryingToAttack)
if (threadNum == player.ThreadNum)
{
characterManager.SetPlayerState(player);
}


+ 31
- 15
logic/Gaming/CharacterManager .cs View File

@@ -20,20 +20,33 @@ namespace Gaming

public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
switch (player.PlayerState)
lock (player.MoveLock)
{
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;
switch (player.PlayerState)
{
case PlayerStateType.OpeningTheChest:
((Chest)player.WhatInteractingWith).StopOpen();
player.ChangePlayerState(value, gameObj);
break;
case PlayerStateType.OpeningTheDoorway:
Doorway doorway = (Doorway)player.WhatInteractingWith;
doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime;
doorway.OpenStartTime = 0;
player.ChangePlayerState(value, gameObj);
break;
case PlayerStateType.Addicted:
if (value == PlayerStateType.Rescued)
player.ChangePlayerStateInOneThread(value, gameObj);
break;
case PlayerStateType.Rescued:
if (value == PlayerStateType.Addicted)
player.ChangePlayerStateInOneThread(value, gameObj);
break;
default:
player.ChangePlayerState(value, gameObj);
break;
}
}
player.ChangePlayerState(value, gameObj);
}

public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null)
@@ -233,6 +246,7 @@ namespace Gaming
}
}
SetPlayerState(player, PlayerStateType.Addicted);
long threadNum = player.ThreadNum;
new Thread
(() =>
{
@@ -240,7 +254,7 @@ namespace Gaming
Debugger.Output(player, " is addicted ");
#endif
new FrameRateTaskExecutor<int>(
() => (player.PlayerState == PlayerStateType.Addicted || player.PlayerState == PlayerStateType.Rescued) && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming,
() => threadNum == player.ThreadNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming,
() =>
{
player.GamingAddiction += (player.PlayerState == PlayerStateType.Addicted) ? GameData.frameDuration : 0;
@@ -269,8 +283,9 @@ namespace Gaming
(() =>
{
SetPlayerState(player, PlayerStateType.Stunned);
long threadNum = player.ThreadNum;
Thread.Sleep(time);
if (player.PlayerState == PlayerStateType.Stunned)
if (threadNum == player.ThreadNum)
SetPlayerState(player);
}
)
@@ -358,13 +373,14 @@ namespace Gaming
if (time <= 0) return false;
if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false;
SetPlayerState(player, PlayerStateType.Swinging);
long threadNum = player.ThreadNum;

new Thread
(() =>
{
Thread.Sleep(time);

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


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

@@ -80,12 +80,7 @@ namespace Gaming
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
bool res = actionManager.MovePlayer(player, moveTimeInMilliseconds, angle);
#if DEBUG
Console.WriteLine($"PlayerID:{playerID} move to ({player.Position.x},{player.Position.y})!");
#endif
return res;

return actionManager.MovePlayer(player, moveTimeInMilliseconds, angle);
}
else
{


+ 1
- 0
logic/Preparation/Interface/ICharacter.cs View File

@@ -14,6 +14,7 @@ namespace Preparation.Interface
public BulletType BulletOfPlayer { get; set; }
public CharacterType CharacterType { get; }
public int BulletNum { get; }
public long ThreadNum { get; }

public bool IsGhost();
}


+ 0
- 2
logic/Server/CopyInfo.cs View File

@@ -1,7 +1,5 @@
using Protobuf;
using System.Collections.Generic;
using GameClass.GameObj;
using System.Numerics;
using Preparation.Utility;
using Gaming;



+ 7
- 0
logic/cmd/gameServerAndClient.cmd View File

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

ping -n 2 127.0.0.1 > NUL

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

Loading…
Cancel
Save