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