diff --git a/project.godot b/project.godot
index f6f5e1d..1be4e31 100644
--- a/project.godot
+++ b/project.godot
@@ -133,11 +133,6 @@ hotbar_9={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":57,"physical_keycode":0,"key_label":0,"unicode":57,"echo":false,"script":null)
]
}
-hotbar_10={
-"deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":48,"physical_keycode":0,"key_label":0,"unicode":48,"echo":false,"script":null)
-]
-}
hotbar_next={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(241, 17),"global_position":Vector2(245, 58),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
diff --git a/scripts/Config.cs b/scripts/Config.cs
index 16e9135..837b603 100644
--- a/scripts/Config.cs
+++ b/scripts/Config.cs
@@ -90,7 +90,7 @@ public static class Config
/// How many item slots are there on the shortcut bar
/// 快捷栏上有多少个物品槽
///
- public const int HotBarSize = 10;
+ public const int HotBarSize = 9;
///
diff --git a/scripts/GameSceneNodeHolder.cs b/scripts/GameSceneNodeHolder.cs
index f11f868..31e3205 100644
--- a/scripts/GameSceneNodeHolder.cs
+++ b/scripts/GameSceneNodeHolder.cs
@@ -13,7 +13,7 @@ public class GameSceneNodeHolder
/// Player instances within the game scene
/// 游戏场景内的玩家实例
///
- public static Player Player { get; set; }
+ public static Player? Player { get; set; }
///
/// WeaponContainer
diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs
index 00bebb6..dd7ea07 100644
--- a/scripts/character/CharacterTemplate.cs
+++ b/scripts/character/CharacterTemplate.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using ColdMint.scripts.camp;
using ColdMint.scripts.damage;
-using ColdMint.scripts.debug;
using ColdMint.scripts.health;
using ColdMint.scripts.weapon;
using Godot;
@@ -19,383 +18,397 @@ namespace ColdMint.scripts.character;
///
public partial class CharacterTemplate : CharacterBody2D
{
- // Get the gravity from the project settings to be synced with RigidBody nodes.
- public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
- public const float Speed = 300.0f;
+ // Get the gravity from the project settings to be synced with RigidBody nodes.
+ // 从项目设置中获取与RigidBody节点同步的重力。
+ protected float Gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
+ protected const float Speed = 300.0f;
- public const float JumpVelocity = -240;
+ protected const float JumpVelocity = -240;
- protected string _characterName;
+ public string? ReadOnlyCharacterName => CharacterName;
- public string CharacterName => _characterName;
-
- //当前持有的物品
- public Node2D CurrentItem;
+ protected string? CharacterName;
- //定义一个拾起范围
- private Area2D PickingArea;
+ //Items currently held
+ //当前持有的物品
+ public Node2D? CurrentItem;
- protected AnimatedSprite2D AnimatedSprite2D;
+ //Define a pick up range
+ //定义一个拾起范围
+ private Area2D? _pickingArea;
- //一个标志,定义物品的位置
- protected Marker2D ItemMarker2D;
+ private AnimatedSprite2D? _animatedSprite2D;
- //物品标记的原始X坐标
- private float ItemMarkerOriginalX;
+ //A marker that defines the location of the item
+ //一个标记,定义物品的位置
+ protected Marker2D? ItemMarker2D;
- public float ReadOnlyItemMarkerOriginalX => ItemMarkerOriginalX;
+ //The original X-coordinate of the item marker
+ //物品标记的原始X坐标
+ private float _itemMarkerOriginalX;
- //面向左边吗
- public bool FacingLeft = false;
+ protected float ReadOnlyItemMarkerOriginalX => _itemMarkerOriginalX;
- //The force added by the AddForce method
- //由AddForce方法追加的力
- private Vector2 additionalForce = Vector2.Zero;
+ //Face left?
+ //面向左边吗
+ public bool FacingLeft = false;
- protected int CurrentHp;
+ //The force added by the AddForce method
+ //由AddForce方法追加的力
+ private Vector2 _additionalForce = Vector2.Zero;
- //The initial health of the character after creation
- //角色创建后的初始血量
- private int InitialHp;
+ protected int CurrentHp;
- protected int MaxHp;
+ //The initial health of the character after creation
+ //角色创建后的初始血量
+ private int _initialHp;
- ///
- /// The camp ID of the role
- /// 角色的阵营ID
- ///
- public string CampId;
+ protected int MaxHp;
- private DamageNumberNodeSpawn DamageNumber;
+ ///
+ /// The camp ID of the role
+ /// 角色的阵营ID
+ ///
+ public string CampId = null!;
- private HealthBar _healthBar;
- private DateTime _lastDamageTime;
+ private DamageNumberNodeSpawn? _damageNumber;
- ///
- /// Pick up all items within range
- /// 拾捡范围内的所有物品
- ///
- private List _pickingRangeBodies;
+ private HealthBar? _healthBar;
+ private DateTime _lastDamageTime;
- public Node[] PickingRangeBodies => _pickingRangeBodies.ToArray();
+ ///
+ /// Pick up all items within range
+ /// 拾捡范围内的所有物品
+ ///
+ private List? _pickingRangeBodies;
+
+ public Node[] PickingRangeBodies => _pickingRangeBodies?.ToArray() ?? Array.Empty();
- ///
- /// Get all weapons within range of the pick up
- /// 获取所有在拾捡范围内的武器
- ///
- ///
- public WeaponTemplate[] GetCanPickedWeapon()
- {
- var weaponTemplates = new List();
- foreach (var pickingRangeBody in PickingRangeBodies)
- {
- if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
- if (weaponTemplate.Owner != null)
- {
- continue;
- }
+ ///
+ /// Get all weapons within range of the pick up
+ /// 获取所有在拾捡范围内的武器
+ ///
+ ///
+ public WeaponTemplate[] GetCanPickedWeapon()
+ {
+ var weaponTemplates = new List();
+ foreach (var pickingRangeBody in PickingRangeBodies)
+ {
+ if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
+ if (weaponTemplate.Owner != null)
+ {
+ continue;
+ }
- weaponTemplates.Add(weaponTemplate);
- }
+ weaponTemplates.Add(weaponTemplate);
+ }
- return weaponTemplates.ToArray();
- }
+ return weaponTemplates.ToArray();
+ }
- public override void _Ready()
- {
- base._Ready();
- _pickingRangeBodies = new List();
- _characterName = GetMeta("Name", Name).AsString();
- CampId = GetMeta("CampId", Config.CampId.Default).AsString();
- MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
- if (MaxHp <= 0)
- {
- //若最大血量为0或小于0,则将最大血量设置为10
- MaxHp = Config.DefaultMaxHp;
- }
+ public override void _Ready()
+ {
+ base._Ready();
+ _pickingRangeBodies = new List();
+ CharacterName = GetMeta("Name", Name).AsString();
+ CampId = GetMeta("CampId", Config.CampId.Default).AsString();
+ MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
+ if (MaxHp <= 0)
+ {
+ //If Max blood volume is 0 or less, set Max blood volume to 10
+ //若最大血量为0或小于0,则将最大血量设置为10
+ MaxHp = Config.DefaultMaxHp;
+ }
- InitialHp = GetMeta("InitialHp", "0").AsInt32();
- if (InitialHp <= 0)
- {
- //若初始血量小于等于0,则将初始血量设置为最大血量
- InitialHp = MaxHp;
- }
+ _initialHp = GetMeta("InitialHp", "0").AsInt32();
+ if (_initialHp <= 0)
+ {
+ //If the initial blood volume is less than or equal to 0, the initial blood volume is set to the maximum blood volume
+ //若初始血量小于等于0,则将初始血量设置为最大血量
+ _initialHp = MaxHp;
+ }
- CurrentHp = InitialHp;
- //生物的健康条,可能为null。
- _healthBar = GetNodeOrNull("HealthBar");
- if (_healthBar != null)
- {
- _healthBar.MaxValue = MaxHp;
- }
+ CurrentHp = _initialHp;
+ //The health bar of a creature may be null.
+ //生物的健康条,可能为null。
+ _healthBar = GetNodeOrNull("HealthBar");
+ if (_healthBar != null)
+ {
+ _healthBar.MaxValue = MaxHp;
+ }
- ItemMarker2D = GetNode("ItemMarker2D");
- ItemMarkerOriginalX = ItemMarker2D.Position.X;
- AnimatedSprite2D = GetNode("AnimatedSprite2D");
- PickingArea = GetNode("Area2DPickingArea");
- DamageNumber = GetNode("DamageNumber") as DamageNumberNodeSpawn;
- if (PickingArea != null)
- {
- //如果为true,该区域将检测进出该区域的物体或区域。
- PickingArea.Monitoring = true;
- //Other regions cannot detect our pick region
- //其他区域不能检测到我们的拾取区域
- PickingArea.Monitorable = false;
- PickingArea.BodyEntered += EnterThePickingRangeBody;
- PickingArea.BodyExited += ExitThePickingRangeBody;
- }
- }
+ ItemMarker2D = GetNode("ItemMarker2D");
+ _itemMarkerOriginalX = ItemMarker2D.Position.X;
+ _animatedSprite2D = GetNode("AnimatedSprite2D");
+ _pickingArea = GetNode("Area2DPickingArea");
+ _damageNumber = GetNode("DamageNumber") as DamageNumberNodeSpawn;
+ if (_pickingArea != null)
+ {
+ //If true, the zone will detect objects or areas entering and leaving the zone.
+ //如果为true,该区域将检测进出该区域的物体或区域。
+ _pickingArea.Monitoring = true;
+ //Other regions cannot detect our pick region
+ //其他区域不能检测到我们的拾取区域
+ _pickingArea.Monitorable = false;
+ _pickingArea.BodyEntered += EnterThePickingRangeBody;
+ _pickingArea.BodyExited += ExitThePickingRangeBody;
+ }
+ }
- ///
- /// Pick up the specified items
- /// 将指定物品拾起来
- ///
- ///
- ///
- ///Whether successfully picked up
- ///是否成功拾起
- ///
- public bool PickItem(Node2D pickAbleItem)
- {
- if (pickAbleItem == null)
- {
- return false;
- }
+ ///
+ /// Pick up the specified items
+ /// 将指定物品拾起来
+ ///
+ ///
+ ///
+ ///Whether successfully picked up
+ ///是否成功拾起
+ ///
+ public bool PickItem(Node2D pickAbleItem)
+ {
+ if (CurrentItem == null)
+ {
+ if (pickAbleItem is WeaponTemplate weaponTemplate)
+ {
+ if (weaponTemplate.Owner != null && weaponTemplate.Owner != this)
+ {
+ return false;
+ }
- if (CurrentItem == null)
- {
- if (pickAbleItem is WeaponTemplate weaponTemplate)
- {
- if (weaponTemplate.Owner != null && weaponTemplate.Owner != this)
- {
- return false;
- }
+ weaponTemplate.Owner = this;
+ weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
+ weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
+ weaponTemplate.EnableContactInjury = false;
+ weaponTemplate.Sleeping = true;
+ }
- weaponTemplate.Owner = this;
- weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
- weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
- weaponTemplate.EnableContactInjury = false;
- weaponTemplate.Sleeping = true;
- }
+ pickAbleItem.Reparent(ItemMarker2D);
+ pickAbleItem.Position = Vector2.Zero;
+ CurrentItem = pickAbleItem;
+ return true;
+ }
- pickAbleItem.Reparent(ItemMarker2D);
- pickAbleItem.Position = Vector2.Zero;
- CurrentItem = pickAbleItem;
- return true;
- }
-
- return false;
- }
-
- ///
- /// Use what you have in your hand
- /// 使用手中的物品
- ///
- public bool UseItem(Vector2 position)
- {
- if (CurrentItem == null)
- {
- return false;
- }
-
- if (CurrentItem is WeaponTemplate weaponTemplate)
- {
- weaponTemplate.Fire(this, position);
- }
-
- return true;
- }
-
- public override void _Process(double delta)
- {
- base._Process(delta);
-
- //如果上次受到伤害的时间与当前时间的时间差大于健康条显示时间,则隐藏健康条
- var timeSpan = DateTime.Now - _lastDamageTime;
- if (timeSpan > Config.HealthBarDisplaysTime)
- {
- if (_healthBar != null)
- {
- _healthBar.Visible = false;
- }
- }
- }
-
- ///
- /// Update the role's health bar
- /// 更新角色的健康条
- ///
- protected void UpDataHealthBar(DamageTemplate damageTemplate)
- {
- if (_healthBar == null)
- {
- return;
- }
-
- if (GameSceneNodeHolder.Player == null)
- {
- //We didn't know who the player was, so we showed it as a hostile color
- //我们不知道玩家是谁,所以我们将其显示为敌对颜色
- _healthBar.SetEnemyTones();
- }
- else
- {
- //If we set up a player node, then compare the injured party ID to the player's party ID
- //如果我们设置了玩家节点,那么将受伤者的阵营ID与玩家的阵营ID进行比较
- var targetCamp = CampManager.GetCamp(CampId);
- var playerCamp = CampManager.GetCamp(GameSceneNodeHolder.Player.CampId);
- if (CampManager.CanCauseHarm(targetCamp, playerCamp))
- {
- if (targetCamp.ID == playerCamp.ID)
- {
- //If an attack is allowed and you are on the same side, it is displayed as a friendly color (friend damage).
- //如果允许攻击,且属于同一阵营,则显示为友好颜色(友伤)
- _healthBar.SetFriendlyTones();
- }
- else
- {
- //If the injured target is an enemy of the player, it is displayed as an enemy color
- //如果受伤的目标是玩家的敌人,则显示为敌对颜色
- _healthBar.SetEnemyTones();
- }
- }
- else
- {
- _healthBar.SetFriendlyTones();
- }
- }
-
- _healthBar.Visible = true;
- _healthBar.Value = CurrentHp;
- }
-
- ///
- /// Deal damage to the character
- /// 对角色造成伤害
- ///
- ///
- ///Damage template
- ///伤害模板
- ///
- ///
- ///Return whether the damage was done successfully
- ///返回是否成功造成了伤害
- ///
- public bool Damage(DamageTemplate damageTemplate)
- {
- _lastDamageTime = DateTime.Now;
- DamageNumber.Display(damageTemplate);
- CurrentHp -= damageTemplate.Damage;
- OnHit(damageTemplate);
- if (CurrentHp <= 0)
- {
- //角色死亡
- OnDie(damageTemplate);
- return true;
- }
-
- UpDataHealthBar(damageTemplate);
- return true;
- }
-
- ///
- /// Add power to the character
- /// 在角色身上添加力
- ///
- ///
- public void AddForce(Vector2 force)
- {
- additionalForce = force;
- }
-
- protected virtual void OnHit(DamageTemplate damageTemplate)
- {
- }
-
- ///
- /// Handle the event of character death
- /// 处理角色死亡的事件
- ///
- ///
- protected virtual void OnDie(DamageTemplate damageTemplate)
- {
- QueueFree();
- }
-
- ///
- /// When an object enters the picking range
- /// 当有物体进入拾捡范围时
- ///
- ///
- protected virtual void EnterThePickingRangeBody(Node node)
- {
- _pickingRangeBodies.Add(node);
- }
-
- ///
- /// When an object exit the picking range
- /// 当有物体离开拾捡范围时
- ///
- ///
- protected virtual void ExitThePickingRangeBody(Node node)
- {
- _pickingRangeBodies.Remove(node);
- }
-
- ///
- /// Flip sprites or animations
- /// 翻转精灵或动画
- ///
- protected virtual void Flip()
- {
- AnimatedSprite2D.FlipH = FacingLeft;
- }
+ return false;
+ }
- public sealed override void _PhysicsProcess(double delta)
- {
- //We continuously set the position of the items to prevent them from changing as we zoom in and out of the window.
- //我们持续设置物品的位置,为了防止放大缩小窗口时物品位置的变化。
- if (CurrentItem != null)
- {
- CurrentItem.Position = Vector2.Zero;
- }
+ ///
+ /// Use what you have in your hand
+ /// 使用手中的物品
+ ///
+ public bool UseItem(Vector2 position)
+ {
+ if (CurrentItem == null)
+ {
+ return false;
+ }
- var velocity = Velocity;
- // Add the gravity.
- //增加重力。
- if (!IsOnFloor())
- velocity.Y += gravity * (float)delta;
- // The ref keyword passes its pointer to the following method so that it can be modified in the method.
- // ref关键字将其指针传递给下面的方法,以便在方法中修改它。
- HookPhysicsProcess(ref velocity, delta);
- Velocity = velocity + additionalForce;
- additionalForce = Vector2.Zero;
- MoveAndSlide();
- }
+ if (CurrentItem is WeaponTemplate weaponTemplate)
+ {
+ weaponTemplate.Fire(this, position);
+ }
- ///
- /// Aim the held item at a point
- /// 使持有的物品瞄准某个点
- ///
- public void AimTheCurrentItemAtAPoint(Vector2 position)
- {
- if (CurrentItem == null)
- {
- //Do not currently hold any items.
- //当前没有持有任何物品。
- return;
- }
+ return true;
+ }
- // 将旋转角度应用于节点
- CurrentItem.LookAt(position);
- }
+ public override void _Process(double delta)
+ {
+ base._Process(delta);
+
+ //If the time difference between the last injury and the current time is greater than the time displayed in the health bar, the health bar is hidden
+ //如果上次受到伤害的时间与当前时间的时间差大于健康条显示时间,则隐藏健康条
+ var timeSpan = DateTime.Now - _lastDamageTime;
+ if (timeSpan > Config.HealthBarDisplaysTime)
+ {
+ if (_healthBar != null)
+ {
+ _healthBar.Visible = false;
+ }
+ }
+ }
+
+ ///
+ /// Update the role's health bar
+ /// 更新角色的健康条
+ ///
+ private void UpDataHealthBar(DamageTemplate damageTemplate)
+ {
+ if (_healthBar == null)
+ {
+ return;
+ }
+
+ if (GameSceneNodeHolder.Player == null)
+ {
+ //We didn't know who the player was, so we showed it as a hostile color
+ //我们不知道玩家是谁,所以我们将其显示为敌对颜色
+ _healthBar.SetEnemyTones();
+ }
+ else
+ {
+ //If we set up a player node, then compare the injured party ID to the player's party ID
+ //如果我们设置了玩家节点,那么将受伤者的阵营ID与玩家的阵营ID进行比较
+ var targetCamp = CampManager.GetCamp(CampId);
+ var playerCamp = CampManager.GetCamp(GameSceneNodeHolder.Player.CampId);
+ if (CampManager.CanCauseHarm(targetCamp, playerCamp))
+ {
+ if (targetCamp.ID == playerCamp.ID)
+ {
+ //If an attack is allowed and you are on the same side, it is displayed as a friendly color (friend damage).
+ //如果允许攻击,且属于同一阵营,则显示为友好颜色(友伤)
+ _healthBar.SetFriendlyTones();
+ }
+ else
+ {
+ //If the injured target is an enemy of the player, it is displayed as an enemy color
+ //如果受伤的目标是玩家的敌人,则显示为敌对颜色
+ _healthBar.SetEnemyTones();
+ }
+ }
+ else
+ {
+ _healthBar.SetFriendlyTones();
+ }
+ }
+
+ _healthBar.Visible = true;
+ _healthBar.Value = CurrentHp;
+ }
+
+ ///
+ /// Deal damage to the character
+ /// 对角色造成伤害
+ ///
+ ///
+ ///Damage template
+ ///伤害模板
+ ///
+ ///
+ ///Return whether the damage was done successfully
+ ///返回是否成功造成了伤害
+ ///
+ public bool Damage(DamageTemplate damageTemplate)
+ {
+ _lastDamageTime = DateTime.Now;
+ _damageNumber?.Display(damageTemplate);
+ CurrentHp -= damageTemplate.Damage;
+ OnHit(damageTemplate);
+ if (CurrentHp <= 0)
+ {
+ //Character death
+ //角色死亡
+ OnDie(damageTemplate);
+ return true;
+ }
+
+ UpDataHealthBar(damageTemplate);
+ return true;
+ }
+
+ ///
+ /// Add power to the character
+ /// 在角色身上添加力
+ ///
+ ///
+ public void AddForce(Vector2 force)
+ {
+ _additionalForce = force;
+ }
+
+ protected virtual void OnHit(DamageTemplate damageTemplate)
+ {
+ }
+
+ ///
+ /// Handle the event of character death
+ /// 处理角色死亡的事件
+ ///
+ ///
+ protected virtual void OnDie(DamageTemplate damageTemplate)
+ {
+ QueueFree();
+ }
+
+ ///
+ /// When an object enters the picking range
+ /// 当有物体进入拾捡范围时
+ ///
+ ///
+ protected virtual void EnterThePickingRangeBody(Node node)
+ {
+ _pickingRangeBodies?.Add(node);
+ }
+
+ ///
+ /// When an object exit the picking range
+ /// 当有物体离开拾捡范围时
+ ///
+ ///
+ protected virtual void ExitThePickingRangeBody(Node node)
+ {
+ _pickingRangeBodies?.Remove(node);
+ }
+
+ ///
+ /// Flip sprites or animations
+ /// 翻转精灵或动画
+ ///
+ protected virtual void Flip()
+ {
+ if (_animatedSprite2D == null)
+ {
+ return;
+ }
+
+ _animatedSprite2D.FlipH = FacingLeft;
+ }
- protected virtual void HookPhysicsProcess(ref Vector2 velocity, double delta)
- {
- }
-}
+ public sealed override void _PhysicsProcess(double delta)
+ {
+ //We continuously set the position of the items to prevent them from changing as we zoom in and out of the window.
+ //我们持续设置物品的位置,为了防止放大缩小窗口时物品位置的变化。
+ if (CurrentItem != null)
+ {
+ CurrentItem.Position = Vector2.Zero;
+ }
+
+ var velocity = Velocity;
+ // Add the gravity.
+ //增加重力。
+ if (!IsOnFloor())
+ velocity.Y += Gravity * (float)delta;
+ // The ref keyword passes its pointer to the following method so that it can be modified in the method.
+ // ref关键字将其指针传递给下面的方法,以便在方法中修改它。
+ HookPhysicsProcess(ref velocity, delta);
+ Velocity = velocity + _additionalForce;
+ _additionalForce = Vector2.Zero;
+ MoveAndSlide();
+ }
+
+ ///
+ /// Aim the held item at a point
+ /// 使持有的物品瞄准某个点
+ ///
+ public void AimTheCurrentItemAtAPoint(Vector2 position)
+ {
+ if (CurrentItem == null)
+ {
+ //Do not currently hold any items.
+ //当前没有持有任何物品。
+ return;
+ }
+
+ // Apply the rotation Angle to the node
+ // 将旋转角度应用于节点
+ CurrentItem.LookAt(position);
+ }
+
+
+ protected virtual void HookPhysicsProcess(ref Vector2 velocity, double delta)
+ {
+ }
+}
\ No newline at end of file
diff --git a/scripts/character/Player.cs b/scripts/character/Player.cs
index 392f19a..b4f600c 100644
--- a/scripts/character/Player.cs
+++ b/scripts/character/Player.cs
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using ColdMint.scripts;
using ColdMint.scripts.character;
using ColdMint.scripts.damage;
+using ColdMint.scripts.debug;
using ColdMint.scripts.utils;
using ColdMint.scripts.weapon;
@@ -51,7 +52,7 @@ public partial class Player : CharacterTemplate
public override void _Ready()
{
base._Ready();
- _characterName = TranslationServer.Translate("default_player_name");
+ CharacterName = TranslationServer.Translate("default_player_name");
FloatLabelPackedScene = GD.Load("res://prefab/ui/FloatLabel.tscn");
Parabola = GetNode("Parabola");
PlatformDetectionRayCast2D = GetNode("PlatformDetectionRayCast");
@@ -203,6 +204,7 @@ public partial class Player : CharacterTemplate
{
GameSceneNodeHolder.HotBar.AddItem(weaponTemplate);
}
+
PickAbleItem = null;
TotalNumberOfPickups--;
if (FloatLabel != null)
@@ -241,7 +243,7 @@ public partial class Player : CharacterTemplate
if (CurrentItem != null)
{
Parabola.Points =
- ParabolicUtils.ComputeParabolic(ItemMarker2D.Position, GetThrowVelocity(), gravity, 0.1f);
+ ParabolicUtils.ComputeParabolic(ItemMarker2D.Position, GetThrowVelocity(), Gravity, 0.1f);
}
}
@@ -284,12 +286,12 @@ public partial class Player : CharacterTemplate
CurrentItem = null;
TotalNumberOfPickups++;
+ GameSceneNodeHolder.HotBar.RemoveItemFromItemSlotBySelectIndex(1);
UpdateOperationTip();
}
}
}
-
private Vector2 GetThrowVelocity()
{
@@ -373,7 +375,7 @@ public partial class Player : CharacterTemplate
{
if (weapon.Owner is CharacterTemplate characterTemplate)
{
- stringBuilder.Append(characterTemplate.CharacterName);
+ stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
stringBuilder.Append(TranslationServer.Translate("de"));
}
}
diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs
index 95e94c2..d961cfa 100644
--- a/scripts/inventory/HotBar.cs
+++ b/scripts/inventory/HotBar.cs
@@ -1,10 +1,15 @@
using System.Collections.Generic;
using System.Linq;
using ColdMint.scripts.debug;
+using ColdMint.scripts.weapon;
using Godot;
namespace ColdMint.scripts.inventory;
+///
+/// HotBar
+/// 快捷物品栏
+///
public partial class HotBar : HBoxContainer
{
private PackedScene _itemSlotPackedScene;
@@ -25,6 +30,13 @@ public partial class HotBar : HBoxContainer
public override void _Process(double delta)
{
base._Process(delta);
+ if (Input.IsActionPressed("throw"))
+ {
+ //Players are not allowed to switch current items while throwing them.
+ //玩家在抛物品时禁止切换当前物品。
+ return;
+ }
+
if (Input.IsActionJustPressed("hotbar_next"))
{
var count = _itemSlotNodes.Count;
@@ -32,6 +44,7 @@ public partial class HotBar : HBoxContainer
{
return;
}
+
//Mouse wheel down
//鼠标滚轮向下
var oldSelectIndex = selectIndex;
@@ -51,6 +64,7 @@ public partial class HotBar : HBoxContainer
{
return;
}
+
//Mouse wheel up
//鼠标滚轮向上
var oldSelectIndex = selectIndex;
@@ -107,11 +121,6 @@ public partial class HotBar : HBoxContainer
{
SelectItemSlotByHotBarShortcutKey(8);
}
-
- if (Input.IsActionJustPressed("hotbar_10"))
- {
- SelectItemSlotByHotBarShortcutKey(9);
- }
}
///
@@ -136,6 +145,41 @@ public partial class HotBar : HBoxContainer
selectIndex = newIndex;
}
+
+ ///
+ /// Removes an item from the currently selected inventory
+ /// 移除当前选中的物品栏内的物品
+ ///
+ ///
+ ///
+ public bool RemoveItemFromItemSlotBySelectIndex(int number)
+ {
+ return RemoveItemFromItemSlot(selectIndex, number);
+ }
+
+ ///
+ /// Remove items from the item slot
+ /// 从物品槽内移除物品
+ ///
+ ///
+ ///When this number is greater than the number of item slots, residual filtering is used.
+ ///当此数量大于物品槽的数量时,会使用余数筛选。
+ ///
+ public bool RemoveItemFromItemSlot(int itemSlotIndex, int number)
+ {
+ var count = _itemSlotNodes.Count;
+ if (count == 0)
+ {
+ //Prevents the dividend from being 0
+ //防止被除数为0
+ return false;
+ }
+
+ var newIndex = itemSlotIndex % count;
+ var itemSlot = _itemSlotNodes[newIndex];
+ return itemSlot.RemoveItem(number);
+ }
+
///
/// Select an item slot
/// 选中某个物品槽
@@ -144,6 +188,35 @@ public partial class HotBar : HBoxContainer
{
_itemSlotNodes[oldSelectIndex].IsSelect = false;
_itemSlotNodes[newSelectIndex].IsSelect = true;
+ var oldItem = _itemSlotNodes[oldSelectIndex].GetItem();
+ if (oldItem != null && oldItem is Node2D oldNode2D)
+ {
+ oldNode2D.ProcessMode = ProcessModeEnum.Disabled;
+ oldNode2D.Hide();
+ }
+
+ var item = _itemSlotNodes[newSelectIndex].GetItem();
+ if (item == null)
+ {
+ LogCat.Log("选择" + oldSelectIndex + "新的为" + newSelectIndex + "空对象");
+ GameSceneNodeHolder.Player.CurrentItem = null;
+ LogCat.Log("我是空吗" + (GameSceneNodeHolder.Player.CurrentItem == null));
+ }
+ else
+ {
+ if (item is Node2D node2D)
+ {
+ LogCat.Log("我是空吗" + (GameSceneNodeHolder.Player.CurrentItem == null));
+ LogCat.Log("选择" + oldSelectIndex + "新的为" + newSelectIndex + "已赋值" + node2D);
+ node2D.ProcessMode = ProcessModeEnum.Inherit;
+ node2D.Show();
+ GameSceneNodeHolder.Player.CurrentItem = node2D;
+ }
+ else
+ {
+ GameSceneNodeHolder.Player.CurrentItem = null;
+ }
+ }
}
///
diff --git a/scripts/inventory/ItemSlotNode.cs b/scripts/inventory/ItemSlotNode.cs
index bc82918..11c069a 100644
--- a/scripts/inventory/ItemSlotNode.cs
+++ b/scripts/inventory/ItemSlotNode.cs
@@ -8,132 +8,189 @@ namespace ColdMint.scripts.inventory;
///
public partial class ItemSlotNode : MarginContainer
{
- private IItem? _item;
- private TextureRect _backgroundTextureRect;
- private TextureRect _iconTextureRect;
- private Label _quantityLabel;
- private Control _control;
- private bool _isSelect;
- private Texture2D _backgroundTexture;
- private Texture2D _backgroundTextureWhenSelect;
+ private IItem? _item;
+ private TextureRect _backgroundTextureRect;
+ private TextureRect _iconTextureRect;
+ private Label _quantityLabel;
+ private Control _control;
+ private bool _isSelect;
+ private Texture2D _backgroundTexture;
+ private Texture2D _backgroundTextureWhenSelect;
- public bool IsSelect
- {
- get => _isSelect;
- set
- {
- if (value)
- {
- _backgroundTextureRect.Texture = _backgroundTextureWhenSelect;
- }
- else
- {
- _backgroundTextureRect.Texture = _backgroundTexture;
- }
- _isSelect = value;
- }
- }
+ public bool IsSelect
+ {
+ get => _isSelect;
+ set
+ {
+ if (value)
+ {
+ _backgroundTextureRect.Texture = _backgroundTextureWhenSelect;
+ }
+ else
+ {
+ _backgroundTextureRect.Texture = _backgroundTexture;
+ }
- public TextureRect BackgroundTextureRect => _backgroundTextureRect;
+ _isSelect = value;
+ }
+ }
- ///
- /// Sets items for the item slot
- /// 为物品槽设置物品
- ///
- ///
- ///
- public bool SetItem(IItem item)
- {
- if (_item == null)
- {
- if (item.Icon != null)
- {
- _iconTextureRect.Texture = item.Icon;
- }
+ public TextureRect BackgroundTextureRect => _backgroundTextureRect;
- _item = item;
- UpdateTooltipText(item);
- UpdateQuantityLabel(item.Quantity);
- return true;
- }
- else
- {
- //This inventory already has items, but the items in this inventory are not the same as the incoming items
- //这个物品栏已经有物品了,但是这个物品栏的物品和传入的物品不一样
- if (_item.Id != item.Id)
- {
- return false;
- }
+ ///
+ /// Get the items in the item slot
+ /// 获取物品槽内的物品
+ ///
+ ///
+ public IItem? GetItem()
+ {
+ return _item;
+ }
- var newQuantity = _item.Quantity + item.Quantity;
- if (newQuantity > item.MaxStackQuantity)
- {
- //If the amount of the current item exceeds the maximum stack amount after placing it in this inventory
- //如果将当前物品放置到这个物品栏后,数量超过了最大叠加数量
- return false;
- }
+ ///
+ /// Removes the specified number of items from the item slot
+ /// 在物品槽内移除指定数量的物品
+ ///
+ ///
+ ///
+ public bool RemoveItem(int number)
+ {
+ if (_item == null)
+ {
+ return false;
+ }
- _item.Quantity = newQuantity;
- UpdateTooltipText(item);
- UpdateQuantityLabel(newQuantity);
- return true;
- }
- }
+ var newNumber = _item.Quantity - number;
+ if (newNumber <= 0)
+ {
+ //If the specified number of items is removed, the number of items is less than or equal to 0. Then we return the removal successful and empty the inventory.
+ //如果移除指定数量的物品后,物品数量小于或等于0。那么我们返回移除成功,并清空物品栏。
+ ClearItem();
+ return true;
+ }
+ else
+ {
+ _item.Quantity = newNumber;
+ UpdateTooltipText(_item);
+ UpdateQuantityLabel(_item.Quantity);
+ return true;
+ }
+ }
- ///
- /// Update item tips
- /// 更新物品的提示内容
- ///
- ///
- private void UpdateTooltipText(IItem item)
- {
- if (Config.IsDebug())
- {
- _control.TooltipText = string.Format(TranslationServer.Translate("item_prompt_debug"), item.Id,
- TranslationServer.Translate(item.Name),
- item.Quantity, item.MaxStackQuantity, item.GetType().Name,
- TranslationServer.Translate(item.Description));
- }
- else
- {
- _control.TooltipText = TranslationServer.Translate(item.Name) + "\n" +
- TranslationServer.Translate(item.Description);
- }
- }
+ ///
+ /// Empty the items in the item slot
+ /// 清空物品槽内的物品
+ ///
+ ///
+ ///This method does not calculate how many items should be left. If you want to remove a specified number of items, call the RemoveItem method.
+ ///此方法不会计算物品应该剩余多少个。若您希望移除指定数量的物品,请调用RemoveItem方法。
+ ///
+ public void ClearItem()
+ {
+ _item = null;
+ _iconTextureRect.Texture = null;
+ _control.TooltipText = null;
+ _quantityLabel.Visible = false;
+ }
- ///
- /// Update quantity label
- /// 更新数量标签
- ///
- ///
- private void UpdateQuantityLabel(int? quantity)
- {
- switch (quantity)
- {
- case null:
- _quantityLabel.Visible = false;
- return;
- case > 1:
- //When the quantity is greater than 1, we display the quantity.
- //当数量大于1时,我们显示数量
- _quantityLabel.Text = quantity.ToString();
- _quantityLabel.Visible = true;
- break;
- default:
- _quantityLabel.Visible = false;
- break;
- }
- }
+ ///
+ /// Sets items for the item slot
+ /// 为物品槽设置物品
+ ///
+ ///
+ ///
+ public bool SetItem(IItem item)
+ {
+ if (_item == null)
+ {
+ if (item.Icon != null)
+ {
+ _iconTextureRect.Texture = item.Icon;
+ }
- public override void _Ready()
- {
- _backgroundTexture = GD.Load("res://sprites/ui/ItemBarEmpty.png");
- _backgroundTextureWhenSelect = GD.Load("res://sprites/ui/ItemBarFocus.png");
- _backgroundTextureRect =
- GetNode("BackgroundTexture");
- _iconTextureRect = GetNode("BackgroundTexture/CenterContainer/IconTextureRect");
- _quantityLabel = GetNode
- public Node2D Owner { get; set; }
+ public Node2D? Owner { get; set; }
///
diff --git a/sprites/ui/ItemBarFocus.png b/sprites/ui/ItemBarFocus.png
index 9530b04..bd8e051 100644
Binary files a/sprites/ui/ItemBarFocus.png and b/sprites/ui/ItemBarFocus.png differ