diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs
index c36cf0b..ba33b4c 100644
--- a/logic/GameClass/GameObj/Character/Character.cs
+++ b/logic/GameClass/GameObj/Character/Character.cs
@@ -76,7 +76,7 @@ namespace GameClass.GameObj
&& playerState != PlayerStateType.IsAddicted && playerState != PlayerStateType.IsStunned
&& playerState != PlayerStateType.IsSwinging && playerState != PlayerStateType.IsTryingToAttack
&& playerState != PlayerStateType.IsClimbingThroughWindows);
- public bool InteractingWithMapWithoutMoving() => (playerState == PlayerStateType.IsLockingTheDoor || playerState == PlayerStateType.IsFixing || playerState == PlayerStateType.IsRummagingInTheChest);
+ public bool InteractingWithMapWithoutMoving() => (playerState == PlayerStateType.IsLockingTheDoor || playerState == PlayerStateType.IsFixing || playerState == PlayerStateType.IsOpeningTheChest);
public bool NullOrMoving() => (playerState == PlayerStateType.Null || playerState == PlayerStateType.IsMoving);
// private int deathCount = 0;
@@ -137,8 +137,8 @@ namespace GameClass.GameObj
}
}
- private Prop? propInventory;
- public Prop? PropInventory // 持有的道具
+ private Prop[] propInventory = new Prop[GameData.maxNumOfPropInPropInventory];
+ public Prop[] PropInventory
{
get => propInventory;
set
@@ -155,16 +155,30 @@ namespace GameClass.GameObj
/// 使用物品栏中的道具
///
/// 被使用的道具
- public Prop? UseProp()
+ public Prop? UseProp(int indexing)
{
+ if (indexing < 0 || indexing >= GameData.maxNumOfPropInPropInventory)
+ return null;
lock (gameObjLock)
{
- var oldProp = PropInventory;
- PropInventory = null;
- return oldProp;
+ Prop prop = propInventory[indexing];
+ PropInventory[indexing] = null;
+ return prop;
}
}
+ ///
+ /// 如果indexing==GameData.maxNumOfPropInPropInventory表明道具栏为满
+ ///
+ public int IndexingOfAddProp()
+ {
+ int indexing = 0;
+ for (; indexing < GameData.maxNumOfPropInPropInventory; ++indexing)
+ if (PropInventory[indexing] == null)
+ break;
+ return indexing;
+ }
+
///
/// 是否在隐身
///
diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs
new file mode 100644
index 0000000..975e1cf
--- /dev/null
+++ b/logic/GameClass/GameObj/Map/Chest.cs
@@ -0,0 +1,34 @@
+using Preparation.Utility;
+using System.Collections.Generic;
+
+namespace GameClass.GameObj
+{
+ ///
+ /// 箱子
+ ///
+ public class Chest : GameObj
+ {
+ public Chest(XY initPos) :
+ base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest)
+ {
+ this.place = PlaceType.Chest;
+ this.CanMove = false;
+ }
+ public override bool IsRigid => true;
+ public override ShapeType Shape => ShapeType.Square;
+
+ private Prop[] propInChest = new Prop[GameData.maxNumOfPropInChest];
+ public Prop[] PropInChest => propInChest;
+
+ private bool isOpen = false;
+ public bool IsOpen
+ {
+ get => isOpen;
+ set
+ {
+ lock (gameObjLock)
+ isOpen = value;
+ }
+ }
+ }
+}
diff --git a/logic/GameClass/GameObj/Prop.cs b/logic/GameClass/GameObj/Prop.cs
index 5ebcdbd..9e4fea2 100644
--- a/logic/GameClass/GameObj/Prop.cs
+++ b/logic/GameClass/GameObj/Prop.cs
@@ -12,7 +12,8 @@ namespace GameClass.GameObj
protected override bool IgnoreCollideExecutor(IGameObj targetObj)
{
- if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character)
+ if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet
+ || targetObj.Type == GameObjType.Character || targetObj.Type == GameObjType.Chest)
return true;
return false;
}
diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs
index d2f8b36..55dd75d 100644
--- a/logic/Gaming/AttackManager.cs
+++ b/logic/Gaming/AttackManager.cs
@@ -108,17 +108,16 @@ namespace Gaming
// gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock();
// }
- Prop? dropProp = null;
- if (player.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地
+ for (int i = 0; i < GameData.maxNumOfPropInPropInventory; i++)
{
- dropProp = player.PropInventory;
- XY res = GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell);
- dropProp.ReSetPos(res, gameMap.GetPlaceType(res));
+ Prop? prop = player.UseProp(i);
+ if (prop != null)
+ {
+ prop.ReSetPos(player.Position, gameMap.GetPlaceType(player.Position));
+ gameMap.Add(prop);
+ }
}
- if (dropProp != null)
- gameMap.Add(dropProp);
-
// player.Reset();
// ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分
diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs
index efd4232..45f6729 100644
--- a/logic/Gaming/Game.cs
+++ b/logic/Gaming/Game.cs
@@ -293,24 +293,24 @@ namespace Gaming
_ = attackManager.Attack(player, angle);
}
}
- public void UseProp(long playerID)
+ public void UseProp(long playerID, int indexing)
{
if (!gameMap.Timer.IsGaming)
return;
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
- propManager.UseProp(player);
+ propManager.UseProp(player, indexing);
}
}
- public void ThrowProp(long playerID, int timeInmillionSeconds, double angle)
+ public void ThrowProp(long playerID, int indexing)
{
if (!gameMap.Timer.IsGaming)
return;
Character? player = gameMap.FindPlayer(playerID);
if (player != null)
{
- propManager.ThrowProp(player, timeInmillionSeconds, angle);
+ propManager.ThrowProp(player, indexing);
}
}
public bool PickProp(long playerID, PropType propType = PropType.Null)
diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs
index 65a8faa..d84787a 100644
--- a/logic/Gaming/PropManager.cs
+++ b/logic/Gaming/PropManager.cs
@@ -28,11 +28,11 @@ namespace Gaming
ProduceProp();
}
- public void UseProp(Character player)
+ public void UseProp(Character player, int indexing)
{
if (player.IsResetting)
return;
- Prop? prop = player.UseProp();
+ Prop? prop = player.UseProp(indexing);
switch (prop?.GetPropType())
{
case PropType.Spear:
@@ -62,6 +62,10 @@ namespace Gaming
{
if (player.IsResetting)
return false;
+ int indexing = player.IndexingOfAddProp();
+ if (indexing == GameData.maxNumOfPropInPropInventory)
+ return false;
+
Prop? pickProp = null;
if (propType == PropType.Null) // 自动检查有无道具可捡
{
@@ -70,9 +74,9 @@ namespace Gaming
{
foreach (Prop prop in gameMap.GameObjDict[GameObjType.Prop])
{
- if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false)
+ if (GameData.IsInTheSameCell(prop.Position, player.Position))
{
- pickProp = prop;
+ player.PropInventory[indexing] = prop;
}
}
}
@@ -92,7 +96,7 @@ namespace Gaming
{
if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false)
{
- pickProp = prop;
+ player.PropInventory[indexing] = prop;
}
}
}
@@ -105,42 +109,26 @@ namespace Gaming
if (pickProp != null)
{
- // pickProp.CanMove = false;
- Prop? dropProp = null;
- if (player.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地
- {
- dropProp = player.PropInventory;
- XY res = GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell);
- dropProp.ReSetPos(res, gameMap.GetPlaceType(res));
- }
- player.PropInventory = pickProp;
gameMap.Remove(pickProp);
- if (dropProp != null) gameMap.Add(dropProp);
gameMap.Add(new PickedProp(pickProp));
-
return true;
}
else
return false;
}
- public void ThrowProp(Character player, int timeInMilliseconds, double angle)
+ public void ThrowProp(Character player, int indexing)
{
- if (!gameMap.Timer.IsGaming)
- return;
- if (player.IsResetting) // 移动中也能扔,但由于“惯性”,可能初始位置会有点变化
+ if (!gameMap.Timer.IsGaming || player.IsResetting)
return;
- Prop? prop = player.UseProp();
+ Prop? prop = player.UseProp(indexing);
if (prop == null)
return;
- prop.CanMove = true;
prop.ReSetPos(player.Position, gameMap.GetPlaceType(player.Position));
gameMap.Add(prop);
-
- timeInMilliseconds = timeInMilliseconds < GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000 ? timeInMilliseconds : GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000;
- moveEngine.MoveObj(prop, timeInMilliseconds, angle);
}
+
private void ProduceProp()
{
int len = availableCellForGenerateProp.Count;
diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs
index afdb24e..5247c50 100644
--- a/logic/Preparation/Utility/EnumType.cs
+++ b/logic/Preparation/Utility/EnumType.cs
@@ -20,7 +20,7 @@ namespace Preparation.Utility
IsStunned = 11,
IsTryingToAttack = 12,//指前摇
IsLockingTheDoor = 13,
- IsRummagingInTheChest = 14,
+ IsOpeningTheChest = 14,
IsClimbingThroughWindows = 15,
IsUsingSpecialSkill = 16,
}
diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs
index 4abb2ad..b1e5b2b 100644
--- a/logic/Preparation/Utility/GameData.cs
+++ b/logic/Preparation/Utility/GameData.cs
@@ -52,39 +52,28 @@ namespace Preparation.Utility
#endregion
#region 角色相关
- public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径
- public const int basicApOfGhost = 1500000; // 攻击力
+ public const int characterRadius = numOfPosGridPerCell / 2 / 5 * 4; // 人物半径
+
public const int basicTreatSpeed = 100;
public const int basicFixSpeed = 100;
+ public const int basicTimeOfOpeningOrLocking = 3000;
+ public const int basicTimeOfClimbingThroughWindows = 870;
+
+ public const int basicHp = 3000000; // 初始血量
public const int basicMaxGamingAddiction = 60000;//基本完全沉迷时间
public const int BeginGamingAddiction = 10003;
public const int MidGamingAddiction = 30000;
public const int basicTreatmentDegree = 1500000;
public const int basicRescueDegree = 100000;
- public const int basicHp = 3000000; // 初始血量
- public const int basicCD = 3000; // 初始子弹冷却
- public const int basicCastTime = 500;//基本前摇时间
- public const int basicBackswing = 500;//基本后摇时间
- public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长
- public const int basicBulletNum = 3; // 基本初始子弹量
- public const int MinAP = 0; // 最小攻击力
- public const int MaxAP = int.MaxValue; // 最大攻击力
- public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围
- public const double basicAttackShortRange = 2700; // 基本近程攻击范围
- public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围
+
public const int basicMoveSpeed = 1260; // 基本移动速度,单位:s-1
- public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1
public const int characterMaxSpeed = 12000; // 最大速度
+ public const int basicBulletMoveSpeed = 2700; // 基本子弹移动速度,单位:s-1
+
public const double basicConcealment = 1.0;
public const int basicAlertnessRadius = 30700;
- public const int basicTimeOfOpeningOrLocking = 3000;
- public const int basicTimeOfClimbingThroughWindows = 870;
+ public const int maxNumOfPropInPropInventory = 3;
public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分
- public const int commonSkillCD = 30000; // 普通技能标准冷却时间
- public const int commonSkillTime = 10000; // 普通技能标准持续时间
- public const int bulletRadius = 200; // 默认子弹半径
- public const int reviveTime = 30000; // 复活时间
- public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间
public static XY PosWhoDie = new XY(1, 1);
@@ -97,7 +86,25 @@ namespace Preparation.Utility
};
}
#endregion
+ #region 攻击与子弹相关
+ public const int basicApOfGhost = 1500000; // 捣蛋鬼攻击力
+ public const int MinAP = 0; // 最小攻击力
+ public const int MaxAP = int.MaxValue; // 最大攻击力
+
+ public const int basicCD = 3000; // 初始子弹冷却
+ public const int basicCastTime = 500;//基本前摇时间
+ public const int basicBackswing = 500;//基本后摇时间
+ public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长
+
+ public const int bulletRadius = 200; // 默认子弹半径
+ public const int basicBulletNum = 3; // 基本初始子弹量
+ public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围
+ public const double basicAttackShortRange = 2700; // 基本近程攻击范围
+ public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围
+ #endregion
#region 技能相关
+ public const int commonSkillCD = 30000; // 普通技能标准冷却时间
+ public const int commonSkillTime = 10000; // 普通技能标准持续时间
///
/// BeginToCharge
///
@@ -117,6 +124,7 @@ namespace Preparation.Utility
#endregion
#region 物体相关
public const int degreeOfFixedGenerator = 10300000;
+ public const int maxNumOfPropInChest = 2;
#endregion
#region 游戏帧相关
public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长
diff --git a/logic/规则Logic.md b/logic/规则Logic.md
index eae9bf4..aa881fb 100644
--- a/logic/规则Logic.md
+++ b/logic/规则Logic.md
@@ -94,7 +94,7 @@
IsStunned = 11,
IsTryingToAttack = 12,//指前摇
IsLockingTheDoor = 13,
- IsRummagingInTheChest = 14,
+ IsOpeningTheChest = 14,
IsClimbingThroughWindows = 15,
IsUsingSpecialSkill = 16,
}
@@ -111,7 +111,7 @@
- ~~回血率/原始回血率~~
- 当前子弹类型
- 原始子弹类型
-- 持有道具 *(最多三个)(列表)*
+- 持有道具 (最多三个)(数组)
- 是否隐身
- 队伍ID
- 玩家ID
@@ -221,7 +221,7 @@
3. 修理电机
4. 开锁门
5. 翻窗
-6. 翻找箱子
+6. 开启箱子
### 门
- *门分别属于三个教学区:三教,五教,六教*
@@ -238,10 +238,31 @@
- *翻越窗户是一种交互行为,执行时,实质是限定方向的减速运动*
### 箱子
-- *监管者和求生者都能与箱子交互,同一时刻就允许一人进行翻找*
+- *监管者和求生者都能与箱子交互,同一时刻只允许一人进行开启*
- *开启箱子有不同概率获得不同道具。*
-- *搜寻物品的基础持续时间为10秒。*
-- *未搜寻完成的箱子在下一次需要重新开始搜寻。*
+- *开启箱子的基础持续时间为10秒。*
+- *未开启完成的箱子在下一次需要重新开始开启。*
+- *箱子开启后其中道具才可以被观测和拿取*
+- [箱子道具不刷新]
+- [箱子不可被关闭]
+- [箱子内道具最多两个]
+
+### 道具
+- 每次玩家试图捡起道具时,需要确保道具栏有空位
+- indexing指道具栏数组下标从0开始
+- 扔道具
+ - Logic内实现
+ ~~~csharp
+ public void ThrowProp(long playerID, int indexing)
+ ~~~
+ - 对应下标出现空位,不会对数组进行重新排序
+- 使用道具
+ - Logic内实现
+ ~~~csharp
+ public void UseProp(long playerID,int indexing)
+ ~~~
+ - 对应下标出现空位,不会对数组进行重新排序
+
### 治疗
- 可行动的求生者可以对受伤的其他求生者进行治疗,治疗完成后会回复被治疗程度的血量。