Supports the use of mouse wheel to switch currently held items.
支持使用鼠标滚轮切换当前持有的物品了。
This commit is contained in:
parent
b7939af5d0
commit
801b3dd93b
|
@ -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)
|
"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={
|
hotbar_next={
|
||||||
"deadzone": 0.5,
|
"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)
|
"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)
|
||||||
|
|
|
@ -90,7 +90,7 @@ public static class Config
|
||||||
/// <para>How many item slots are there on the shortcut bar</para>
|
/// <para>How many item slots are there on the shortcut bar</para>
|
||||||
/// <para>快捷栏上有多少个物品槽</para>
|
/// <para>快捷栏上有多少个物品槽</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int HotBarSize = 10;
|
public const int HotBarSize = 9;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class GameSceneNodeHolder
|
||||||
/// <para>Player instances within the game scene</para>
|
/// <para>Player instances within the game scene</para>
|
||||||
/// <para>游戏场景内的玩家实例</para>
|
/// <para>游戏场景内的玩家实例</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Player Player { get; set; }
|
public static Player? Player { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>WeaponContainer</para>
|
/// <para>WeaponContainer</para>
|
||||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ColdMint.scripts.camp;
|
using ColdMint.scripts.camp;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
using ColdMint.scripts.debug;
|
|
||||||
using ColdMint.scripts.health;
|
using ColdMint.scripts.health;
|
||||||
using ColdMint.scripts.weapon;
|
using ColdMint.scripts.weapon;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
@ -19,383 +18,397 @@ namespace ColdMint.scripts.character;
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public partial class CharacterTemplate : CharacterBody2D
|
public partial class CharacterTemplate : CharacterBody2D
|
||||||
{
|
{
|
||||||
// Get the gravity from the project settings to be synced with RigidBody nodes.
|
// Get the gravity from the project settings to be synced with RigidBody nodes.
|
||||||
public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
// 从项目设置中获取与RigidBody节点同步的重力。
|
||||||
public const float Speed = 300.0f;
|
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;
|
protected string? CharacterName;
|
||||||
|
|
||||||
//当前持有的物品
|
|
||||||
public Node2D CurrentItem;
|
|
||||||
|
|
||||||
|
|
||||||
//定义一个拾起范围
|
//Items currently held
|
||||||
private Area2D PickingArea;
|
//当前持有的物品
|
||||||
|
public Node2D? CurrentItem;
|
||||||
|
|
||||||
protected AnimatedSprite2D AnimatedSprite2D;
|
//Define a pick up range
|
||||||
|
//定义一个拾起范围
|
||||||
|
private Area2D? _pickingArea;
|
||||||
|
|
||||||
//一个标志,定义物品的位置
|
private AnimatedSprite2D? _animatedSprite2D;
|
||||||
protected Marker2D ItemMarker2D;
|
|
||||||
|
|
||||||
//物品标记的原始X坐标
|
//A marker that defines the location of the item
|
||||||
private float ItemMarkerOriginalX;
|
//一个标记,定义物品的位置
|
||||||
|
protected Marker2D? ItemMarker2D;
|
||||||
|
|
||||||
public float ReadOnlyItemMarkerOriginalX => ItemMarkerOriginalX;
|
//The original X-coordinate of the item marker
|
||||||
|
//物品标记的原始X坐标
|
||||||
|
private float _itemMarkerOriginalX;
|
||||||
|
|
||||||
//面向左边吗
|
protected float ReadOnlyItemMarkerOriginalX => _itemMarkerOriginalX;
|
||||||
public bool FacingLeft = false;
|
|
||||||
|
|
||||||
//The force added by the AddForce method
|
//Face left?
|
||||||
//由AddForce方法追加的力
|
//面向左边吗
|
||||||
private Vector2 additionalForce = Vector2.Zero;
|
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
|
protected int CurrentHp;
|
||||||
//角色创建后的初始血量
|
|
||||||
private int InitialHp;
|
|
||||||
|
|
||||||
protected int MaxHp;
|
//The initial health of the character after creation
|
||||||
|
//角色创建后的初始血量
|
||||||
|
private int _initialHp;
|
||||||
|
|
||||||
/// <summary>
|
protected int MaxHp;
|
||||||
/// <para>The camp ID of the role</para>
|
|
||||||
/// <para>角色的阵营ID</para>
|
|
||||||
/// </summary>
|
|
||||||
public string CampId;
|
|
||||||
|
|
||||||
private DamageNumberNodeSpawn DamageNumber;
|
/// <summary>
|
||||||
|
/// <para>The camp ID of the role</para>
|
||||||
|
/// <para>角色的阵营ID</para>
|
||||||
|
/// </summary>
|
||||||
|
public string CampId = null!;
|
||||||
|
|
||||||
private HealthBar _healthBar;
|
private DamageNumberNodeSpawn? _damageNumber;
|
||||||
private DateTime _lastDamageTime;
|
|
||||||
|
|
||||||
/// <summary>
|
private HealthBar? _healthBar;
|
||||||
/// <para>Pick up all items within range</para>
|
private DateTime _lastDamageTime;
|
||||||
/// <para>拾捡范围内的所有物品</para>
|
|
||||||
/// </summary>
|
|
||||||
private List<Node> _pickingRangeBodies;
|
|
||||||
|
|
||||||
public Node[] PickingRangeBodies => _pickingRangeBodies.ToArray();
|
/// <summary>
|
||||||
|
/// <para>Pick up all items within range</para>
|
||||||
|
/// <para>拾捡范围内的所有物品</para>
|
||||||
|
/// </summary>
|
||||||
|
private List<Node>? _pickingRangeBodies;
|
||||||
|
|
||||||
|
public Node[] PickingRangeBodies => _pickingRangeBodies?.ToArray() ?? Array.Empty<Node>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Get all weapons within range of the pick up</para>
|
/// <para>Get all weapons within range of the pick up</para>
|
||||||
/// <para>获取所有在拾捡范围内的武器</para>
|
/// <para>获取所有在拾捡范围内的武器</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public WeaponTemplate[] GetCanPickedWeapon()
|
public WeaponTemplate[] GetCanPickedWeapon()
|
||||||
{
|
{
|
||||||
var weaponTemplates = new List<WeaponTemplate>();
|
var weaponTemplates = new List<WeaponTemplate>();
|
||||||
foreach (var pickingRangeBody in PickingRangeBodies)
|
foreach (var pickingRangeBody in PickingRangeBodies)
|
||||||
{
|
{
|
||||||
if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
|
if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
|
||||||
if (weaponTemplate.Owner != null)
|
if (weaponTemplate.Owner != null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
weaponTemplates.Add(weaponTemplate);
|
weaponTemplates.Add(weaponTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return weaponTemplates.ToArray();
|
return weaponTemplates.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_pickingRangeBodies = new List<Node>();
|
_pickingRangeBodies = new List<Node>();
|
||||||
_characterName = GetMeta("Name", Name).AsString();
|
CharacterName = GetMeta("Name", Name).AsString();
|
||||||
CampId = GetMeta("CampId", Config.CampId.Default).AsString();
|
CampId = GetMeta("CampId", Config.CampId.Default).AsString();
|
||||||
MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
|
MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
|
||||||
if (MaxHp <= 0)
|
if (MaxHp <= 0)
|
||||||
{
|
{
|
||||||
//若最大血量为0或小于0,则将最大血量设置为10
|
//If Max blood volume is 0 or less, set Max blood volume to 10
|
||||||
MaxHp = Config.DefaultMaxHp;
|
//若最大血量为0或小于0,则将最大血量设置为10
|
||||||
}
|
MaxHp = Config.DefaultMaxHp;
|
||||||
|
}
|
||||||
|
|
||||||
InitialHp = GetMeta("InitialHp", "0").AsInt32();
|
_initialHp = GetMeta("InitialHp", "0").AsInt32();
|
||||||
if (InitialHp <= 0)
|
if (_initialHp <= 0)
|
||||||
{
|
{
|
||||||
//若初始血量小于等于0,则将初始血量设置为最大血量
|
//If the initial blood volume is less than or equal to 0, the initial blood volume is set to the maximum blood volume
|
||||||
InitialHp = MaxHp;
|
//若初始血量小于等于0,则将初始血量设置为最大血量
|
||||||
}
|
_initialHp = MaxHp;
|
||||||
|
}
|
||||||
|
|
||||||
CurrentHp = InitialHp;
|
CurrentHp = _initialHp;
|
||||||
//生物的健康条,可能为null。
|
//The health bar of a creature may be null.
|
||||||
_healthBar = GetNodeOrNull<HealthBar>("HealthBar");
|
//生物的健康条,可能为null。
|
||||||
if (_healthBar != null)
|
_healthBar = GetNodeOrNull<HealthBar>("HealthBar");
|
||||||
{
|
if (_healthBar != null)
|
||||||
_healthBar.MaxValue = MaxHp;
|
{
|
||||||
}
|
_healthBar.MaxValue = MaxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ItemMarker2D = GetNode<Marker2D>("ItemMarker2D");
|
ItemMarker2D = GetNode<Marker2D>("ItemMarker2D");
|
||||||
ItemMarkerOriginalX = ItemMarker2D.Position.X;
|
_itemMarkerOriginalX = ItemMarker2D.Position.X;
|
||||||
AnimatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
|
_animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
|
||||||
PickingArea = GetNode<Area2D>("Area2DPickingArea");
|
_pickingArea = GetNode<Area2D>("Area2DPickingArea");
|
||||||
DamageNumber = GetNode<Marker2D>("DamageNumber") as DamageNumberNodeSpawn;
|
_damageNumber = GetNode<Marker2D>("DamageNumber") as DamageNumberNodeSpawn;
|
||||||
if (PickingArea != null)
|
if (_pickingArea != null)
|
||||||
{
|
{
|
||||||
//如果为true,该区域将检测进出该区域的物体或区域。
|
//If true, the zone will detect objects or areas entering and leaving the zone.
|
||||||
PickingArea.Monitoring = true;
|
//如果为true,该区域将检测进出该区域的物体或区域。
|
||||||
//Other regions cannot detect our pick region
|
_pickingArea.Monitoring = true;
|
||||||
//其他区域不能检测到我们的拾取区域
|
//Other regions cannot detect our pick region
|
||||||
PickingArea.Monitorable = false;
|
//其他区域不能检测到我们的拾取区域
|
||||||
PickingArea.BodyEntered += EnterThePickingRangeBody;
|
_pickingArea.Monitorable = false;
|
||||||
PickingArea.BodyExited += ExitThePickingRangeBody;
|
_pickingArea.BodyEntered += EnterThePickingRangeBody;
|
||||||
}
|
_pickingArea.BodyExited += ExitThePickingRangeBody;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Pick up the specified items</para>
|
/// <para>Pick up the specified items</para>
|
||||||
/// <para>将指定物品拾起来</para>
|
/// <para>将指定物品拾起来</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pickAbleItem"></param>
|
/// <param name="pickAbleItem"></param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
///<para>Whether successfully picked up</para>
|
///<para>Whether successfully picked up</para>
|
||||||
///<para>是否成功拾起</para>
|
///<para>是否成功拾起</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public bool PickItem(Node2D pickAbleItem)
|
public bool PickItem(Node2D pickAbleItem)
|
||||||
{
|
{
|
||||||
if (pickAbleItem == null)
|
if (CurrentItem == null)
|
||||||
{
|
{
|
||||||
return false;
|
if (pickAbleItem is WeaponTemplate weaponTemplate)
|
||||||
}
|
{
|
||||||
|
if (weaponTemplate.Owner != null && weaponTemplate.Owner != this)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (CurrentItem == null)
|
weaponTemplate.Owner = this;
|
||||||
{
|
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
|
||||||
if (pickAbleItem is WeaponTemplate weaponTemplate)
|
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
|
||||||
{
|
weaponTemplate.EnableContactInjury = false;
|
||||||
if (weaponTemplate.Owner != null && weaponTemplate.Owner != this)
|
weaponTemplate.Sleeping = true;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
weaponTemplate.Owner = this;
|
pickAbleItem.Reparent(ItemMarker2D);
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
|
pickAbleItem.Position = Vector2.Zero;
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
|
CurrentItem = pickAbleItem;
|
||||||
weaponTemplate.EnableContactInjury = false;
|
return true;
|
||||||
weaponTemplate.Sleeping = true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pickAbleItem.Reparent(ItemMarker2D);
|
return false;
|
||||||
pickAbleItem.Position = Vector2.Zero;
|
}
|
||||||
CurrentItem = pickAbleItem;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Use what you have in your hand</para>
|
|
||||||
/// <para>使用手中的物品</para>
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Update the role's health bar</para>
|
|
||||||
/// <para>更新角色的健康条</para>
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Deal damage to the character</para>
|
|
||||||
/// <para>对角色造成伤害</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="damageTemplate">
|
|
||||||
///<para>Damage template</para>
|
|
||||||
///<para>伤害模板</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
///<para>Return whether the damage was done successfully</para>
|
|
||||||
///<para>返回是否成功造成了伤害</para>
|
|
||||||
/// </returns>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Add power to the character</para>
|
|
||||||
/// <para>在角色身上添加力</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="force"></param>
|
|
||||||
public void AddForce(Vector2 force)
|
|
||||||
{
|
|
||||||
additionalForce = force;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnHit(DamageTemplate damageTemplate)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Handle the event of character death</para>
|
|
||||||
/// <para>处理角色死亡的事件</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="damageTemplate"></param>
|
|
||||||
protected virtual void OnDie(DamageTemplate damageTemplate)
|
|
||||||
{
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>When an object enters the picking range</para>
|
|
||||||
/// <para>当有物体进入拾捡范围时</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="node"></param>
|
|
||||||
protected virtual void EnterThePickingRangeBody(Node node)
|
|
||||||
{
|
|
||||||
_pickingRangeBodies.Add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>When an object exit the picking range</para>
|
|
||||||
/// <para>当有物体离开拾捡范围时</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="node"></param>
|
|
||||||
protected virtual void ExitThePickingRangeBody(Node node)
|
|
||||||
{
|
|
||||||
_pickingRangeBodies.Remove(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Flip sprites or animations</para>
|
|
||||||
/// <para>翻转精灵或动画</para>
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void Flip()
|
|
||||||
{
|
|
||||||
AnimatedSprite2D.FlipH = FacingLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public sealed override void _PhysicsProcess(double delta)
|
/// <summary>
|
||||||
{
|
/// <para>Use what you have in your hand</para>
|
||||||
//We continuously set the position of the items to prevent them from changing as we zoom in and out of the window.
|
/// <para>使用手中的物品</para>
|
||||||
//我们持续设置物品的位置,为了防止放大缩小窗口时物品位置的变化。
|
/// </summary>
|
||||||
if (CurrentItem != null)
|
public bool UseItem(Vector2 position)
|
||||||
{
|
{
|
||||||
CurrentItem.Position = Vector2.Zero;
|
if (CurrentItem == null)
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var velocity = Velocity;
|
if (CurrentItem is WeaponTemplate weaponTemplate)
|
||||||
// Add the gravity.
|
{
|
||||||
//增加重力。
|
weaponTemplate.Fire(this, position);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
return true;
|
||||||
/// <para>Aim the held item at a point</para>
|
}
|
||||||
/// <para>使持有的物品瞄准某个点</para>
|
|
||||||
/// </summary>
|
|
||||||
public void AimTheCurrentItemAtAPoint(Vector2 position)
|
|
||||||
{
|
|
||||||
if (CurrentItem == null)
|
|
||||||
{
|
|
||||||
//Do not currently hold any items.
|
|
||||||
//当前没有持有任何物品。
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将旋转角度应用于节点
|
public override void _Process(double delta)
|
||||||
CurrentItem.LookAt(position);
|
{
|
||||||
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update the role's health bar</para>
|
||||||
|
/// <para>更新角色的健康条</para>
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Deal damage to the character</para>
|
||||||
|
/// <para>对角色造成伤害</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="damageTemplate">
|
||||||
|
///<para>Damage template</para>
|
||||||
|
///<para>伤害模板</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
///<para>Return whether the damage was done successfully</para>
|
||||||
|
///<para>返回是否成功造成了伤害</para>
|
||||||
|
/// </returns>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Add power to the character</para>
|
||||||
|
/// <para>在角色身上添加力</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="force"></param>
|
||||||
|
public void AddForce(Vector2 force)
|
||||||
|
{
|
||||||
|
_additionalForce = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnHit(DamageTemplate damageTemplate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Handle the event of character death</para>
|
||||||
|
/// <para>处理角色死亡的事件</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="damageTemplate"></param>
|
||||||
|
protected virtual void OnDie(DamageTemplate damageTemplate)
|
||||||
|
{
|
||||||
|
QueueFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When an object enters the picking range</para>
|
||||||
|
/// <para>当有物体进入拾捡范围时</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
protected virtual void EnterThePickingRangeBody(Node node)
|
||||||
|
{
|
||||||
|
_pickingRangeBodies?.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When an object exit the picking range</para>
|
||||||
|
/// <para>当有物体离开拾捡范围时</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
protected virtual void ExitThePickingRangeBody(Node node)
|
||||||
|
{
|
||||||
|
_pickingRangeBodies?.Remove(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Flip sprites or animations</para>
|
||||||
|
/// <para>翻转精灵或动画</para>
|
||||||
|
/// </summary>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Aim the held item at a point</para>
|
||||||
|
/// <para>使持有的物品瞄准某个点</para>
|
||||||
|
/// </summary>
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using ColdMint.scripts;
|
using ColdMint.scripts;
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using ColdMint.scripts.weapon;
|
using ColdMint.scripts.weapon;
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ public partial class Player : CharacterTemplate
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_characterName = TranslationServer.Translate("default_player_name");
|
CharacterName = TranslationServer.Translate("default_player_name");
|
||||||
FloatLabelPackedScene = GD.Load<PackedScene>("res://prefab/ui/FloatLabel.tscn");
|
FloatLabelPackedScene = GD.Load<PackedScene>("res://prefab/ui/FloatLabel.tscn");
|
||||||
Parabola = GetNode<Line2D>("Parabola");
|
Parabola = GetNode<Line2D>("Parabola");
|
||||||
PlatformDetectionRayCast2D = GetNode<RayCast2D>("PlatformDetectionRayCast");
|
PlatformDetectionRayCast2D = GetNode<RayCast2D>("PlatformDetectionRayCast");
|
||||||
|
@ -203,6 +204,7 @@ public partial class Player : CharacterTemplate
|
||||||
{
|
{
|
||||||
GameSceneNodeHolder.HotBar.AddItem(weaponTemplate);
|
GameSceneNodeHolder.HotBar.AddItem(weaponTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
PickAbleItem = null;
|
PickAbleItem = null;
|
||||||
TotalNumberOfPickups--;
|
TotalNumberOfPickups--;
|
||||||
if (FloatLabel != null)
|
if (FloatLabel != null)
|
||||||
|
@ -241,7 +243,7 @@ public partial class Player : CharacterTemplate
|
||||||
if (CurrentItem != null)
|
if (CurrentItem != null)
|
||||||
{
|
{
|
||||||
Parabola.Points =
|
Parabola.Points =
|
||||||
ParabolicUtils.ComputeParabolic(ItemMarker2D.Position, GetThrowVelocity(), gravity, 0.1f);
|
ParabolicUtils.ComputeParabolic(ItemMarker2D.Position, GetThrowVelocity(), Gravity, 0.1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,13 +286,13 @@ public partial class Player : CharacterTemplate
|
||||||
|
|
||||||
CurrentItem = null;
|
CurrentItem = null;
|
||||||
TotalNumberOfPickups++;
|
TotalNumberOfPickups++;
|
||||||
|
GameSceneNodeHolder.HotBar.RemoveItemFromItemSlotBySelectIndex(1);
|
||||||
UpdateOperationTip();
|
UpdateOperationTip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Vector2 GetThrowVelocity()
|
private Vector2 GetThrowVelocity()
|
||||||
{
|
{
|
||||||
//我们拿到鼠标的位置,将其归一化处理,然后乘以玩家可扔出的距离
|
//我们拿到鼠标的位置,将其归一化处理,然后乘以玩家可扔出的距离
|
||||||
|
@ -373,7 +375,7 @@ public partial class Player : CharacterTemplate
|
||||||
{
|
{
|
||||||
if (weapon.Owner is CharacterTemplate characterTemplate)
|
if (weapon.Owner is CharacterTemplate characterTemplate)
|
||||||
{
|
{
|
||||||
stringBuilder.Append(characterTemplate.CharacterName);
|
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
|
||||||
stringBuilder.Append(TranslationServer.Translate("de"));
|
stringBuilder.Append(TranslationServer.Translate("de"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
|
using ColdMint.scripts.weapon;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.inventory;
|
namespace ColdMint.scripts.inventory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>HotBar</para>
|
||||||
|
/// <para>快捷物品栏</para>
|
||||||
|
/// </summary>
|
||||||
public partial class HotBar : HBoxContainer
|
public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
private PackedScene _itemSlotPackedScene;
|
private PackedScene _itemSlotPackedScene;
|
||||||
|
@ -25,6 +30,13 @@ public partial class HotBar : HBoxContainer
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
base._Process(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"))
|
if (Input.IsActionJustPressed("hotbar_next"))
|
||||||
{
|
{
|
||||||
var count = _itemSlotNodes.Count;
|
var count = _itemSlotNodes.Count;
|
||||||
|
@ -32,6 +44,7 @@ public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mouse wheel down
|
//Mouse wheel down
|
||||||
//鼠标滚轮向下
|
//鼠标滚轮向下
|
||||||
var oldSelectIndex = selectIndex;
|
var oldSelectIndex = selectIndex;
|
||||||
|
@ -51,6 +64,7 @@ public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mouse wheel up
|
//Mouse wheel up
|
||||||
//鼠标滚轮向上
|
//鼠标滚轮向上
|
||||||
var oldSelectIndex = selectIndex;
|
var oldSelectIndex = selectIndex;
|
||||||
|
@ -107,11 +121,6 @@ public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
SelectItemSlotByHotBarShortcutKey(8);
|
SelectItemSlotByHotBarShortcutKey(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.IsActionJustPressed("hotbar_10"))
|
|
||||||
{
|
|
||||||
SelectItemSlotByHotBarShortcutKey(9);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -136,6 +145,41 @@ public partial class HotBar : HBoxContainer
|
||||||
selectIndex = newIndex;
|
selectIndex = newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Removes an item from the currently selected inventory</para>
|
||||||
|
/// <para>移除当前选中的物品栏内的物品</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool RemoveItemFromItemSlotBySelectIndex(int number)
|
||||||
|
{
|
||||||
|
return RemoveItemFromItemSlot(selectIndex, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Remove items from the item slot</para>
|
||||||
|
/// <para>从物品槽内移除物品</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemSlotIndex">
|
||||||
|
///<para>When this number is greater than the number of item slots, residual filtering is used.</para>
|
||||||
|
///<para>当此数量大于物品槽的数量时,会使用余数筛选。</para>
|
||||||
|
/// </param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Select an item slot</para>
|
/// <para>Select an item slot</para>
|
||||||
/// <para>选中某个物品槽</para>
|
/// <para>选中某个物品槽</para>
|
||||||
|
@ -144,6 +188,35 @@ public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
_itemSlotNodes[oldSelectIndex].IsSelect = false;
|
_itemSlotNodes[oldSelectIndex].IsSelect = false;
|
||||||
_itemSlotNodes[newSelectIndex].IsSelect = true;
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -8,132 +8,189 @@ namespace ColdMint.scripts.inventory;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ItemSlotNode : MarginContainer
|
public partial class ItemSlotNode : MarginContainer
|
||||||
{
|
{
|
||||||
private IItem? _item;
|
private IItem? _item;
|
||||||
private TextureRect _backgroundTextureRect;
|
private TextureRect _backgroundTextureRect;
|
||||||
private TextureRect _iconTextureRect;
|
private TextureRect _iconTextureRect;
|
||||||
private Label _quantityLabel;
|
private Label _quantityLabel;
|
||||||
private Control _control;
|
private Control _control;
|
||||||
private bool _isSelect;
|
private bool _isSelect;
|
||||||
private Texture2D _backgroundTexture;
|
private Texture2D _backgroundTexture;
|
||||||
private Texture2D _backgroundTextureWhenSelect;
|
private Texture2D _backgroundTextureWhenSelect;
|
||||||
|
|
||||||
public bool IsSelect
|
public bool IsSelect
|
||||||
{
|
{
|
||||||
get => _isSelect;
|
get => _isSelect;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
_backgroundTextureRect.Texture = _backgroundTextureWhenSelect;
|
_backgroundTextureRect.Texture = _backgroundTextureWhenSelect;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_backgroundTextureRect.Texture = _backgroundTexture;
|
_backgroundTextureRect.Texture = _backgroundTexture;
|
||||||
}
|
}
|
||||||
_isSelect = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextureRect BackgroundTextureRect => _backgroundTextureRect;
|
_isSelect = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
public TextureRect BackgroundTextureRect => _backgroundTextureRect;
|
||||||
/// <para>Sets items for the item slot</para>
|
|
||||||
/// <para>为物品槽设置物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool SetItem(IItem item)
|
|
||||||
{
|
|
||||||
if (_item == null)
|
|
||||||
{
|
|
||||||
if (item.Icon != null)
|
|
||||||
{
|
|
||||||
_iconTextureRect.Texture = item.Icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
_item = item;
|
/// <summary>
|
||||||
UpdateTooltipText(item);
|
/// <para>Get the items in the item slot</para>
|
||||||
UpdateQuantityLabel(item.Quantity);
|
/// <para>获取物品槽内的物品</para>
|
||||||
return true;
|
/// </summary>
|
||||||
}
|
/// <returns></returns>
|
||||||
else
|
public IItem? GetItem()
|
||||||
{
|
{
|
||||||
//This inventory already has items, but the items in this inventory are not the same as the incoming items
|
return _item;
|
||||||
//这个物品栏已经有物品了,但是这个物品栏的物品和传入的物品不一样
|
}
|
||||||
if (_item.Id != item.Id)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newQuantity = _item.Quantity + item.Quantity;
|
/// <summary>
|
||||||
if (newQuantity > item.MaxStackQuantity)
|
/// <para>Removes the specified number of items from the item slot</para>
|
||||||
{
|
/// <para>在物品槽内移除指定数量的物品</para>
|
||||||
//If the amount of the current item exceeds the maximum stack amount after placing it in this inventory
|
/// </summary>
|
||||||
//如果将当前物品放置到这个物品栏后,数量超过了最大叠加数量
|
/// <param name="number"></param>
|
||||||
return false;
|
/// <returns></returns>
|
||||||
}
|
public bool RemoveItem(int number)
|
||||||
|
{
|
||||||
|
if (_item == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_item.Quantity = newQuantity;
|
var newNumber = _item.Quantity - number;
|
||||||
UpdateTooltipText(item);
|
if (newNumber <= 0)
|
||||||
UpdateQuantityLabel(newQuantity);
|
{
|
||||||
return true;
|
//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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Update item tips</para>
|
/// <para>Empty the items in the item slot</para>
|
||||||
/// <para>更新物品的提示内容</para>
|
/// <para>清空物品槽内的物品</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item"></param>
|
/// <remarks>
|
||||||
private void UpdateTooltipText(IItem item)
|
///<para>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.</para>
|
||||||
{
|
///<para>此方法不会计算物品应该剩余多少个。若您希望移除指定数量的物品,请调用RemoveItem方法。</para>
|
||||||
if (Config.IsDebug())
|
/// </remarks>
|
||||||
{
|
public void ClearItem()
|
||||||
_control.TooltipText = string.Format(TranslationServer.Translate("item_prompt_debug"), item.Id,
|
{
|
||||||
TranslationServer.Translate(item.Name),
|
_item = null;
|
||||||
item.Quantity, item.MaxStackQuantity, item.GetType().Name,
|
_iconTextureRect.Texture = null;
|
||||||
TranslationServer.Translate(item.Description));
|
_control.TooltipText = null;
|
||||||
}
|
_quantityLabel.Visible = false;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
_control.TooltipText = TranslationServer.Translate(item.Name) + "\n" +
|
|
||||||
TranslationServer.Translate(item.Description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Update quantity label</para>
|
/// <para>Sets items for the item slot</para>
|
||||||
/// <para>更新数量标签</para>
|
/// <para>为物品槽设置物品</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="quantity"></param>
|
/// <param name="item"></param>
|
||||||
private void UpdateQuantityLabel(int? quantity)
|
/// <returns></returns>
|
||||||
{
|
public bool SetItem(IItem item)
|
||||||
switch (quantity)
|
{
|
||||||
{
|
if (_item == null)
|
||||||
case null:
|
{
|
||||||
_quantityLabel.Visible = false;
|
if (item.Icon != null)
|
||||||
return;
|
{
|
||||||
case > 1:
|
_iconTextureRect.Texture = item.Icon;
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
_item = item;
|
||||||
{
|
UpdateTooltipText(item);
|
||||||
_backgroundTexture = GD.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
|
UpdateQuantityLabel(item.Quantity);
|
||||||
_backgroundTextureWhenSelect = GD.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
|
return true;
|
||||||
_backgroundTextureRect =
|
}
|
||||||
GetNode<TextureRect>("BackgroundTexture");
|
else
|
||||||
_iconTextureRect = GetNode<TextureRect>("BackgroundTexture/CenterContainer/IconTextureRect");
|
{
|
||||||
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
|
//This inventory already has items, but the items in this inventory are not the same as the incoming items
|
||||||
_control = GetNode<Control>("Control");
|
//这个物品栏已经有物品了,但是这个物品栏的物品和传入的物品不一样
|
||||||
_quantityLabel.Visible = false;
|
if (_item.Id != item.Id)
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
_item.Quantity = newQuantity;
|
||||||
|
UpdateTooltipText(item);
|
||||||
|
UpdateQuantityLabel(newQuantity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update item tips</para>
|
||||||
|
/// <para>更新物品的提示内容</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update quantity label</para>
|
||||||
|
/// <para>更新数量标签</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quantity"></param>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_backgroundTexture = GD.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
|
||||||
|
_backgroundTextureWhenSelect = GD.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
|
||||||
|
_backgroundTextureRect =
|
||||||
|
GetNode<TextureRect>("BackgroundTexture");
|
||||||
|
_iconTextureRect = GetNode<TextureRect>("BackgroundTexture/CenterContainer/IconTextureRect");
|
||||||
|
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
|
||||||
|
_control = GetNode<Control>("Control");
|
||||||
|
_quantityLabel.Visible = false;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -63,9 +63,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
|
||||||
{
|
{
|
||||||
_mapGenerator.Generate(_mapGeneratorConfig);
|
_mapGenerator.Generate(_mapGeneratorConfig);
|
||||||
var packedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
var packedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
||||||
|
//Register players in the holder
|
||||||
//在持有者内注册玩家
|
//在持有者内注册玩家
|
||||||
GameSceneNodeHolder.Player = (Player)packedScene.Instantiate();
|
|
||||||
var node2D = (Node2D)packedScene.Instantiate();
|
var node2D = (Node2D)packedScene.Instantiate();
|
||||||
|
GameSceneNodeHolder.Player = node2D as Player;
|
||||||
var gameRoot = GetNode<Node2D>(".");
|
var gameRoot = GetNode<Node2D>(".");
|
||||||
gameRoot.AddChild(node2D);
|
gameRoot.AddChild(node2D);
|
||||||
node2D.Position = new Vector2(55, 70);
|
node2D.Position = new Vector2(55, 70);
|
||||||
|
@ -75,6 +76,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
|
||||||
gameRoot.AddChild(delivererOfDarkMagicPackedSceneNode2D);
|
gameRoot.AddChild(delivererOfDarkMagicPackedSceneNode2D);
|
||||||
delivererOfDarkMagicPackedSceneNode2D.Position = new Vector2(70, 70);
|
delivererOfDarkMagicPackedSceneNode2D.Position = new Vector2(70, 70);
|
||||||
|
|
||||||
|
//Load a weapon
|
||||||
//加载武器
|
//加载武器
|
||||||
var w = GD.Load<PackedScene>("res://prefab/weapons/staffOfTheUndead.tscn");
|
var w = GD.Load<PackedScene>("res://prefab/weapons/staffOfTheUndead.tscn");
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
|
|
|
@ -30,7 +30,7 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
||||||
/// <para>Owner</para>
|
/// <para>Owner</para>
|
||||||
/// <para>主人</para>
|
/// <para>主人</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Node2D Owner { get; set; }
|
public Node2D? Owner { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 148 B |
Loading…
Reference in New Issue
Block a user