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