2024-06-21 11:16:40 +00:00
|
|
|
|
using System;
|
2024-05-24 14:58:52 +00:00
|
|
|
|
using ColdMint.scripts.utils;
|
2024-04-28 13:55:19 +00:00
|
|
|
|
using Godot;
|
|
|
|
|
|
|
|
|
|
namespace ColdMint.scripts.inventory;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>A slot in the inventory</para>
|
|
|
|
|
/// <para>物品栏内的一个插槽</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public partial class ItemSlotNode : MarginContainer
|
|
|
|
|
{
|
2024-05-08 10:22:04 +00:00
|
|
|
|
private TextureRect? _backgroundTextureRect;
|
|
|
|
|
private TextureRect? _iconTextureRect;
|
|
|
|
|
private Label? _quantityLabel;
|
|
|
|
|
private Control? _control;
|
2024-05-06 10:59:39 +00:00
|
|
|
|
private bool _isSelect;
|
2024-05-08 10:22:04 +00:00
|
|
|
|
private Texture2D? _backgroundTexture;
|
|
|
|
|
private Texture2D? _backgroundTextureWhenSelect;
|
2024-06-21 14:55:31 +00:00
|
|
|
|
private IItem? _item;
|
|
|
|
|
|
|
|
|
|
public IItem? Item
|
|
|
|
|
{
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
//Set item
|
|
|
|
|
//设置物品
|
|
|
|
|
_item = value;
|
|
|
|
|
UpdateAllDisplay();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-18 15:37:18 +00:00
|
|
|
|
|
|
|
|
|
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/IconTextureRect");
|
|
|
|
|
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
|
|
|
|
|
_control = GetNode<Control>("Control");
|
|
|
|
|
_quantityLabel.Hide();
|
|
|
|
|
}
|
2024-05-06 10:59:39 +00:00
|
|
|
|
|
2024-06-17 14:12:51 +00:00
|
|
|
|
public override Variant _GetDragData(Vector2 atPosition)
|
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
if (_isSelect || _iconTextureRect == null)
|
2024-06-17 14:12:51 +00:00
|
|
|
|
{
|
2024-06-18 15:37:18 +00:00
|
|
|
|
//Drag is not allowed if there is no icon or no pile of items.
|
|
|
|
|
//如果没有图标或者没有物品堆,那么不允许拖动。
|
|
|
|
|
return new Variant();
|
2024-06-17 14:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var textureRect = new TextureRect();
|
|
|
|
|
textureRect.ExpandMode = _iconTextureRect.ExpandMode;
|
|
|
|
|
textureRect.Size = _iconTextureRect.Size;
|
|
|
|
|
textureRect.Texture = _iconTextureRect.Texture;
|
|
|
|
|
SetDragPreview(textureRect);
|
2024-06-18 15:37:18 +00:00
|
|
|
|
return Variant.CreateFrom(this);
|
2024-06-17 14:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool _CanDropData(Vector2 atPosition, Variant data)
|
|
|
|
|
{
|
2024-06-18 15:37:18 +00:00
|
|
|
|
//If the preplaced slot does not have an icon, the preplaced slot is not allowed.
|
|
|
|
|
//如果预放置的槽位没有图标,那么不允许放置。
|
2024-06-17 14:12:51 +00:00
|
|
|
|
if (_iconTextureRect == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 15:37:18 +00:00
|
|
|
|
var type = data.VariantType;
|
|
|
|
|
if (type == Variant.Type.Nil)
|
|
|
|
|
{
|
|
|
|
|
//The preplaced data is null.
|
|
|
|
|
//预放置的数据为null。
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var itemSlotNode = data.As<ItemSlotNode>();
|
2024-06-21 11:16:40 +00:00
|
|
|
|
var item = itemSlotNode.GetItem();
|
|
|
|
|
if (item == null)
|
2024-06-18 15:37:18 +00:00
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
//Return null when trying to get the source item.
|
|
|
|
|
//尝试获取源物品时返回null。
|
2024-06-18 15:37:18 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-06-19 14:33:00 +00:00
|
|
|
|
|
2024-06-25 14:11:19 +00:00
|
|
|
|
return CanAddItem(item);
|
2024-06-21 11:16:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-21 14:55:31 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Get the items in the item container</para>
|
|
|
|
|
/// <para>获取物品容器内的物品</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>
|
|
|
|
|
///<para>There may be multiple quantities</para>
|
|
|
|
|
///<para>数量可能有多个</para>
|
|
|
|
|
/// </returns>
|
2024-06-21 11:16:40 +00:00
|
|
|
|
public IItem? GetItem()
|
|
|
|
|
{
|
|
|
|
|
return _item;
|
2024-06-18 15:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-22 15:29:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>CreateItemInstance</para>
|
|
|
|
|
/// <para>创建物品槽内的物品实例</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="number">
|
|
|
|
|
///<para>number</para>
|
|
|
|
|
///<para>数量</para>
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
///<para>Newly created item</para>
|
|
|
|
|
///<para>新创建的物品</para>
|
|
|
|
|
/// </returns>
|
|
|
|
|
public IItem? CreateItemInstance(int number)
|
|
|
|
|
{
|
|
|
|
|
if (_item is not Node2D node2D)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var duplicate = node2D.Duplicate();
|
2024-06-25 15:54:37 +00:00
|
|
|
|
if (duplicate is not Node2D newNode2D)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newNode2D.GlobalPosition = node2D.GlobalPosition;
|
2024-06-22 15:29:24 +00:00
|
|
|
|
if (duplicate is not IItem newItem)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-06-25 14:11:19 +00:00
|
|
|
|
|
2024-06-22 15:29:24 +00:00
|
|
|
|
if (number > _item.Quantity)
|
|
|
|
|
{
|
|
|
|
|
//The number of item instances created exceeds the current number of items
|
|
|
|
|
//创建的物品实例数量,超过了当前物品的数量
|
|
|
|
|
duplicate.QueueFree();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newItem.Quantity = number;
|
|
|
|
|
return newItem;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-25 15:54:37 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Empty the inventory</para>
|
|
|
|
|
/// <para>清空物品栏内的物品</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ClearItem()
|
|
|
|
|
{
|
|
|
|
|
if (_item == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_item is Node node)
|
|
|
|
|
{
|
|
|
|
|
node.QueueFree();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_item = null;
|
|
|
|
|
UpdateAllDisplay();
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 15:37:18 +00:00
|
|
|
|
public override void _DropData(Vector2 atPosition, Variant data)
|
|
|
|
|
{
|
|
|
|
|
if (_iconTextureRect == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var type = data.VariantType;
|
|
|
|
|
if (type == Variant.Type.Nil)
|
|
|
|
|
{
|
|
|
|
|
//The passed variable is null.
|
|
|
|
|
//传入的变量为null。
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var itemSlotNode = data.As<ItemSlotNode>();
|
2024-06-21 14:55:31 +00:00
|
|
|
|
var item = itemSlotNode._item;
|
|
|
|
|
if (item == null)
|
2024-06-18 15:37:18 +00:00
|
|
|
|
{
|
2024-06-21 14:55:31 +00:00
|
|
|
|
//Return null when trying to get the source item.
|
|
|
|
|
//尝试获取源物品时返回null。
|
2024-06-18 15:37:18 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-06-19 14:33:00 +00:00
|
|
|
|
|
2024-06-25 15:54:37 +00:00
|
|
|
|
itemSlotNode.ClearItem();
|
2024-06-25 14:11:19 +00:00
|
|
|
|
AddItem(item);
|
2024-06-17 14:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-25 14:11:19 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Whether to place a backpack in the current slot</para>
|
|
|
|
|
/// <para>当前槽位是否允许放置背包</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool BackpackAllowed { get; set; }
|
|
|
|
|
|
2024-05-06 10:59:39 +00:00
|
|
|
|
public bool IsSelect
|
|
|
|
|
{
|
|
|
|
|
get => _isSelect;
|
|
|
|
|
set
|
|
|
|
|
{
|
2024-05-08 10:22:04 +00:00
|
|
|
|
if (_backgroundTextureRect != null)
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-05-08 10:22:04 +00:00
|
|
|
|
_backgroundTextureRect.Texture = value ? _backgroundTextureWhenSelect : _backgroundTexture;
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_isSelect = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 10:22:04 +00:00
|
|
|
|
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
|
2024-05-06 10:59:39 +00:00
|
|
|
|
|
2024-06-14 04:22:44 +00:00
|
|
|
|
/// <summary>
|
2024-06-21 11:16:40 +00:00
|
|
|
|
/// <para>Whether the item in this node is empty</para>
|
|
|
|
|
/// <para>此节点内的物品是否为空的</para>
|
2024-05-06 10:59:39 +00:00
|
|
|
|
/// </summary>
|
2024-06-12 09:57:38 +00:00
|
|
|
|
/// <returns>
|
2024-06-21 11:16:40 +00:00
|
|
|
|
///<para>Return true if the number of items is 0 or the item object does not exist</para>
|
|
|
|
|
///<para>当物品数量为0或物品对象不存在时,返回true</para>
|
2024-06-12 09:57:38 +00:00
|
|
|
|
/// </returns>
|
2024-06-21 11:16:40 +00:00
|
|
|
|
public bool IsEmpty()
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
if (_item == null || _item.Quantity == 0)
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
return true;
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|
2024-06-12 09:57:38 +00:00
|
|
|
|
|
2024-06-21 11:16:40 +00:00
|
|
|
|
return false;
|
2024-06-12 09:57:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Update all displays of this slot</para>
|
|
|
|
|
/// <para>更新该槽位的一切显示信息</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void UpdateAllDisplay()
|
|
|
|
|
{
|
|
|
|
|
UpdateIconTexture();
|
|
|
|
|
UpdateQuantityLabel();
|
|
|
|
|
UpdateTooltipText();
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Update item tips</para>
|
|
|
|
|
/// <para>更新物品的提示内容</para>
|
|
|
|
|
/// </summary>
|
2024-06-12 09:57:38 +00:00
|
|
|
|
private void UpdateTooltipText()
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
if (_item == null)
|
2024-05-08 10:22:04 +00:00
|
|
|
|
{
|
2024-06-18 15:37:18 +00:00
|
|
|
|
TooltipText = null;
|
2024-05-08 10:22:04 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-06 10:59:39 +00:00
|
|
|
|
if (Config.IsDebug())
|
|
|
|
|
{
|
2024-05-24 14:58:52 +00:00
|
|
|
|
var debugText = TranslationServerUtils.Translate("item_prompt_debug");
|
|
|
|
|
if (debugText != null)
|
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
TooltipText = string.Format(debugText, _item.Id,
|
|
|
|
|
TranslationServerUtils.Translate(_item.Name),
|
|
|
|
|
_item.Quantity, _item.MaxQuantity, _item.GetType().Name,
|
|
|
|
|
TranslationServerUtils.Translate(_item.Description));
|
2024-05-24 14:58:52 +00:00
|
|
|
|
}
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
TooltipText = TranslationServerUtils.Translate(_item.Name) + "\n" +
|
|
|
|
|
TranslationServerUtils.Translate(_item.Description);
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Update quantity label</para>
|
|
|
|
|
/// <para>更新数量标签</para>
|
|
|
|
|
/// </summary>
|
2024-06-12 09:57:38 +00:00
|
|
|
|
private void UpdateQuantityLabel()
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-05-08 10:22:04 +00:00
|
|
|
|
if (_quantityLabel == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-21 11:16:40 +00:00
|
|
|
|
switch (_item?.Quantity)
|
2024-05-06 10:59:39 +00:00
|
|
|
|
{
|
2024-06-12 09:57:38 +00:00
|
|
|
|
case null or 1:
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_quantityLabel.Hide();
|
2024-05-06 10:59:39 +00:00
|
|
|
|
return;
|
|
|
|
|
default:
|
2024-06-12 09:57:38 +00:00
|
|
|
|
//When the quantity is not null or 1, we display the quantity.
|
|
|
|
|
//当数量不为null或1时,我们显示数量
|
2024-06-21 11:16:40 +00:00
|
|
|
|
_quantityLabel.Text = _item?.Quantity.ToString();
|
2024-06-12 09:57:38 +00:00
|
|
|
|
_quantityLabel.Show();
|
2024-05-06 10:59:39 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 15:37:18 +00:00
|
|
|
|
|
2024-06-12 09:57:38 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Update texture of the icon rect</para>
|
|
|
|
|
/// <para>更新显示的物品图标</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void UpdateIconTexture()
|
|
|
|
|
{
|
|
|
|
|
if (_iconTextureRect != null)
|
|
|
|
|
{
|
2024-06-21 11:16:40 +00:00
|
|
|
|
_iconTextureRect.Texture = _item?.Icon;
|
2024-06-12 09:57:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-21 11:16:40 +00:00
|
|
|
|
|
|
|
|
|
public bool CanAddItem(IItem item)
|
|
|
|
|
{
|
2024-06-25 14:11:19 +00:00
|
|
|
|
if (!BackpackAllowed && item is Packsack)
|
|
|
|
|
{
|
|
|
|
|
//如果禁止放置背包,且新物品是背包
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-21 11:16:40 +00:00
|
|
|
|
if (_item == null)
|
|
|
|
|
{
|
|
|
|
|
//If there is no item in the current item slot, it is allowed to add.
|
|
|
|
|
//如果当前物品槽内没物品,那么允许添加。
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.Id != _item.Id)
|
|
|
|
|
{
|
|
|
|
|
//If the item ID you want to add is different from the current item ID, disable.
|
|
|
|
|
//如果要添加的物品ID和当前的物品ID不一样,那么禁止。
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var newQuantity = item.Quantity + _item.Quantity;
|
|
|
|
|
if (newQuantity > _item.MaxQuantity)
|
|
|
|
|
{
|
|
|
|
|
//The maximum number is exceeded and items cannot be added.
|
|
|
|
|
//超过了最大数量,无法添加物品。
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Remove items from the item slot</para>
|
|
|
|
|
/// <para>从物品槽内移除物品</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="number">
|
|
|
|
|
///<para>number(Less than 0, remove all items)</para>
|
|
|
|
|
///<para>物品数量(小于0,则移除全部物品)</para>
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
///<para>How many items were actually removed</para>
|
|
|
|
|
///<para>实际移除了多少个物品</para>
|
|
|
|
|
/// </returns>
|
|
|
|
|
public int RemoveItem(int number)
|
|
|
|
|
{
|
|
|
|
|
if (_item == null)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//The number of actual removals
|
|
|
|
|
//实际移除的数量
|
|
|
|
|
var removeNumber = number < 0 ? _item.Quantity : number;
|
|
|
|
|
_item.Quantity -= removeNumber;
|
2024-06-21 14:55:31 +00:00
|
|
|
|
if (_item.Quantity <= 0)
|
|
|
|
|
{
|
2024-06-25 15:54:37 +00:00
|
|
|
|
ClearItem();
|
2024-06-21 14:55:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-21 11:16:40 +00:00
|
|
|
|
return removeNumber;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool AddItem(IItem item)
|
|
|
|
|
{
|
|
|
|
|
if (_item == null)
|
|
|
|
|
{
|
2024-06-21 14:55:31 +00:00
|
|
|
|
Item = item;
|
|
|
|
|
return true;
|
2024-06-21 11:16:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var newQuantity = item.Quantity + _item.Quantity;
|
|
|
|
|
_item.Quantity = Math.Min(newQuantity, _item.MaxQuantity);
|
2024-06-22 15:29:24 +00:00
|
|
|
|
if (item is Node2D node2D)
|
|
|
|
|
{
|
|
|
|
|
node2D.QueueFree();
|
|
|
|
|
}
|
2024-06-25 14:11:19 +00:00
|
|
|
|
|
2024-06-22 15:29:24 +00:00
|
|
|
|
UpdateQuantityLabel();
|
2024-06-21 11:16:40 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2024-05-06 10:59:39 +00:00
|
|
|
|
}
|