Browse Source

refactor: 🚧 change setPlayerState to the Method of character

tags/v0.1.0
shangfengh 2 years ago
parent
commit
121136cf50
15 changed files with 353 additions and 262 deletions
  1. +3
    -2
      docs/版本更新说明.md
  2. +177
    -45
      logic/GameClass/GameObj/Character/Character.cs
  3. +1
    -2
      logic/GameClass/GameObj/Immovable.cs
  4. +3
    -2
      logic/GameClass/GameObj/Map/Chest.cs
  5. +50
    -15
      logic/GameClass/GameObj/Map/Doorway.cs
  6. +8
    -30
      logic/GameClass/GameObj/Map/Window.cs
  7. +26
    -63
      logic/GameClass/GameObj/Moveable.cs
  8. +31
    -29
      logic/Gaming/ActionManager.cs
  9. +2
    -2
      logic/Gaming/AttackManager.cs
  10. +15
    -68
      logic/Gaming/CharacterManager.cs
  11. +3
    -3
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  12. +9
    -0
      logic/Preparation/Interface/IChest.cs
  13. +12
    -0
      logic/Preparation/Interface/IDoorway.cs
  14. +1
    -1
      logic/Preparation/Interface/IMoveable.cs
  15. +12
    -0
      logic/Preparation/Interface/IWindow.cs

+ 3
- 2
docs/版本更新说明.md View File

@@ -30,5 +30,6 @@
- **重复发出同一类型的交互指令和移动指令是无效的**
- feat&fix:修复并**将`SendMessage`改为`SendTextMessage`与`SendBinaryMessage`**

# 最新更新
- docs:更新了 游戏机制与平衡性调整更新草案.pdf
# 5月13日更新
- docs:更新了 游戏机制与平衡性调整更新草案.pdf
- feat:更新了下载器

+ 177
- 45
logic/GameClass/GameObj/Character/Character.cs View File

@@ -2,11 +2,16 @@
using Preparation.Utility;
using System;
using System.Collections.Generic;
using System.Threading;

namespace GameClass.GameObj
{
public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终了
{

private readonly ReaderWriterLockSlim hpReaderWriterLock = new();
public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock;

#region 装弹、攻击相关的基本属性及方法
/// <summary>
/// 装弹冷却
@@ -231,21 +236,65 @@ namespace GameClass.GameObj
}
#endregion
#region 血量相关的基本属性及方法
public int MaxHp { get; protected set; } // 最大血量
private int maxHp;
public int MaxHp
{
get
{
HPReadWriterLock.EnterReadLock();
try
{
return maxHp;
}
finally
{
HPReadWriterLock.ExitReadLock();
}
}
protected set
{
HPReadWriterLock.EnterWriteLock();
try
{
maxHp = value;
}
finally
{
HPReadWriterLock.ExitWriteLock();
}
}
} // 最大血量
protected int hp;
public int HP
{
get => hp;
get
{
HPReadWriterLock.EnterReadLock();
try
{
return hp;
}
finally
{
HPReadWriterLock.ExitReadLock();
}
}
set
{
if (value > 0)
HPReadWriterLock.EnterWriteLock();
try
{
lock (gameObjLock)
if (value > 0)
{
hp = value <= MaxHp ? value : MaxHp;
}
else
lock (gameObjLock)
}
else
hp = 0;
}
finally
{
HPReadWriterLock.ExitWriteLock();
}
}
}

@@ -256,47 +305,62 @@ namespace GameClass.GameObj
/// <returns>减操作是否成功</returns>
public int TrySubHp(int sub)
{
int previousHp = hp;
lock (gameObjLock)
hp = hp <= sub ? 0 : hp - sub;
Debugger.Output(this, " hp has subed to: " + hp.ToString());
return previousHp - hp;
HPReadWriterLock.EnterWriteLock();
try
{
int previousHp = hp;
if (hp <= sub)
{
hp = 0;
return hp;
}
else
{
hp -= sub;
return sub;
}
}
finally
{
HPReadWriterLock.ExitWriteLock();
}
}

private double vampire = 0; // 回血率:0-1之间
public double Vampire
{
get => vampire;
set
get
{
if (value > 1)
lock (gameObjLock)
vampire = 1;
else if (value < 0)
lock (gameObjLock)
vampire = 0;
else
lock (gameObjLock)
vampire = value;
HPReadWriterLock.EnterReadLock();
try
{
return vampire;
}
finally
{
HPReadWriterLock.ExitReadLock();
}
}
}
private double oriVampire = 0;
public double OriVampire
{
get => oriVampire;
set
{
if (value > 1)
lock (gameObjLock)
HPReadWriterLock.EnterWriteLock();
try
{
if (value > 1)
vampire = 1;
else if (value < 0)
lock (gameObjLock)
else if (value < 0)
vampire = 0;
else
lock (gameObjLock)
else
vampire = value;
}
finally
{
HPReadWriterLock.ExitWriteLock();
}
}
}
private double oriVampire = 0;
public double OriVampire { get; protected set; }
#endregion
#region 状态相关的基本属性与方法
private PlayerStateType playerState = PlayerStateType.Null;
@@ -363,7 +427,7 @@ namespace GameClass.GameObj
private GameObj? whatInteractingWith = null;
public GameObj? WhatInteractingWith => whatInteractingWith;

public long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
private long ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
//只能被SetPlayerState引用
whatInteractingWith = gameObj;
@@ -374,7 +438,7 @@ namespace GameClass.GameObj
return ++stateNum;
}

public long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
private long ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
//只能被SetPlayerState引用
whatInteractingWith = gameObj;
@@ -385,6 +449,74 @@ namespace GameClass.GameObj
return stateNum;
}


public long SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (actionLock)
{
PlayerStateType nowPlayerState = PlayerState;
if (nowPlayerState == value) return -1;
switch (nowPlayerState)
{
case PlayerStateType.Escaped:
case PlayerStateType.Deceased:
return -1;

case PlayerStateType.Addicted:
if (value == PlayerStateType.Rescued)
return ChangePlayerStateInOneThread(value, gameObj);
else if (value == PlayerStateType.Null)
return ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Rescued:
if (value == PlayerStateType.Addicted)
return ChangePlayerStateInOneThread(value, gameObj);
else if (value == PlayerStateType.Null)
return ChangePlayerState(value, gameObj);
else return -1;

case PlayerStateType.TryingToAttack:
if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows)
return ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Stunned:
case PlayerStateType.Charmed:
if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows && value != PlayerStateType.Swinging)
return ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Swinging:
if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows)
{
ThreadNum.Release();
return ChangePlayerState(value, gameObj);
}
else return -1;
case PlayerStateType.ClimbingThroughWindows:
if (value != PlayerStateType.Moving)
{
Window window = (Window)WhatInteractingWith!;
window.FinishClimbing();
if (window.Stage.x == 0)
ThreadNum.Release();
else ReSetPos(window.Stage);
return ChangePlayerState(value, gameObj);
}
else return -1;

case PlayerStateType.OpeningTheChest:
((Chest)WhatInteractingWith!).StopOpen();
return ChangePlayerState(value, gameObj);
case PlayerStateType.OpeningTheDoorway:
Doorway doorway = (Doorway)WhatInteractingWith!;
doorway.StopOpenning();
return ChangePlayerState(value, gameObj);

default:
return ChangePlayerState(value, gameObj);
}
}
}

public long SetPlayerStateNaturally()
{
lock (actionLock)
@@ -398,20 +530,20 @@ namespace GameClass.GameObj

public void RemoveFromGame(PlayerStateType playerStateType)
{
MoveReaderWriterLock.EnterWriteLock();
try
lock (actionLock)
{
lock (actionLock)
MoveReaderWriterLock.EnterWriteLock();
try
{
playerState = playerStateType;
canMove = false;
isRemoved = true;
position = GameData.PosWhoDie;
}
}
finally
{
MoveReaderWriterLock.ExitWriteLock();
finally
{
MoveReaderWriterLock.ExitWriteLock();
}
playerState = playerStateType;
position = GameData.PosWhoDie;
}
}
#endregion


+ 1
- 2
logic/GameClass/GameObj/Immovable.cs View File

@@ -1,5 +1,4 @@
using Preparation.Interface;
using Preparation.Utility;
using Preparation.Utility;

namespace GameClass.GameObj
{


+ 3
- 2
logic/GameClass/GameObj/Map/Chest.cs View File

@@ -1,11 +1,12 @@
using Preparation.Utility;
using Preparation.Interface;
using Preparation.Utility;

namespace GameClass.GameObj
{
/// <summary>
/// 箱子
/// </summary>
public class Chest : Immovable
public class Chest : Immovable, IChest
{
public Chest(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest)


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

@@ -1,12 +1,14 @@
using Preparation.Interface;
using Google.Protobuf.WellKnownTypes;
using Preparation.Interface;
using Preparation.Utility;
using System;

namespace GameClass.GameObj
{
/// <summary>
/// 出口
/// </summary>
public class Doorway : Immovable
public class Doorway : Immovable, IDoorway
{
public Doorway(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Doorway)
@@ -25,7 +27,11 @@ namespace GameClass.GameObj
private bool powerSupply = false;
public bool PowerSupply
{
get => powerSupply;
get
{
lock (gameObjLock)
return powerSupply;
}
set
{
lock (gameObjLock)
@@ -36,29 +42,58 @@ namespace GameClass.GameObj
private int openStartTime = 0;
public int OpenStartTime
{
get => openStartTime;
set
get
{
lock (gameObjLock)
openStartTime = value;
return openStartTime;
}
}
public bool TryToOpen()
{
lock (gameObjLock)
{
if (!powerSupply || openStartTime > 0) return false;
openStartTime = Environment.TickCount;
return true;
}
}

public bool StopOpenning()
{
lock (gameObjLock)
{
if (openDegree + Environment.TickCount - openStartTime >= GameData.degreeOfOpenedDoorway)
{
openDegree = GameData.degreeOfOpenedDoorway;
return true;
}
else
{
openDegree = openDegree + Environment.TickCount - openStartTime;
openStartTime = 0;
return false;
}
}
}

public void FinishOpenning()
{
lock (gameObjLock)
{
openDegree = GameData.degreeOfOpenedDoorway;
}
}

private int openDegree = 0;
public int OpenDegree
{
get => openDegree;
set
get
{
if (value > 0)
lock (gameObjLock)
openDegree = (value < GameData.degreeOfOpenedDoorway) ? value : GameData.degreeOfOpenedDoorway;
else
lock (gameObjLock)
openDegree = 0;
lock (gameObjLock)
return openDegree;
}
}

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

+ 8
- 30
logic/GameClass/GameObj/Map/Window.cs View File

@@ -1,14 +1,12 @@
using Preparation.Interface;
using Preparation.Utility;
using System.Numerics;
using System;

namespace GameClass.GameObj
{
/// <summary>
/// 窗
/// </summary>
public class Window : Immovable
public class Window : Immovable, IWindow
{
public Window(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Window)
@@ -32,12 +30,8 @@ namespace GameClass.GameObj
{
get
{
GameObjReaderWriterLock.EnterReadLock();
try
{
lock (gameObjLock)
return stage;
}
finally { GameObjReaderWriterLock.ExitReadLock(); }
}
}

@@ -46,47 +40,31 @@ namespace GameClass.GameObj
{
get
{
GameObjReaderWriterLock.EnterReadLock();
try
{
lock (gameObjLock)
return whoIsClimbing;
}
finally { GameObjReaderWriterLock.ExitReadLock(); }
}
}

public bool TryToClimb(Character character)
public bool TryToClimb(ICharacter character)
{
GameObjReaderWriterLock.EnterWriteLock();
try
{
lock (gameObjLock)
if (whoIsClimbing == null)
{
stage = new(0, 0);
whoIsClimbing = character;
whoIsClimbing = (Character)character;
return true;
}
else return false;
}
finally { GameObjReaderWriterLock.ExitWriteLock(); }
}
public void FinishClimbing()
{
GameObjReaderWriterLock.EnterWriteLock();
try
{
lock (gameObjLock)
whoIsClimbing = null;
}
finally { GameObjReaderWriterLock.ExitWriteLock(); }
}
public void Enter2Stage(XY xy)
{
GameObjReaderWriterLock.EnterWriteLock();
try
{
lock (gameObjLock)
stage = xy;
}
finally { GameObjReaderWriterLock.ExitWriteLock(); }
}
}
}

+ 26
- 63
logic/GameClass/GameObj/Moveable.cs View File

@@ -11,19 +11,9 @@ namespace GameClass.GameObj
//player.actionLock>其他.actionLock
private readonly ReaderWriterLockSlim moveReaderWriterLock = new();
public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock;
//规定moveReaderWriterLock<actionLock

private Semaphore threadNum = new(1, 1);
public Semaphore ThreadNum
{
get
{
return threadNum;
}
set
{
threadNum = value;
}
}
public Semaphore ThreadNum { get; } = new(1, 1);

protected long stateNum = 0;
public long StateNum
@@ -38,7 +28,6 @@ namespace GameClass.GameObj
lock (actionLock) stateNum = value;
}
}
//规定moveReaderWriterLock>actionLock

public override XY Position
{
@@ -81,20 +70,20 @@ namespace GameClass.GameObj

if (moveVec.x != 0 || moveVec.y != 0)
{
moveReaderWriterLock.EnterReadLock();
try
lock (actionLock)
{
lock (actionLock)
moveReaderWriterLock.EnterReadLock();
try
{
if (!canMove || isRemoved) return -1;
if (stateNo != stateNum) return -1;
facingDirection = moveVec;
this.position += moveVec;
}
}
finally
{
moveReaderWriterLock.ExitReadLock();
finally
{
moveReaderWriterLock.ExitReadLock();
}
if (stateNo != stateNum) return -1;
facingDirection = moveVec;
this.position += moveVec;
}
}
return moveVec * moveVec;
@@ -129,10 +118,7 @@ namespace GameClass.GameObj
moveReaderWriterLock.EnterWriteLock();
try
{
lock (actionLock)
{
canMove = value;
}
canMove = value;
}
finally
{
@@ -161,52 +147,29 @@ namespace GameClass.GameObj
{
get
{
moveReaderWriterLock.EnterReadLock();
try
lock (actionLock)
{
lock (actionLock)
moveReaderWriterLock.EnterReadLock();
try
{
return !isMoving && canMove && !isRemoved;
}
finally
{
moveReaderWriterLock.ExitReadLock();
}
finally
{
moveReaderWriterLock.ExitReadLock();
}
}
}
}

protected int moveSpeed;
protected long moveSpeed;
/// <summary>
/// 移动速度
/// </summary>
public int MoveSpeed
public long MoveSpeed
{
get
{
moveReaderWriterLock.EnterReadLock();
try
{
return moveSpeed;
}
finally
{
moveReaderWriterLock.ExitReadLock();
}
}
set
{
moveReaderWriterLock.EnterWriteLock();
try
{
lock (actionLock)
{
moveSpeed = value;
}
}
finally
{
moveReaderWriterLock.ExitWriteLock();
}
}
get => Interlocked.Read(ref moveSpeed);
set => Interlocked.Exchange(ref moveSpeed, value);
}
/// <summary>
/// 原初移动速度


+ 31
- 29
logic/Gaming/ActionManager.cs View File

@@ -36,7 +36,7 @@ namespace Gaming
public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{
if (moveTimeInMilliseconds < 5) return false;
long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving);
long stateNum = playerToMove.SetPlayerState(PlayerStateType.Moving);
if (stateNum == -1) return false;
new Thread
(
@@ -56,7 +56,7 @@ namespace Gaming
public bool MovePlayerWhenStunned(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{
if (playerToMove.CharacterType == CharacterType.Robot) return false;
long stateNum = characterManager.SetPlayerState(playerToMove, PlayerStateType.Charmed);
long stateNum = playerToMove.SetPlayerState(PlayerStateType.Charmed);
if (stateNum == -1) return false;
new Thread
(() =>
@@ -86,7 +86,7 @@ namespace Gaming
{
if (player.Commandable())
{
characterManager.SetPlayerState(player);
player.SetPlayerState();
return true;
}
}
@@ -103,7 +103,7 @@ namespace Gaming
return false;

++generatorForFix.NumOfFixing;
characterManager.SetPlayerState(player, PlayerStateType.Fixing);
player.SetPlayerState(PlayerStateType.Fixing);
long threadNum = player.StateNum;
new Thread
(
@@ -117,7 +117,7 @@ namespace Gaming
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
gameMap.NumOfRepairedGenerators++;
if (generatorForFix.DegreeOfRepair == GameData.degreeOfFixedGenerator)
characterManager.SetPlayerState(player);
player.SetPlayerState();
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
@@ -134,24 +134,26 @@ namespace Gaming

public bool OpenDoorway(Student player)
{
if (!(player.Commandable()) || player.PlayerState == PlayerStateType.OpeningTheDoorway)
if (!(player.Commandable()))
return false;
Doorway? doorwayToOpen = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway);
if (doorwayToOpen == null || doorwayToOpen.OpenStartTime > 0 || !doorwayToOpen.PowerSupply)
return false;
if (doorwayToOpen == null) return false;

characterManager.SetPlayerState(player, PlayerStateType.OpeningTheDoorway, doorwayToOpen);
int startTime = doorwayToOpen.OpenStartTime = gameMap.Timer.nowTime();
long stateNum = player.SetPlayerState(PlayerStateType.OpeningTheDoorway, doorwayToOpen);
if (stateNum == -1) return false;
new Thread
(
() =>
{
//player.ThreadNum.WaitOne();
Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree);

if (doorwayToOpen.OpenStartTime == startTime)
lock (player.ActionLock)
{
doorwayToOpen.OpenDegree = GameData.degreeOfOpenedDoorway;
player.SetPlayerStateNaturally();
if (stateNum == player.StateNum)
{
player.SetPlayerStateNaturally();
doorwayToOpen.FinishOpenning();
}
}
}

@@ -203,8 +205,8 @@ namespace Gaming
(
() =>
{
characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated);
characterManager.SetPlayerState(player, PlayerStateType.Treating);
playerTreated.SetPlayerState(PlayerStateType.Treated);
player.SetPlayerState(PlayerStateType.Treating);
long threadNum = player.StateNum;

new FrameRateTaskExecutor<int>(
@@ -212,15 +214,15 @@ namespace Gaming
loopToDo: () =>
{
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
characterManager.SetPlayerState(playerTreated);
playerTreated.SetPlayerState();
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0
)
.Start();

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

new Thread
@@ -259,14 +261,14 @@ namespace Gaming
{
if (playerRescued.TimeOfRescue >= GameData.basicTimeOfRescue)
{
characterManager.SetPlayerState(playerRescued);
playerRescued.SetPlayerState();
playerRescued.HP = playerRescued.MaxHp / 2;
player.AddScore(GameData.StudentScoreRescue);
}
else
characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted);
playerRescued.SetPlayerState(PlayerStateType.Addicted);
}
if (threadNum == player.StateNum) characterManager.SetPlayerState(player);
if (threadNum == player.StateNum) player.SetPlayerState();
playerRescued.TimeOfRescue = 0;
}
)
@@ -283,7 +285,7 @@ namespace Gaming
if (chestToOpen == null || chestToOpen.OpenStartTime > 0)
return false;

characterManager.SetPlayerState(player, PlayerStateType.OpeningTheChest, chestToOpen);
player.SetPlayerState(PlayerStateType.OpeningTheChest, chestToOpen);
int startTime = gameMap.Timer.nowTime();
chestToOpen.Open(startTime, player);
new Thread
@@ -315,7 +317,7 @@ namespace Gaming
Window? windowForClimb = (Window?)gameMap.OneForInteractInACross(player.Position, GameObjType.Window);
if (windowForClimb == null) return false;

long stateNum = characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows, windowForClimb);
long stateNum = player.SetPlayerState(PlayerStateType.ClimbingThroughWindows, windowForClimb);
if (stateNum == -1) return false;

XY windowToPlayer = new(
@@ -371,7 +373,7 @@ namespace Gaming
{
if (stateNum == player.StateNum)
{
characterManager.SetPlayerState(player);
player.SetPlayerState();
windowForClimb.FinishClimbing();
}
}
@@ -414,7 +416,7 @@ namespace Gaming
}
if (!flag) return false;

characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor);
player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor);
long threadNum = player.StateNum;
new Thread
(
@@ -436,7 +438,7 @@ namespace Gaming
doorToLock.IsOpen = (!doorToLock.IsOpen);
}
if (threadNum == player.StateNum)
characterManager.SetPlayerState(player);
player.SetPlayerState();
doorToLock.OpenOrLockDegree = 0;
}



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

@@ -200,7 +200,7 @@ namespace Gaming

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

new Thread
@@ -221,7 +221,7 @@ namespace Gaming
{
if (threadNum == player.StateNum)
{
characterManager.SetPlayerState(player);
player.SetPlayerState();
}
else TryRemoveBullet(bullet);
}


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

@@ -17,65 +17,6 @@ namespace Gaming
this.gameMap = gameMap;
}

public long SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (player.ActionLock)
{
PlayerStateType nowPlayerState = player.PlayerState;
if (nowPlayerState == value) return -1;
switch (nowPlayerState)
{
case PlayerStateType.Escaped:
case PlayerStateType.Deceased:
return -1;

case PlayerStateType.Addicted:
if (value == PlayerStateType.Rescued)
return player.ChangePlayerStateInOneThread(value, gameObj);
else if (value == PlayerStateType.Null)
return player.ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Rescued:
if (value == PlayerStateType.Addicted)
return player.ChangePlayerStateInOneThread(value, gameObj);
else if (value == PlayerStateType.Null)
return player.ChangePlayerState(value, gameObj);
else return -1;

case PlayerStateType.TryingToAttack:
case PlayerStateType.Stunned:
case PlayerStateType.Charmed:
case PlayerStateType.Swinging:
if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows)
return player.ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.ClimbingThroughWindows:
if (value != PlayerStateType.Moving)
{
Window window = (Window)player.WhatInteractingWith!;
window.FinishClimbing();
if (window.Stage.x == 0)
player.ThreadNum.Release();
else player.ReSetPos(window.Stage);
return player.ChangePlayerState(value, gameObj);
}
else return -1;

case PlayerStateType.OpeningTheChest:
((Chest)player.WhatInteractingWith!).StopOpen();
return player.ChangePlayerState(value, gameObj);
case PlayerStateType.OpeningTheDoorway:
Doorway doorway = (Doorway)player.WhatInteractingWith!;
doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime;
doorway.OpenStartTime = 0;
return player.ChangePlayerState(value, gameObj);

default:
return player.ChangePlayerState(value, gameObj);
}
}
}

public Character? AddPlayer(XY pos, int teamID, int playerID, CharacterType characterType, Character? parent = null)
{
Character newPlayer;
@@ -268,7 +209,7 @@ namespace Gaming
return;
}
}
SetPlayerState(player, PlayerStateType.Addicted);
player.SetPlayerState(PlayerStateType.Addicted);
long threadNum = player.StateNum;
new Thread
(() =>
@@ -302,14 +243,14 @@ namespace Gaming
public long BeStunned(Character player, int time)
{
if (player.CharacterType == CharacterType.Robot) return -1;
long threadNum = SetPlayerState(player, PlayerStateType.Stunned);
long threadNum = player.SetPlayerState(PlayerStateType.Stunned);
if (threadNum == -1) return -1;
new Thread
(() =>
{
Thread.Sleep(time);
if (threadNum == player.StateNum)
SetPlayerState(player);
player.SetPlayerState();
}
)
{ IsBackground = true }.Start();
@@ -339,7 +280,6 @@ namespace Gaming
#if DEBUG
Debugger.Output(student, "is being shot!");
#endif
if (student.NoHp()) return; // 原来已经死了
if (!bullet.Parent!.IsGhost()) return;

if (student.CharacterType == CharacterType.StraightAStudent)
@@ -347,6 +287,9 @@ namespace Gaming
((WriteAnswers)student.FindIActiveSkill(ActiveSkillType.WriteAnswers)).DegreeOfMeditation = 0;
}
student.SetDegreeOfTreatment0();

if (student.NoHp()) return; // 原来已经死了

#if DEBUG
Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString());
#endif
@@ -394,18 +337,22 @@ namespace Gaming
public bool BackSwing(Character player, int time)
{
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.StateNum;
long stateNum = player.SetPlayerState(PlayerStateType.Swinging);
if (stateNum == -1) return false;

new Thread
(() =>
{
player.ThreadNum.WaitOne();
Thread.Sleep(time);

if (threadNum == player.StateNum)
lock (player.ActionLock)
{
SetPlayerState(player);
if (stateNum == player.StateNum)
{
player.ThreadNum.Release();
player.SetPlayerStateNaturally();
}
}
}
)


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

@@ -111,8 +111,8 @@ namespace Gaming
Debugger.Output(player, "use robot!");
IActiveSkill activeSkill = player.FindIActiveSkill(ActiveSkillType.UseRobot);
activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true;
if (activeSkill.IsBeingUsed) characterManager.SetPlayerState(player, PlayerStateType.UsingSkill);
else characterManager.SetPlayerState(player);
if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill);
else player.SetPlayerState();
return true;
}

@@ -247,7 +247,7 @@ namespace Gaming
{
if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character))
{
characterManager.SetPlayerState(character);
character.SetPlayerState();
character.HP = GameData.RemainHpWhenAddLife;
((Student)character).TimeOfRescue = 0;
player.AddScore(GameData.StudentScoreRescue);


+ 9
- 0
logic/Preparation/Interface/IChest.cs View File

@@ -0,0 +1,9 @@
using Preparation.Utility;

namespace Preparation.Interface
{
public interface IChest : IGameObj
{
public void StopOpen();
}
}

+ 12
- 0
logic/Preparation/Interface/IDoorway.cs View File

@@ -0,0 +1,12 @@
using Preparation.Utility;

namespace Preparation.Interface
{
public interface IDoorway : IGameObj
{
public int OpenStartTime { get; }
public int OpenDegree { get; }
public bool StopOpenning();
public bool TryToOpen();
}
}

+ 1
- 1
logic/Preparation/Interface/IMoveable.cs View File

@@ -12,7 +12,7 @@ namespace Preparation.Interface
public bool IsRemoved { get; }
public bool IsAvailableForMove { get; }
public long StateNum { get; }
public Semaphore ThreadNum { get; set; }
public Semaphore ThreadNum { get; }
public long MovingSetPos(XY moveVec, long stateNum);
public void ReSetCanMove(bool value);
public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞


+ 12
- 0
logic/Preparation/Interface/IWindow.cs View File

@@ -0,0 +1,12 @@
using Preparation.Utility;

namespace Preparation.Interface
{
public interface IWindow : IGameObj
{
public void Enter2Stage(XY xy);
public bool TryToClimb(ICharacter character);
public XY Stage { get; }
public void FinishClimbing();
}
}

Loading…
Cancel
Save