Browse Source

Merge pull request #643 from shangfengh/new

refactor: 🔒 add locks
dev
Timothy Liu GitHub 2 years ago
parent
commit
fc4829286a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 242 additions and 215 deletions
  1. +6
    -1
      docs/GameRules.md
  2. +2
    -1
      logic/GameClass/GameObj/Bullet/BombedBullet.cs
  3. +1
    -4
      logic/GameClass/GameObj/Character/Character.Skill.cs
  4. +40
    -58
      logic/GameClass/GameObj/Character/Character.Student.cs
  5. +130
    -59
      logic/GameClass/GameObj/Character/Character.cs
  6. +0
    -3
      logic/GameClass/GameObj/GameObj.cs
  7. +0
    -2
      logic/GameClass/GameObj/Immovable.cs
  8. +15
    -33
      logic/GameClass/GameObj/Map/Door.cs
  9. +1
    -2
      logic/GameClass/GameObj/Map/Doorway.cs
  10. +10
    -3
      logic/GameClass/GameObj/Moveable.cs
  11. +19
    -32
      logic/Gaming/ActionManager.cs
  12. +6
    -6
      logic/Gaming/CharacterManager.cs
  13. +1
    -1
      logic/Gaming/Game.cs
  14. +4
    -4
      logic/Gaming/PropManager.cs
  15. +2
    -2
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  16. +2
    -1
      logic/Preparation/Interface/ICharacter.cs
  17. +0
    -1
      logic/Preparation/Interface/IGameObj.cs
  18. +1
    -0
      logic/Preparation/Interface/IMoveable.cs
  19. +1
    -1
      logic/Server/CopyInfo.cs
  20. +1
    -1
      logic/Server/RpcServices.cs

+ 6
- 1
docs/GameRules.md View File

@@ -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


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

@@ -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)


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

@@ -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!");
}
}

+ 40
- 58
logic/GameClass/GameObj/Character/Character.Student.cs View File

@@ -32,83 +32,60 @@ namespace GameClass.GameObj
/// </summary>
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;
}


+ 130
- 59
logic/GameClass/GameObj/Character/Character.cs View File

@@ -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();
/// <summary>
/// 装弹冷却
/// </summary>
@@ -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
/// <returns>攻击操作发出的子弹</returns>
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
/// 尝试减血
/// </summary>
/// <param name="sub">减血量</param>
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
/// 使用物品栏中的道具
/// </summary>
/// <returns>被使用的道具</returns>
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)
{


+ 0
- 3
logic/GameClass/GameObj/GameObj.cs View File

@@ -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; }


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

@@ -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)


+ 15
- 33
logic/GameClass/GameObj/Map/Door.cs View File

@@ -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)


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

@@ -1,5 +1,4 @@
using Google.Protobuf.WellKnownTypes;
using Preparation.Interface;
using Preparation.Interface;
using Preparation.Utility;
using System;



+ 10
- 3
logic/GameClass/GameObj/Moveable.cs View File

@@ -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<actionLock
@@ -52,13 +52,19 @@ namespace GameClass.GameObj
}
}

public override XY FacingDirection
protected XY facingDirection = new(1, 0);
public XY FacingDirection
{
get
{
lock (actionLock)
return facingDirection;
}
set
{
lock (actionLock)
facingDirection = value;
}
}

private int isMoving = 0;
@@ -127,7 +133,8 @@ namespace GameClass.GameObj
/// <summary>
/// 原初移动速度
/// </summary>
public int OrgMoveSpeed { get; protected set; }
protected int orgMoveSpeed;
public int OrgMoveSpeed => orgMoveSpeed;

/* /// <summary>
/// 复活时数据重置


+ 19
- 32
logic/Gaming/ActionManager.cs View File

@@ -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<int>(
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();
}
}


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

@@ -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);


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

@@ -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)


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

@@ -17,11 +17,11 @@ namespace Gaming
private readonly CharacterManager characterManager;
private readonly List<XY> 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;



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

@@ -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;
}


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

@@ -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; }


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

@@ -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; }


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

@@ -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; }


+ 1
- 1
logic/Server/CopyInfo.cs View File

@@ -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
}


+ 1
- 1
logic/Server/RpcServices.cs View File

@@ -305,7 +305,7 @@ namespace Server
public override Task<BoolRes> 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)


Loading…
Cancel
Save