diff --git a/docs/GameRules.md b/docs/GameRules.md
index 6511cf9..e007606 100644
--- a/docs/GameRules.md
+++ b/docs/GameRules.md
@@ -277,7 +277,12 @@ $$
- 主动技能
0. 惩罚 Punish
- CD:45s
- - “使用瞬间,在视野距离/3范围内(不是可视范围)的翻窗、开锁门、攻击前后摇、使用技能期间的捣蛋鬼会被眩晕(3070+$\frac{500×已受伤害}{基本伤害(1500000)×2^{开局老师数量-1}}$)ms”
+ - 使用瞬间,在视野距离/3范围内(不是可视范围)的翻窗、开锁门、攻击前后摇、使用技能期间的捣蛋鬼会被眩晕
+
+ $$
+ (3070+\frac{500×已受伤害}{基本伤害(1500000)×2^{开局老师数量-1}})ms
+ $$
+
- 其眩晕得分为正常眩晕得分/2^开局老师数量-1^
1. 喝茶 HaveTea
- CD:90s
diff --git a/logic/GameClass/GameObj/Bullet/BombedBullet.cs b/logic/GameClass/GameObj/Bullet/BombedBullet.cs
index 492ecb8..8f3f327 100644
--- a/logic/GameClass/GameObj/Bullet/BombedBullet.cs
+++ b/logic/GameClass/GameObj/Bullet/BombedBullet.cs
@@ -8,7 +8,8 @@ namespace GameClass.GameObj
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
public long MappingID { get; }
- public Bullet bulletHasBombed;
+ public readonly Bullet bulletHasBombed;
+ public readonly XY facingDirection;
public BombedBullet(Bullet bullet) :
base(bullet.Position, bullet.Radius, GameObjType.BombedBullet)
diff --git a/logic/GameClass/GameObj/Character/Character.Skill.cs b/logic/GameClass/GameObj/Character/Character.Skill.cs
index f2d887e..b57c3a5 100644
--- a/logic/GameClass/GameObj/Character/Character.Skill.cs
+++ b/logic/GameClass/GameObj/Character/Character.Skill.cs
@@ -36,7 +36,7 @@ namespace GameClass.GameObj
this.buffManager = new BuffManager();
this.occupation = OccupationFactory.FindIOccupation(characterType);
this.MaxHp = this.hp = Occupation.MaxHp;
- this.MoveSpeed = this.OrgMoveSpeed = Occupation.MoveSpeed;
+ this.MoveSpeed = this.orgMoveSpeed = Occupation.MoveSpeed;
this.BulletOfPlayer = this.OriBulletOfPlayer = Occupation.InitBullet;
this.concealment = Occupation.Concealment;
this.alertnessRadius = Occupation.AlertnessRadius;
@@ -50,9 +50,6 @@ namespace GameClass.GameObj
{
this.ActiveSkillDictionary.Add(activeSkill, SkillFactory.FindActiveSkill(activeSkill));
}
-
- // UsePassiveSkill(); //这一过程放到gamestart时进行
-
Debugger.Output(this, "constructed!");
}
}
diff --git a/logic/GameClass/GameObj/Character/Character.Student.cs b/logic/GameClass/GameObj/Character/Character.Student.cs
index d0a4902..1b52f08 100644
--- a/logic/GameClass/GameObj/Character/Character.Student.cs
+++ b/logic/GameClass/GameObj/Character/Character.Student.cs
@@ -32,83 +32,60 @@ namespace GameClass.GameObj
///
protected readonly int orgFixSpeed;
+ private readonly object treatLock = new();
protected int treatSpeed = GameData.basicTreatSpeed;
public int TreatSpeed
{
- get => treatSpeed;
+ get
+ {
+ lock (treatLock)
+ return treatSpeed;
+ }
set
{
- lock (gameObjLock)
+ lock (treatLock)
{
treatSpeed = value;
}
}
}
- public int OrgTreatSpeed { get; protected set; }
+ protected readonly int orgTreatSpeed;
- public int MaxGamingAddiction { get; protected set; }
- private int gamingAddiction;
- public int GamingAddiction
+ private readonly object addictionLock = new();
+ private int maxGamingAddiction;
+ public int MaxGamingAddiction
{
- get => gamingAddiction;
- set
+ get
{
- if (value > 0)
- lock (gameObjLock)
- gamingAddiction = value <= MaxGamingAddiction ? value : MaxGamingAddiction;
- else
- lock (gameObjLock)
- gamingAddiction = 0;
+ lock (addictionLock)
+ return maxGamingAddiction;
}
- }
-
- private int selfHealingTimes = 1;//剩余的自愈次数
- public int SelfHealingTimes
- {
- get => selfHealingTimes;
- set
+ protected set
{
- lock (gameObjLock)
- selfHealingTimes = (value > 0) ? value : 0;
- }
- }
-
- private int degreeOfTreatment = 0;
- public int DegreeOfTreatment
- {
- get => degreeOfTreatment;
- private set
- {
- degreeOfTreatment = value;
+ lock (addictionLock)
+ {
+ if (value < gamingAddiction) gamingAddiction = value;
+ maxGamingAddiction = value;
+ }
}
}
- public void SetDegreeOfTreatment0()
- {
- DegreeOfTreatment = 0;
- }
- public bool SetDegreeOfTreatment(int value, Student whoTreatYou)
+ private int gamingAddiction;
+ public int GamingAddiction
{
- if (value <= 0) { degreeOfTreatment = 0; return false; }
- if (value >= MaxHp - HP)
+ get
{
- whoTreatYou.AddScore(GameData.StudentScoreTreat(MaxHp - HP));
- HP = MaxHp;
- degreeOfTreatment = 0;
- return true;
+ lock (addictionLock)
+ return gamingAddiction;
}
- if (value >= GameData.basicTreatmentDegree)
+ set
{
- whoTreatYou.AddScore(GameData.StudentScoreTreat(GameData.basicTreatmentDegree));
- HP += GameData.basicTreatmentDegree;
- DegreeOfTreatment = 0;
- return true;
+ if (value > 0)
+ lock (addictionLock)
+ gamingAddiction = value <= maxGamingAddiction ? value : maxGamingAddiction;
+ else
+ lock (addictionLock)
+ gamingAddiction = 0;
}
- DegreeOfTreatment = value;
- return false;
- }
- public bool AddDegreeOfTreatment(int value, Student student)
- {
- return SetDegreeOfTreatment(value + degreeOfTreatment, student);
}
private int timeOfRescue = 0;
@@ -128,19 +105,24 @@ namespace GameClass.GameObj
public Student(XY initPos, int initRadius, CharacterType characterType) : base(initPos, initRadius, characterType)
{
this.orgFixSpeed = this.fixSpeed = ((IStudentType)Occupation).FixSpeed;
- this.TreatSpeed = this.OrgTreatSpeed = ((IStudentType)Occupation).TreatSpeed;
+ this.TreatSpeed = this.orgTreatSpeed = ((IStudentType)Occupation).TreatSpeed;
this.MaxGamingAddiction = ((IStudentType)Occupation).MaxGamingAddiction;
}
}
public class Golem : Student, IGolem
{
+ private readonly object parentLock = new();
private Character? parent; // 主人
public Character? Parent
{
- get => parent;
+ get
+ {
+ lock (parentLock)
+ return parent;
+ }
set
{
- lock (gameObjLock)
+ lock (parentLock)
{
parent = value;
}
diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs
index 3e6b937..c9c6153 100644
--- a/logic/GameClass/GameObj/Character/Character.cs
+++ b/logic/GameClass/GameObj/Character/Character.cs
@@ -8,15 +8,8 @@ namespace GameClass.GameObj
{
public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终了
{
-
- private readonly ReaderWriterLockSlim hpReaderWriterLock = new();
- public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock;
- private readonly object vampireLock = new();
- public object VampireLock => vampire;
- private readonly object inventoryLock = new();
- public object InventoryLock => inventoryLock;
-
#region 装弹、攻击相关的基本属性及方法
+ private readonly object attackLock = new();
///
/// 装弹冷却
///
@@ -25,7 +18,7 @@ namespace GameClass.GameObj
{
get
{
- lock (actionLock)
+ lock (attackLock)
{
return cd;
}
@@ -36,7 +29,7 @@ namespace GameClass.GameObj
{
get
{
- lock (actionLock)
+ lock (attackLock)
return orgCD;
}
}
@@ -47,14 +40,14 @@ namespace GameClass.GameObj
{
get
{
- lock (actionLock)
+ lock (attackLock)
{
return bulletOfPlayer;
}
}
set
{
- lock (actionLock)
+ lock (attackLock)
{
bulletOfPlayer = value;
cd = orgCD = (BulletFactory.BulletCD(value));
@@ -69,7 +62,7 @@ namespace GameClass.GameObj
{
get
{
- lock (actionLock)
+ lock (attackLock)
{
return maxBulletNum;
}
@@ -78,17 +71,17 @@ namespace GameClass.GameObj
private int bulletNum;
private int updateTimeOfBulletNum = 0;
- public int UpdateBulletNum(int time)
+ public int UpdateBulletNum(int time)//通过该函数获取真正的bulletNum
{
- lock (actionLock)
+ lock (attackLock)
{
- if (bulletNum < maxBulletNum)
+ if (bulletNum < maxBulletNum && time - updateTimeOfBulletNum >= cd)
{
int add = Math.Min(maxBulletNum - bulletNum, (time - updateTimeOfBulletNum) / cd);
updateTimeOfBulletNum += add * cd;
return (bulletNum += add);
}
- return maxBulletNum;
+ return bulletNum;
}
}
@@ -98,7 +91,7 @@ namespace GameClass.GameObj
/// 攻击操作发出的子弹
public Bullet? Attack(double angle, int time)
{
- lock (actionLock)
+ lock (attackLock)
{
if (bulletOfPlayer == BulletType.Null)
return null;
@@ -115,7 +108,7 @@ namespace GameClass.GameObj
Bullet? bullet = BulletFactory.GetBullet(this, res, this.bulletOfPlayer);
if (bullet == null) return null;
if (TryAddAp()) bullet.AddAP(GameData.ApPropAdd);
- facingDirection = new(angle, bullet.AttackDistance);
+ FacingDirection = new(angle, bullet.AttackDistance);
return bullet;
}
else
@@ -140,7 +133,7 @@ namespace GameClass.GameObj
if (!(bouncer?.TeamID == this.TeamID))
{
if (hasSpear || !HasShield)
- _ = TrySubHp(subHP);
+ _ = SubHp(subHP);
if (hp <= 0)
TryActivatingLIFE();
}
@@ -194,6 +187,9 @@ namespace GameClass.GameObj
}
#endregion
#region 血量相关的基本属性及方法
+ private readonly ReaderWriterLockSlim hpReaderWriterLock = new();
+ public ReaderWriterLockSlim HPReadWriterLock => hpReaderWriterLock;
+
private long maxHp;
public long MaxHp
{
@@ -222,7 +218,8 @@ namespace GameClass.GameObj
HPReadWriterLock.ExitWriteLock();
}
}
- } // 最大血量
+ }
+ // 最大血量
protected long hp;
public long HP
{
@@ -238,22 +235,23 @@ namespace GameClass.GameObj
HPReadWriterLock.ExitReadLock();
}
}
- set
+ }
+
+ public long SetHP(long value)
+ {
+ HPReadWriterLock.EnterWriteLock();
+ try
{
- HPReadWriterLock.EnterWriteLock();
- try
- {
- if (value > 0)
- {
- hp = value <= maxHp ? value : maxHp;
- }
- else
- hp = 0;
- }
- finally
+ if (value > 0)
{
- HPReadWriterLock.ExitWriteLock();
+ return hp = value <= maxHp ? value : maxHp;
}
+ else
+ return hp = 0;
+ }
+ finally
+ {
+ HPReadWriterLock.ExitWriteLock();
}
}
@@ -261,7 +259,7 @@ namespace GameClass.GameObj
/// 尝试减血
///
/// 减血量
- public long TrySubHp(long sub)
+ public long SubHp(long sub)
{
HPReadWriterLock.EnterWriteLock();
try
@@ -284,6 +282,23 @@ namespace GameClass.GameObj
}
}
+ public long AddHP(long add)
+ {
+ HPReadWriterLock.EnterWriteLock();
+ try
+ {
+ long previousHp = hp;
+ return (hp = (hp + add > maxHp) ? maxHp : hp + add) - previousHp;
+ }
+ finally
+ {
+ HPReadWriterLock.ExitWriteLock();
+ }
+ }
+
+ private readonly object vampireLock = new();
+ public object VampireLock => vampire;
+
private double vampire = 0; // 回血率:0-1之间
public double Vampire
{
@@ -306,8 +321,65 @@ namespace GameClass.GameObj
}
}
public double OriVampire { get; protected set; }
+
+ private readonly object treatLock = new();
+ private int degreeOfTreatment = 0;
+ public int DegreeOfTreatment
+ {
+ get
+ {
+ HPReadWriterLock.EnterReadLock();
+ try
+ {
+ return degreeOfTreatment;
+ }
+ finally
+ {
+ HPReadWriterLock.ExitReadLock();
+ }
+ }
+ }
+ public void SetDegreeOfTreatment0()
+ {
+ HPReadWriterLock.EnterWriteLock();
+ try
+ {
+ degreeOfTreatment = 0;
+ }
+ finally
+ {
+ HPReadWriterLock.ExitWriteLock();
+ }
+ }
+ public bool AddDegreeOfTreatment(int value, Student whoTreatYou)
+ {
+ HPReadWriterLock.EnterWriteLock();
+ try
+ {
+ if (value >= maxHp - hp)
+ {
+ whoTreatYou.AddScore(GameData.StudentScoreTreat(maxHp - hp));
+ hp = maxHp;
+ degreeOfTreatment = 0;
+ return true;
+ }
+ if (value >= GameData.basicTreatmentDegree)
+ {
+ whoTreatYou.AddScore(GameData.StudentScoreTreat(GameData.basicTreatmentDegree));
+ hp += GameData.basicTreatmentDegree;
+ degreeOfTreatment = 0;
+ return true;
+ }
+ degreeOfTreatment = value;
+ }
+ finally
+ {
+ HPReadWriterLock.ExitWriteLock();
+ }
+ return false;
+ }
#endregion
- #region 状态相关的基本属性与方法
+ #region 查询状态相关的基本属性与方法
private PlayerStateType playerState = PlayerStateType.Null;
public PlayerStateType PlayerState
{
@@ -371,6 +443,8 @@ namespace GameClass.GameObj
|| playerState == PlayerStateType.Stunned || playerState == PlayerStateType.Charmed
|| playerState == PlayerStateType.Null || playerState == PlayerStateType.Moving);
}
+ #endregion
+ #region 更改状态相关的属性和方法
private GameObj? whatInteractingWith = null;
public GameObj? WhatInteractingWith
{
@@ -383,19 +457,6 @@ namespace GameClass.GameObj
}
}
- public bool StartThread(long stateNum, RunningStateType runningState)
- {
- lock (ActionLock)
- {
- if (this.StateNum == stateNum)
- {
- this.runningState = runningState;
- return true;
- }
- }
- return false;
- }
-
private long ChangePlayerState(RunningStateType running, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
//只能被SetPlayerState引用
@@ -492,13 +553,7 @@ namespace GameClass.GameObj
if (value == PlayerStateType.Rescued) return -1;
Door door = (Door)lastObj!;
door.StopOpen();
- ReleaseTool(door.DoorNum switch
- {
- 3 => PropType.Key3,
- 5 => PropType.Key5,
- _ => PropType.Key6,
- }
- );
+ ReleaseTool(door.KeyType);
return ChangePlayerState(runningState, value, gameObj);
case PlayerStateType.UsingSkill:
{
@@ -573,6 +628,19 @@ namespace GameClass.GameObj
}
}
+ public bool StartThread(long stateNum, RunningStateType runningState)
+ {
+ lock (ActionLock)
+ {
+ if (this.StateNum == stateNum)
+ {
+ this.runningState = runningState;
+ return true;
+ }
+ }
+ return false;
+ }
+
public bool TryToRemoveFromGame(PlayerStateType playerStateType)
{
lock (actionLock)
@@ -619,6 +687,9 @@ namespace GameClass.GameObj
}
#region 道具和buff相关属性、方法
+ private readonly object inventoryLock = new();
+ public object InventoryLock => inventoryLock;
+
private Gadget[] propInventory = new Gadget[GameData.maxNumOfPropInPropInventory]
{new NullProp(), new NullProp(),new NullProp() };
public Gadget[] PropInventory
@@ -639,7 +710,7 @@ namespace GameClass.GameObj
/// 使用物品栏中的道具
///
/// 被使用的道具
- public Gadget UseProp(int indexing)
+ public Gadget ConsumeProp(int indexing)
{
if (indexing < 0 || indexing >= GameData.maxNumOfPropInPropInventory)
return new NullProp();
@@ -652,7 +723,7 @@ namespace GameClass.GameObj
}
}
- public Gadget UseProp(PropType propType)
+ public Gadget ConsumeProp(PropType propType)
{
if (propType == PropType.Null)
{
@@ -687,7 +758,7 @@ namespace GameClass.GameObj
return new NullProp();
}
- public bool UseTool(PropType propType)
+ public bool UseTool(PropType propType)//占用道具,使其不能重复使用和被消耗
{
lock (inventoryLock)
{
diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs
index c528b52..0e070e2 100644
--- a/logic/GameClass/GameObj/GameObj.cs
+++ b/logic/GameClass/GameObj/GameObj.cs
@@ -26,9 +26,6 @@ namespace GameClass.GameObj
protected XY position;
public abstract XY Position { get; }
- protected XY facingDirection = new(1, 0);
- public abstract XY FacingDirection { get; }
-
public abstract bool CanMove { get; }
public abstract bool IsRigid { get; }
diff --git a/logic/GameClass/GameObj/Immovable.cs b/logic/GameClass/GameObj/Immovable.cs
index 8820399..f6f496b 100644
--- a/logic/GameClass/GameObj/Immovable.cs
+++ b/logic/GameClass/GameObj/Immovable.cs
@@ -7,8 +7,6 @@ namespace GameClass.GameObj
public override XY Position => position;
- public override XY FacingDirection => facingDirection;
-
public override bool CanMove => false;
public Immovable(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
diff --git a/logic/GameClass/GameObj/Map/Door.cs b/logic/GameClass/GameObj/Map/Door.cs
index ab459b5..0f03d72 100644
--- a/logic/GameClass/GameObj/Map/Door.cs
+++ b/logic/GameClass/GameObj/Map/Door.cs
@@ -13,23 +13,16 @@ namespace GameClass.GameObj
public Door(XY initPos, PlaceType placeType) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Door)
{
- switch (placeType)
+ keyType = placeType switch
{
- case PlaceType.Door3:
- doorNum = 3;
- break;
- case PlaceType.Door5:
- doorNum = 5;
- break;
- case PlaceType.Door6:
- default:
- doorNum = 6;
- break;
- }
+ PlaceType.Door3 => PropType.Key3,
+ PlaceType.Door5 => PropType.Key5,
+ _ => PropType.Key6,
+ };
}
- private readonly int doorNum;
- public int DoorNum => doorNum;
+ private readonly PropType keyType;
+ public PropType KeyType => keyType;
public override bool IsRigid => !isOpen;
public override ShapeType Shape => ShapeType.Square;
@@ -57,17 +50,11 @@ namespace GameClass.GameObj
private int lockDegree = 0;
public int LockDegree
{
- get
- {
- lock (gameObjLock)
- return lockDegree;
- }
- set
- {
- value = (value > GameData.degreeOfLockingOrOpeningTheDoor) ? GameData.degreeOfLockingOrOpeningTheDoor : value;
- lock (gameObjLock)
- lockDegree = value;
- }
+ get => Interlocked.CompareExchange(ref lockDegree, -1, -1);
+ }
+ public int AddLockDegree(int add)
+ {
+ return Interlocked.Add(ref lockDegree, add);
}
private long openStartTime = 0;
@@ -119,7 +106,7 @@ namespace GameClass.GameObj
{
if (!isOpen) return false;
if (whoLockOrOpen != null) return false;
- lockDegree = 0;
+ Interlocked.Exchange(ref lockDegree, 0);
whoLockOrOpen = character;
return true;
}
@@ -128,7 +115,7 @@ namespace GameClass.GameObj
{
lock (gameObjLock)
{
- if (lockDegree >= GameData.degreeOfLockingOrOpeningTheDoor)
+ if (LockDegree >= GameData.degreeOfLockingOrOpeningTheDoor)
isOpen = false;
whoLockOrOpen = null;
}
@@ -157,12 +144,7 @@ namespace GameClass.GameObj
{
if (character.PlayerState == PlayerStateType.OpeningTheDoor)
{
- character.ReleaseTool(DoorNum switch
- {
- 3 => PropType.Key3,
- 5 => PropType.Key5,
- _ => PropType.Key6,
- });
+ character.ReleaseTool(KeyType);
character.SetPlayerStateNaturally();
}
else if (character.PlayerState == PlayerStateType.LockingTheDoor)
diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs
index 1373fd8..d5e70ca 100644
--- a/logic/GameClass/GameObj/Map/Doorway.cs
+++ b/logic/GameClass/GameObj/Map/Doorway.cs
@@ -1,5 +1,4 @@
-using Google.Protobuf.WellKnownTypes;
-using Preparation.Interface;
+using Preparation.Interface;
using Preparation.Utility;
using System;
diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs
index 9d3cd00..41f1ea5 100644
--- a/logic/GameClass/GameObj/Moveable.cs
+++ b/logic/GameClass/GameObj/Moveable.cs
@@ -8,7 +8,7 @@ namespace GameClass.GameObj
{
protected readonly object actionLock = new();
public object ActionLock => actionLock;
- //player.actionLock>其他.actionLock
+ //player.actionLock>其他.actionLock/其他Lock,应当避免两个player的actionlock互锁
private readonly ReaderWriterLockSlim moveReaderWriterLock = new();
public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock;
//规定moveReaderWriterLock
/// 原初移动速度
///
- public int OrgMoveSpeed { get; protected set; }
+ protected int orgMoveSpeed;
+ public int OrgMoveSpeed => orgMoveSpeed;
/* ///
/// 复活时数据重置
diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs
index 89d930e..585d7ff 100644
--- a/logic/Gaming/ActionManager.cs
+++ b/logic/Gaming/ActionManager.cs
@@ -321,7 +321,7 @@ namespace Gaming
if (playerRescued.AddTimeOfRescue(GameData.checkInterval))
{
playerRescued.SetPlayerStateNaturally();
- playerRescued.HP = playerRescued.MaxHp / 2;
+ playerRescued.SetHP(playerRescued.MaxHp / 2);
player.AddScore(GameData.StudentScoreRescue);
return false;
}
@@ -479,19 +479,12 @@ namespace Gaming
Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door);
if (doorToLock == null) return false;
- PropType propType = doorToLock.DoorNum switch
- {
- 3 => PropType.Key3,
- 5 => PropType.Key5,
- _ => PropType.Key6,
- };
-
- if (!player.UseTool(propType)) return false;
+ if (!player.UseTool(doorToLock.KeyType)) return false;
long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.LockingTheDoor, doorToLock);
if (stateNum == -1)
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToLock.KeyType);
return false;
}
@@ -502,25 +495,26 @@ namespace Gaming
player.ThreadNum.WaitOne();
if (!player.StartThread(stateNum, RunningStateType.RunningActively))
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToLock.KeyType);
player.ThreadNum.Release();
return;
}
if (!doorToLock.TryLock(player))
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToLock.KeyType);
player.ResetPlayerState(stateNum);
player.ThreadNum.Release();
return;
}
Thread.Sleep(GameData.checkInterval);
new FrameRateTaskExecutor(
- loopCondition: () => stateNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.LockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
+ loopCondition: () => stateNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
if ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) != null)
return false;
- doorToLock.LockDegree += GameData.checkInterval * player.SpeedOfOpeningOrLocking;
+ if (doorToLock.AddLockDegree(GameData.checkInterval * player.SpeedOfOpeningOrLocking) >= GameData.basicSpeedOfOpeningOrLocking)
+ return false;
return true;
},
timeInterval: GameData.checkInterval,
@@ -528,7 +522,7 @@ namespace Gaming
)
.Start();
doorToLock.StopLock();
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToLock.KeyType);
player.ThreadNum.Release();
player.ResetPlayerState(stateNum);
}
@@ -541,22 +535,15 @@ namespace Gaming
public bool OpenDoor(Character player)
{
if (player.CharacterType == CharacterType.Robot) return false;
- Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door);
- if (doorToLock == null) return false;
-
- PropType propType = doorToLock.DoorNum switch
- {
- 3 => PropType.Key3,
- 5 => PropType.Key5,
- _ => PropType.Key6,
- };
+ Door? doorToOpen = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door);
+ if (doorToOpen == null) return false;
- if (!player.UseTool(propType)) return false;
+ if (!player.UseTool(doorToOpen.KeyType)) return false;
- long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.OpeningTheDoor, doorToLock);
+ long stateNum = player.SetPlayerState(RunningStateType.Waiting, PlayerStateType.OpeningTheDoor, doorToOpen);
if (stateNum == -1)
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToOpen.KeyType);
return false;
}
@@ -567,13 +554,13 @@ namespace Gaming
player.ThreadNum.WaitOne();
if (!player.StartThread(stateNum, RunningStateType.RunningSleepily))
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToOpen.KeyType);
player.ThreadNum.Release();
return;
}
- if (!doorToLock.TryOpen(player))
+ if (!doorToOpen.TryOpen(player))
{
- player.ReleaseTool(propType);
+ player.ReleaseTool(doorToOpen.KeyType);
if (player.ResetPlayerState(stateNum))
player.ThreadNum.Release();
return;
@@ -582,8 +569,8 @@ namespace Gaming
if (player.ResetPlayerState(stateNum))
{
- doorToLock.StopOpen();
- player.ReleaseTool(propType);
+ doorToOpen.StopOpen();
+ player.ReleaseTool(doorToOpen.KeyType);
player.ThreadNum.Release();
}
}
diff --git a/logic/Gaming/CharacterManager.cs b/logic/Gaming/CharacterManager.cs
index a95ca20..1db03b5 100644
--- a/logic/Gaming/CharacterManager.cs
+++ b/logic/Gaming/CharacterManager.cs
@@ -326,12 +326,12 @@ namespace Gaming
{
if (bullet.HasSpear)
{
- long subHp = student.TrySubHp(bullet.AP);
+ long subHp = student.SubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear);
- bullet.Parent.HP = (long)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
+ bullet.Parent.AddHP((long)bullet.Parent.Vampire * subHp);
}
else return;
}
@@ -340,14 +340,14 @@ namespace Gaming
long subHp;
if (bullet.HasSpear)
{
- subHp = student.TrySubHp(bullet.AP + GameData.ApSpearAdd);
+ subHp = student.SubHp(bullet.AP + GameData.ApSpearAdd);
#if DEBUG
Debugger.Output(this, "is being shot with Spear! Now his hp is" + student.HP.ToString());
#endif
}
else
{
- subHp = student.TrySubHp(bullet.AP);
+ subHp = student.SubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
@@ -358,7 +358,7 @@ namespace Gaming
student.AddScore(subHp * GameData.factorOfScoreWhenTeacherAttacked / GameData.basicApOfGhost / FactorTeacher);
}
- bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * subHp));
+ bullet.Parent.AddHP((long)(bullet.Parent.Vampire * subHp));
}
if (student.HP <= 0)
student.TryActivatingLIFE(); // 如果有复活甲
@@ -393,7 +393,7 @@ namespace Gaming
for (int i = 0; i < GameData.maxNumOfPropInPropInventory; i++)
{
- Gadget? prop = player.UseProp(i);
+ Gadget? prop = player.ConsumeProp(i);
if (prop != null)
{
prop.ReSetPos(player.Position);
diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs
index 04af9bd..c9a7268 100644
--- a/logic/Gaming/Game.cs
+++ b/logic/Gaming/Game.cs
@@ -238,7 +238,7 @@ namespace Gaming
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
- propManager.UseProp(player, propType);
+ propManager.ConsumeProp(player, propType);
}
}
public void ThrowProp(long playerID, PropType propType = PropType.Null)
diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs
index 5127f64..75426af 100644
--- a/logic/Gaming/PropManager.cs
+++ b/logic/Gaming/PropManager.cs
@@ -17,11 +17,11 @@ namespace Gaming
private readonly CharacterManager characterManager;
private readonly List availableCellForGenerateProp;
- public void UseProp(Character player, PropType propType)
+ public void ConsumeProp(Character player, PropType propType)
{
if (player.CharacterType == CharacterType.Robot || player.IsRemoved)
return;
- Gadget prop = player.UseProp(propType);
+ Gadget prop = player.ConsumeProp(propType);
switch (prop.GetPropType())
{
case PropType.ShieldOrSpear:
@@ -46,7 +46,7 @@ namespace Gaming
if (!player.IsGhost())
if (player.HP < player.MaxHp)
{
- player.HP += GameData.basicTreatmentDegree / 2;
+ player.AddHP(GameData.basicTreatmentDegree / 2);
player.AddScore(GameData.ScorePropAddHp);
}
else player.AddAp(GameData.PropDuration);
@@ -117,7 +117,7 @@ namespace Gaming
{
if (!gameMap.Timer.IsGaming || player.IsRemoved)
return;
- Gadget prop = player.UseProp(propType);
+ Gadget prop = player.ConsumeProp(propType);
if (prop.GetPropType() == PropType.Null)
return;
diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
index 8f6d003..48502e9 100644
--- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
+++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
@@ -421,7 +421,7 @@ namespace Gaming
if ((character.PlayerState == PlayerStateType.Addicted) && gameMap.CanSee(player, character))
{
character.SetPlayerStateNaturally();
- character.HP = GameData.RemainHpWhenAddLife;
+ character.SetHP(GameData.RemainHpWhenAddLife);
((Student)character).SetTimeOfRescue(0);
player.AddScore(GameData.StudentScoreRescue);
break;
@@ -452,7 +452,7 @@ namespace Gaming
if ((character.HP < character.MaxHp) && gameMap.CanSee(player, character))
{
player.AddScore(GameData.StudentScoreTreat(GameData.addHpWhenEncourage));
- character.HP += GameData.addHpWhenEncourage;
+ character.AddHP(GameData.addHpWhenEncourage);
((Student)character).SetDegreeOfTreatment0();
break;
}
diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs
index 9fe6927..07f0b93 100644
--- a/logic/Preparation/Interface/ICharacter.cs
+++ b/logic/Preparation/Interface/ICharacter.cs
@@ -6,7 +6,8 @@ namespace Preparation.Interface
public interface ICharacter : IMoveable
{
public long TeamID { get; }
- public long HP { get; set; }
+ public long HP { get; }
+ public long AddHP(long add);
public long Score { get; }
public void AddScore(long add);
public double Vampire { get; }
diff --git a/logic/Preparation/Interface/IGameObj.cs b/logic/Preparation/Interface/IGameObj.cs
index 017226f..74699e5 100644
--- a/logic/Preparation/Interface/IGameObj.cs
+++ b/logic/Preparation/Interface/IGameObj.cs
@@ -7,7 +7,6 @@ namespace Preparation.Interface
public GameObjType Type { get; }
public long ID { get; }
public XY Position { get; } // if Square, Pos equals the center
- public XY FacingDirection { get; }
public bool IsRigid { get; }
public ShapeType Shape { get; }
public bool CanMove { get; }
diff --git a/logic/Preparation/Interface/IMoveable.cs b/logic/Preparation/Interface/IMoveable.cs
index ad87c31..6854d15 100644
--- a/logic/Preparation/Interface/IMoveable.cs
+++ b/logic/Preparation/Interface/IMoveable.cs
@@ -6,6 +6,7 @@ namespace Preparation.Interface
{
public interface IMoveable : IGameObj
{
+ public XY FacingDirection { get; set; }
object ActionLock { get; }
public int MoveSpeed { get; }
public bool IsMoving { get; set; }
diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs
index 9644826..d9d341a 100644
--- a/logic/Server/CopyInfo.cs
+++ b/logic/Server/CopyInfo.cs
@@ -203,7 +203,7 @@ namespace Server
Type = Transformation.ToBulletType(bombedBullet.bulletHasBombed.TypeOfBullet),
X = bombedBullet.bulletHasBombed.Position.x,
Y = bombedBullet.bulletHasBombed.Position.y,
- FacingDirection = bombedBullet.FacingDirection.Angle(),
+ FacingDirection = bombedBullet.facingDirection.Angle(),
MappingId = bombedBullet.MappingID,
BombRange = bombedBullet.bulletHasBombed.BulletBombRange
}
diff --git a/logic/Server/RpcServices.cs b/logic/Server/RpcServices.cs
index 34ec687..79d9317 100644
--- a/logic/Server/RpcServices.cs
+++ b/logic/Server/RpcServices.cs
@@ -305,7 +305,7 @@ namespace Server
public override Task UseProp(PropMsg request, ServerCallContext context)
{
#if DEBUG
- Console.WriteLine($"UseProp ID: {request.PlayerId}");
+ Console.WriteLine($"ConsumeProp ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)