Remove item slots.
移除物品槽位。
This commit is contained in:
parent
5d6d42aa54
commit
309a7b73d2
|
@ -332,9 +332,8 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
pickAbleTemplate.Sleeping = true;
|
pickAbleTemplate.Sleeping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemStack = selectItemSlotNode.GetItemStack();
|
var selectItem = selectItemSlotNode.GetItem();
|
||||||
var itemFromStack = itemStack?.GetItem();
|
if (_currentItem == null)
|
||||||
if (itemFromStack != null && itemFromStack == item && _currentItem == null)
|
|
||||||
{
|
{
|
||||||
//If the selected item slot in the item container is a newly picked item, and there is no item in the hand, then we put the selected item into the hand.
|
//If the selected item slot in the item container is a newly picked item, and there is no item in the hand, then we put the selected item into the hand.
|
||||||
//如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。
|
//如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。
|
||||||
|
@ -667,7 +666,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
{
|
{
|
||||||
//Pick an item from the item container
|
//Pick an item from the item container
|
||||||
//从物品容器内取出一个物品
|
//从物品容器内取出一个物品
|
||||||
var item = itemSlotNode.PickItem();
|
var item = itemSlotNode.GetItem();
|
||||||
|
|
||||||
if (item is not Node2D node2D)
|
if (item is not Node2D node2D)
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,7 +87,7 @@ public partial class Player : CharacterTemplate
|
||||||
|
|
||||||
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
|
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
|
||||||
{
|
{
|
||||||
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItemStack()?.GetItem();
|
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem();
|
||||||
GameSceneNodeHolder.HideBackpackUiContainerIfVisible();
|
GameSceneNodeHolder.HideBackpackUiContainerIfVisible();
|
||||||
if (item is Node2D node2D)
|
if (item is Node2D node2D)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.item.itemStacks;
|
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -44,28 +43,7 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <para>此物品容器是否支持选中</para>
|
/// <para>此物品容器是否支持选中</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SupportSelect { get; set; }
|
public bool SupportSelect { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Determines the number of items that can be received from the specified pile</para>
|
|
||||||
/// <para>判断能从指定物品堆中接收的物品数量</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStack">
|
|
||||||
/// <para>Item stack to add to the current container</para>
|
|
||||||
/// <para>向该容器中放入物品的物品堆</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns></returns>
|
|
||||||
int CanAddItemStack(IItemStack itemStack);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Add an stack of items to this container</para>
|
|
||||||
/// <para>向当前容器中存入一堆物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStack"></param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>If the source item stack is empty after the operation is completed</para>
|
|
||||||
/// <para>操作完成后,源物品堆是否被取空</para>
|
|
||||||
/// </returns>
|
|
||||||
bool AddItemStack(IItemStack itemStack);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Gets the selected location</para>
|
/// <para>Gets the selected location</para>
|
||||||
|
@ -81,23 +59,8 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ItemSlotNode? GetSelectItemSlotNode();
|
ItemSlotNode? GetSelectItemSlotNode();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>If present, remove an item from the slot at the currently selected location and return it.</para>
|
|
||||||
/// <para>如果存在,移除当前选中位置的槽位中的一个物品并将其返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="PickItemFromItemSlot"/><seealso cref="PickItemsFromItemSlotBySelectIndex"/>
|
|
||||||
IItem? PickItemFromItemSlotBySelectIndex();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove the specified number of items from the item slot at the currently selected location, and return them as a new item stack</para>
|
|
||||||
/// <para>取出当前选中位置的物品槽中指定数量的物品,并作为新的物品堆返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">
|
|
||||||
/// <para>Quantity to be taken out, inputs below zero represent all items</para>
|
|
||||||
/// <para>要取出的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <seealso cref="PickItemsFromItemSlot"/><seealso cref="PickItemFromItemSlotBySelectIndex"/>
|
|
||||||
IItemStack? PickItemsFromItemSlotBySelectIndex(int value);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Removes an item from the inventory at the currently selected location</para>
|
/// <para>Removes an item from the inventory at the currently selected location</para>
|
||||||
|
@ -111,10 +74,6 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
||||||
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
/// <remarks>
|
|
||||||
/// <para>Will remove the removed items from the game, if that is not the intent, consider using the <see cref="PickItemsFromItemSlotBySelectIndex"/></para>
|
|
||||||
/// <para>会将移除的物品从游戏中删除,如果目的并非如此,请考虑使用<see cref="PickItemsFromItemSlotBySelectIndex"/></para>
|
|
||||||
/// </remarks>
|
|
||||||
int RemoveItemFromItemSlotBySelectIndex(int number);
|
int RemoveItemFromItemSlotBySelectIndex(int number);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -139,25 +98,8 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ItemSlotNode? this[int index] => GetItemSlotNode(index);
|
ItemSlotNode? this[int index] => GetItemSlotNode(index);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>If present, remove an item from the slot in the specified location and return it.</para>
|
|
||||||
/// <para>如果存在,移除指定位置的槽位中的一个物品并将其返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="PickItemsFromItemSlot"/>
|
|
||||||
IItem? PickItemFromItemSlot(int itemSlotIndex);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove the specified number of items from the item slot in the specified location, and return them as a new item stack</para>
|
|
||||||
/// <para>取出指定位置的物品槽中指定数量的物品,并作为新的物品堆返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemSlotIndex"></param>
|
|
||||||
/// <param name="value">
|
|
||||||
/// <para>Quantity to be taken out, inputs below zero represent all items</para>
|
|
||||||
/// <para>要取出的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <seealso cref="PickItemFromItemSlot"/>
|
|
||||||
IItemStack? PickItemsFromItemSlot(int itemSlotIndex, int value);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Removes an item from the item slot in the specified location</para>
|
/// <para>Removes an item from the item slot in the specified location</para>
|
||||||
|
@ -172,10 +114,6 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
||||||
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
/// <remarks>
|
|
||||||
/// <para>Will remove the removed items from the game, if that is not the intent, consider using the <see cref="PickItemsFromItemSlot"/></para>
|
|
||||||
/// <para>会将移除的物品从游戏中删除,如果目的并非如此,请考虑使用<see cref="PickItemsFromItemSlot"/></para>
|
|
||||||
/// </remarks>
|
|
||||||
int RemoveItemFromItemSlot(int itemSlotIndex, int number);
|
int RemoveItemFromItemSlot(int itemSlotIndex, int number);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -189,43 +127,6 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
ItemSlotNode? Match(IItem item);
|
ItemSlotNode? Match(IItem item);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Based on the given item stack, match the item slots where it can be added to</para>
|
|
||||||
/// <para>根据给定的物品堆,匹配可放置它的物品槽</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stack"></param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>Return null if there is no slot to add the item slot in</para>
|
|
||||||
/// <para>若没有槽可放置此物品堆,则返回null</para>
|
|
||||||
/// </returns>
|
|
||||||
ItemSlotNode? Match(IItemStack stack);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Match the first item slot that satisfies the predicate</para>
|
|
||||||
/// <para>匹配首个拥有满足指定条件的物品槽</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="predicate">
|
|
||||||
///<para>predicate</para>
|
|
||||||
///<para>谓语</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>Return null if there is no slot satisfies the predicate</para>
|
|
||||||
/// <para>若没有满足条件的槽位,返回null</para>
|
|
||||||
/// </returns>
|
|
||||||
/// <seealso cref="MatchAll"/>
|
|
||||||
ItemSlotNode? Match(Func<ItemSlotNode, bool> predicate);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Match all item slots that satisfies the predicate</para>
|
|
||||||
/// <para>匹配所有拥有满足指定条件的物品槽</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="predicate"></param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>IEnumerable for the item slot matched to, will be empty if there's no slot satisfies the predicate</para>
|
|
||||||
/// <para>包含匹配到的槽位的IEnumerable,当没有满足条件的槽位时为空</para>
|
|
||||||
/// </returns>
|
|
||||||
IEnumerable<ItemSlotNode> MatchAll(Func<ItemSlotNode, bool> predicate);
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>AddItemSlot</para>
|
/// <para>AddItemSlot</para>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.item.itemStacks;
|
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -11,7 +12,6 @@ namespace ColdMint.scripts.inventory;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ItemSlotNode : MarginContainer
|
public partial class ItemSlotNode : MarginContainer
|
||||||
{
|
{
|
||||||
private IItemStack? _itemStack;
|
|
||||||
private TextureRect? _backgroundTextureRect;
|
private TextureRect? _backgroundTextureRect;
|
||||||
private TextureRect? _iconTextureRect;
|
private TextureRect? _iconTextureRect;
|
||||||
private Label? _quantityLabel;
|
private Label? _quantityLabel;
|
||||||
|
@ -19,6 +19,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
private bool _isSelect;
|
private bool _isSelect;
|
||||||
private Texture2D? _backgroundTexture;
|
private Texture2D? _backgroundTexture;
|
||||||
private Texture2D? _backgroundTextureWhenSelect;
|
private Texture2D? _backgroundTextureWhenSelect;
|
||||||
|
private IItem? _item = null;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
@ -34,7 +35,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
|
|
||||||
public override Variant _GetDragData(Vector2 atPosition)
|
public override Variant _GetDragData(Vector2 atPosition)
|
||||||
{
|
{
|
||||||
if (_isSelect || _iconTextureRect == null || _itemStack == null)
|
if (_isSelect || _iconTextureRect == null)
|
||||||
{
|
{
|
||||||
//Drag is not allowed if there is no icon or no pile of items.
|
//Drag is not allowed if there is no icon or no pile of items.
|
||||||
//如果没有图标或者没有物品堆,那么不允许拖动。
|
//如果没有图标或者没有物品堆,那么不允许拖动。
|
||||||
|
@ -67,15 +68,20 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemSlotNode = data.As<ItemSlotNode>();
|
var itemSlotNode = data.As<ItemSlotNode>();
|
||||||
var itemStack = itemSlotNode.GetItemStack();
|
var item = itemSlotNode.GetItem();
|
||||||
if (itemStack == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
//Return null when trying to get the source item heap.
|
//Return null when trying to get the source item.
|
||||||
//尝试获取源物品堆时返回null。
|
//尝试获取源物品时返回null。
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _itemStack == null;
|
return _item == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IItem? GetItem()
|
||||||
|
{
|
||||||
|
return _item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _DropData(Vector2 atPosition, Variant data)
|
public override void _DropData(Vector2 atPosition, Variant data)
|
||||||
|
@ -94,7 +100,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemSlotNode = data.As<ItemSlotNode>();
|
var itemSlotNode = data.As<ItemSlotNode>();
|
||||||
var itemStack = itemSlotNode.ReplaceItemStack(null);
|
var itemStack = itemSlotNode._item;
|
||||||
if (itemStack == null)
|
if (itemStack == null)
|
||||||
{
|
{
|
||||||
//Return null when trying to get the source item heap.
|
//Return null when trying to get the source item heap.
|
||||||
|
@ -102,7 +108,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplaceItemStack(itemStack);
|
// ReplaceItemStack(itemStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSelect
|
public bool IsSelect
|
||||||
|
@ -121,212 +127,22 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
|
|
||||||
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
|
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
|
||||||
|
|
||||||
public bool IsEmpty() => _itemStack == null;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Get the item stack in the item slot</para>
|
/// <para>Whether the item in this node is empty</para>
|
||||||
/// <para>获取物品槽内的物品堆</para>
|
/// <para>此节点内的物品是否为空的</para>
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IItemStack? GetItemStack() => _itemStack;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>If present, remove an item in this slot and return it.</para>
|
|
||||||
/// <para>如果存在,移除该槽位中的一个物品并将其返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="PickItems"/>
|
|
||||||
public IItem? PickItem()
|
|
||||||
{
|
|
||||||
if (_itemStack is null) return null;
|
|
||||||
|
|
||||||
var result = _itemStack.PickItem();
|
|
||||||
if (_itemStack.Empty)
|
|
||||||
{
|
|
||||||
SetItemStack(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAllDisplay();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove the specified number of items and return them as a new item stack</para>
|
|
||||||
/// <para>取出当前物品槽中指定数量的物品,并作为新的物品堆返回</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">
|
|
||||||
/// <para>Quantity to be taken out, inputs below zero represent all items</para>
|
|
||||||
/// <para>要取出的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <seealso cref="PickItem"/>
|
|
||||||
public IItemStack? PickItems(int value)
|
|
||||||
{
|
|
||||||
if (_itemStack is null) return null;
|
|
||||||
|
|
||||||
var result = _itemStack.PickItems(value);
|
|
||||||
if (_itemStack.Empty)
|
|
||||||
{
|
|
||||||
SetItemStack(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAllDisplay();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Removes the specified number of items from the item slot</para>
|
|
||||||
/// <para>在物品槽内移除指定数量的物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="number">
|
|
||||||
/// <para>Quantity to be removed, inputs below zero represent all items</para>
|
|
||||||
/// <para>要删除的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
|
||||||
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
|
||||||
/// </returns>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Will remove the removed items from the game, if that is not the intent, consider using the <see cref="PickItems"/></para>
|
|
||||||
/// <para>会将移除的物品从游戏中删除,如果目的并非如此,请考虑使用<see cref="PickItems"/></para>
|
|
||||||
/// </remarks>
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
|
||||||
if (_itemStack == null)
|
|
||||||
{
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = _itemStack.RemoveItem(number);
|
|
||||||
//If the specified number of items is removed, the number of items is less than or equal to 0. Then we empty the inventory.
|
|
||||||
//如果移除指定数量的物品后,物品数量小于或等于0。那么我们清空物品栏。
|
|
||||||
if (_itemStack.Empty)
|
|
||||||
{
|
|
||||||
SetItemStack(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAllDisplay();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove item stack from slot and return it, equivalent to ReplaceItemStack(null)</para>
|
|
||||||
/// <para>从当前槽位中移出并返回物品堆,等价于ReplaceItemStack(null)</para>
|
|
||||||
/// <seealso cref="ReplaceItemStack"/>
|
|
||||||
/// </summary>
|
|
||||||
public IItemStack? RemoveItemStack() => ReplaceItemStack(null);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Empty the item slot</para>
|
|
||||||
/// <para>清空当前物品槽</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
///<para>This method will remove all items stored in the item slots from the game, if this is not what you want to do, consider using the <see cref="RemoveItemStack"/> method.</para>
|
|
||||||
///<para>此方法会从游戏中移除储存于物品槽中的所有物品,若这不是您希望的操作,请考虑使用<see cref="RemoveItemStack"/>方法。</para>
|
|
||||||
/// </remarks>
|
|
||||||
public void ClearSlot()
|
|
||||||
{
|
|
||||||
_itemStack?.ClearStack();
|
|
||||||
SetItemStack(null);
|
|
||||||
UpdateAllDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>
|
|
||||||
/// Set item stack for this slot, this will completely replace current item stack.
|
|
||||||
/// If you want the item stack to be added to current stack, use the <see cref="AddItemStack"/>.
|
|
||||||
/// </para>
|
|
||||||
/// <para>为物品槽设置物品堆,将完全替换掉当前物品堆。如果想要物品堆叠加至该物品堆,请使用<see cref="AddItemStack"/></para>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// <para>The item stack that was previously in this slot</para>
|
///<para>Return true if the number of items is 0 or the item object does not exist</para>
|
||||||
/// <para>该槽位中原本的物品堆</para>
|
///<para>当物品数量为0或物品对象不存在时,返回true</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public IItemStack? ReplaceItemStack(IItemStack? newItemStack)
|
public bool IsEmpty()
|
||||||
{
|
{
|
||||||
var result = _itemStack;
|
if (_item == null || _item.Quantity == 0)
|
||||||
SetItemStack(newItemStack);
|
|
||||||
UpdateAllDisplay();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Can the specified item be placed in the item slot?</para>
|
|
||||||
/// <para>指定的物品是否可设置在物品槽内?</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool CanAddItem(IItem item)
|
|
||||||
{
|
|
||||||
if (_itemStack == null) return true;
|
|
||||||
return _itemStack.CanAddItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Try to add an item to this slot, if it can't be added to this slot, return false</para>
|
|
||||||
/// <para>尝试向当前槽位中加入物品,如果该物品不能被放入该槽位,返回false</para>
|
|
||||||
/// </summary>
|
|
||||||
public bool AddItem(IItem item)
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
if (_itemStack is null)
|
|
||||||
{
|
{
|
||||||
SetItemStack(IItemStack.FromItem(item));
|
return true;
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = _itemStack.AddItem(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
return false;
|
||||||
{
|
|
||||||
UpdateAllDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Determines the number of items that can be received from the specified pile</para>
|
|
||||||
/// <para>判断能从指定物品堆中接收的物品数量</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStack">
|
|
||||||
/// <para>Item stack to add to the current slot</para>
|
|
||||||
/// <para>向该物品槽中放入物品的物品堆</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public int CanAddItemStack(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
if (_itemStack is null) return itemStack.Quantity;
|
|
||||||
return _itemStack.CanTakeFrom(itemStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Try to combine an item stack into this slot</para>
|
|
||||||
/// <para>尝试将一个物品堆合并至该槽位中</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>If the source item stack is empty after the operation is completed</para>
|
|
||||||
/// <para>操作完成后,源物品堆是否被取空</para>
|
|
||||||
/// </returns>
|
|
||||||
public bool AddItemStack(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
if (_itemStack is null)
|
|
||||||
{
|
|
||||||
SetItemStack(itemStack);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = _itemStack.TakeFrom(itemStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAllDisplay();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -347,7 +163,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateTooltipText()
|
private void UpdateTooltipText()
|
||||||
{
|
{
|
||||||
if (_itemStack == null)
|
if (_item == null)
|
||||||
{
|
{
|
||||||
TooltipText = null;
|
TooltipText = null;
|
||||||
return;
|
return;
|
||||||
|
@ -358,16 +174,16 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
var debugText = TranslationServerUtils.Translate("item_prompt_debug");
|
var debugText = TranslationServerUtils.Translate("item_prompt_debug");
|
||||||
if (debugText != null)
|
if (debugText != null)
|
||||||
{
|
{
|
||||||
TooltipText = string.Format(debugText, _itemStack.GetItem()?.Id,
|
TooltipText = string.Format(debugText, _item.Id,
|
||||||
TranslationServerUtils.Translate(_itemStack.Name),
|
TranslationServerUtils.Translate(_item.Name),
|
||||||
_itemStack.Quantity, _itemStack.MaxQuantity, _itemStack.GetType().Name,
|
_item.Quantity, _item.MaxQuantity, _item.GetType().Name,
|
||||||
TranslationServerUtils.Translate(_itemStack.Description));
|
TranslationServerUtils.Translate(_item.Description));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TooltipText = TranslationServerUtils.Translate(_itemStack.Name) + "\n" +
|
TooltipText = TranslationServerUtils.Translate(_item.Name) + "\n" +
|
||||||
TranslationServerUtils.Translate(_itemStack.Description);
|
TranslationServerUtils.Translate(_item.Description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +198,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_itemStack?.Quantity)
|
switch (_item?.Quantity)
|
||||||
{
|
{
|
||||||
case null or 1:
|
case null or 1:
|
||||||
_quantityLabel.Hide();
|
_quantityLabel.Hide();
|
||||||
|
@ -390,25 +206,12 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
default:
|
default:
|
||||||
//When the quantity is not null or 1, we display the quantity.
|
//When the quantity is not null or 1, we display the quantity.
|
||||||
//当数量不为null或1时,我们显示数量
|
//当数量不为null或1时,我们显示数量
|
||||||
_quantityLabel.Text = _itemStack?.Quantity.ToString();
|
_quantityLabel.Text = _item?.Quantity.ToString();
|
||||||
_quantityLabel.Show();
|
_quantityLabel.Show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>SetItemStack</para>
|
|
||||||
/// <para>设置物品堆</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
///<para>This method broadcasts changes to the stack to the outside world</para>
|
|
||||||
///<para>此方法会对外广播物品堆的变更事件</para>
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="itemStack"></param>
|
|
||||||
private void SetItemStack(IItemStack? itemStack)
|
|
||||||
{
|
|
||||||
_itemStack = itemStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Update texture of the icon rect</para>
|
/// <para>Update texture of the icon rect</para>
|
||||||
|
@ -418,7 +221,72 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
{
|
{
|
||||||
if (_iconTextureRect != null)
|
if (_iconTextureRect != null)
|
||||||
{
|
{
|
||||||
_iconTextureRect.Texture = _itemStack?.Icon;
|
_iconTextureRect.Texture = _item?.Icon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanAddItem(IItem item)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return removeNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddItem(IItem item)
|
||||||
|
{
|
||||||
|
if (_item == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newQuantity = item.Quantity + _item.Quantity;
|
||||||
|
_item.Quantity = Math.Min(newQuantity, _item.MaxQuantity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.item.itemStacks;
|
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
@ -17,10 +16,9 @@ namespace ColdMint.scripts.inventory;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UniversalItemContainer : IItemContainer
|
public class UniversalItemContainer : IItemContainer
|
||||||
{
|
{
|
||||||
private readonly PackedScene? _itemSlotPackedScene = GD.Load<PackedScene>("res://prefab/ui/ItemSlot.tscn");
|
|
||||||
|
|
||||||
private readonly List<ItemSlotNode>? _itemSlotNodes = [];
|
private readonly List<ItemSlotNode>? _itemSlotNodes = [];
|
||||||
|
|
||||||
|
private readonly PackedScene? _itemSlotPackedScene = GD.Load<PackedScene>("res://prefab/ui/ItemSlot.tscn");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>UnknownIndex</para>
|
/// <para>UnknownIndex</para>
|
||||||
|
@ -31,8 +29,17 @@ public class UniversalItemContainer : IItemContainer
|
||||||
//_selectIndex默认为0.
|
//_selectIndex默认为0.
|
||||||
private int _selectIndex;
|
private int _selectIndex;
|
||||||
|
|
||||||
|
[MustDisposeResource]
|
||||||
|
public IEnumerator<ItemSlotNode> GetEnumerator()
|
||||||
|
{
|
||||||
|
return _itemSlotNodes?.GetEnumerator() ?? Enumerable.Empty<ItemSlotNode>().GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
public bool SupportSelect { get; set; } = true;
|
[MustDisposeResource]
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
public Action<SelectedItemSlotChangeEvent>? SelectedItemSlotChangeEvent { get; set; }
|
public Action<SelectedItemSlotChangeEvent>? SelectedItemSlotChangeEvent { get; set; }
|
||||||
|
|
||||||
|
@ -52,43 +59,16 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return itemSlotNode.AddItem(item);
|
return itemSlotNode.AddItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CanAddItemStack(IItemStack itemStack)
|
public bool SupportSelect { get; set; }
|
||||||
{
|
|
||||||
var testItem = itemStack.GetItem();
|
|
||||||
if (testItem is null) return 0;
|
|
||||||
var slots = MatchAll(slot => slot.CanAddItem(testItem));
|
|
||||||
return
|
|
||||||
Math.Min(itemStack.Quantity,
|
|
||||||
slots.Select(slot => slot.CanAddItemStack(itemStack)).Sum());
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddItemStack(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
ItemSlotNode? itemSlotNode = Match(itemStack);
|
|
||||||
while (itemSlotNode is not null)
|
|
||||||
{
|
|
||||||
if (itemSlotNode.AddItemStack(itemStack))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
itemSlotNode = Match(itemStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetSelectIndex()
|
public int GetSelectIndex()
|
||||||
{
|
{
|
||||||
if (!SupportSelect)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _selectIndex;
|
return _selectIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemSlotNode? GetSelectItemSlotNode()
|
public ItemSlotNode? GetSelectItemSlotNode()
|
||||||
{
|
{
|
||||||
if (!SupportSelect || _itemSlotNodes == null || _itemSlotNodes.Count == 0)
|
if (_itemSlotNodes == null || _itemSlotNodes.Count == 0)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -103,35 +83,7 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IItem? PickItemFromItemSlotBySelectIndex()
|
public int RemoveItemFromItemSlotBySelectIndex(int number) => RemoveItemFromItemSlot(_selectIndex, number);
|
||||||
{
|
|
||||||
if (!SupportSelect)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PickItemFromItemSlot(_selectIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItemsFromItemSlotBySelectIndex(int value)
|
|
||||||
{
|
|
||||||
if (!SupportSelect)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PickItemsFromItemSlot(_selectIndex, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItemFromItemSlotBySelectIndex(int number)
|
|
||||||
{
|
|
||||||
if (!SupportSelect)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemoveItemFromItemSlot(_selectIndex, number);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetItemSlotCount()
|
public int GetItemSlotCount()
|
||||||
{
|
{
|
||||||
|
@ -154,32 +106,6 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return _itemSlotNodes[safeIndex];
|
return _itemSlotNodes[safeIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IItem? PickItemFromItemSlot(int itemSlotIndex)
|
|
||||||
{
|
|
||||||
if (_itemSlotNodes == null) return null;
|
|
||||||
var safeIndex = GetSafeIndex(itemSlotIndex);
|
|
||||||
if (safeIndex == UnknownIndex)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemSlot = _itemSlotNodes[safeIndex];
|
|
||||||
return itemSlot.PickItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItemsFromItemSlot(int itemSlotIndex, int value)
|
|
||||||
{
|
|
||||||
if (_itemSlotNodes == null) return null;
|
|
||||||
var safeIndex = GetSafeIndex(itemSlotIndex);
|
|
||||||
if (safeIndex == UnknownIndex)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemSlot = _itemSlotNodes[safeIndex];
|
|
||||||
return itemSlot.PickItems(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItemFromItemSlot(int itemSlotIndex, int number)
|
public int RemoveItemFromItemSlot(int itemSlotIndex, int number)
|
||||||
{
|
{
|
||||||
if (_itemSlotNodes == null) return number;
|
if (_itemSlotNodes == null) return number;
|
||||||
|
@ -193,30 +119,6 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return itemSlot.RemoveItem(number);
|
return itemSlot.RemoveItem(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemSlotNode? Match(IItem item)
|
|
||||||
{
|
|
||||||
//Find and return the first slot that can hold this item, if the list is null or not found, return null
|
|
||||||
//寻找并返回第一个遇到的可放置此物品的物品槽,若列表为空或不存在,将返回null
|
|
||||||
return _itemSlotNodes?.FirstOrDefault(itemSlotNode => itemSlotNode.CanAddItem(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSlotNode? Match(IItemStack stack)
|
|
||||||
{
|
|
||||||
var item = stack.GetItem();
|
|
||||||
return item == null ? null : _itemSlotNodes?.FirstOrDefault(itemSlotNode => itemSlotNode.CanAddItem(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSlotNode? Match(Func<ItemSlotNode, bool> predicate)
|
|
||||||
{
|
|
||||||
return _itemSlotNodes?.FirstOrDefault(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<ItemSlotNode> MatchAll(Func<ItemSlotNode, bool> predicate)
|
|
||||||
{
|
|
||||||
return from node in _itemSlotNodes where predicate(node) select node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Gets a secure subscript index</para>
|
/// <para>Gets a secure subscript index</para>
|
||||||
/// <para>获取安全的下标索引</para>
|
/// <para>获取安全的下标索引</para>
|
||||||
|
@ -244,10 +146,13 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return itemSlotIndex % count;
|
return itemSlotIndex % count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public ItemSlotNode? Match(IItem item)
|
||||||
/// <para>Add items tank</para>
|
{
|
||||||
/// <para>添加物品槽</para>
|
//Find and return the first slot that can hold this item, if the list is null or not found, return null
|
||||||
/// </summary>
|
//寻找并返回第一个遇到的可放置此物品的物品槽,若列表为空或不存在,将返回null
|
||||||
|
return _itemSlotNodes?.FirstOrDefault(itemSlotNode => itemSlotNode.CanAddItem(item));
|
||||||
|
}
|
||||||
|
|
||||||
public ItemSlotNode? AddItemSlot(Node rootNode)
|
public ItemSlotNode? AddItemSlot(Node rootNode)
|
||||||
{
|
{
|
||||||
if (_itemSlotNodes == null || _itemSlotPackedScene == null)
|
if (_itemSlotNodes == null || _itemSlotPackedScene == null)
|
||||||
|
@ -261,22 +166,14 @@ public class UniversalItemContainer : IItemContainer
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SupportSelect)
|
itemSlotNode.IsSelect = (_itemSlotNodes.Count) == _selectIndex;
|
||||||
{
|
|
||||||
itemSlotNode.IsSelect = (_itemSlotNodes.Count) == _selectIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemSlotNode.IsSelect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_itemSlotNodes.Add(itemSlotNode);
|
_itemSlotNodes.Add(itemSlotNode);
|
||||||
return itemSlotNode;
|
return itemSlotNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectTheNextItemSlot()
|
public void SelectTheNextItemSlot()
|
||||||
{
|
{
|
||||||
if (!SupportSelect || _itemSlotNodes == null)
|
if (_itemSlotNodes == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -299,7 +196,7 @@ public class UniversalItemContainer : IItemContainer
|
||||||
|
|
||||||
public void SelectThePreviousItemSlot()
|
public void SelectThePreviousItemSlot()
|
||||||
{
|
{
|
||||||
if (!SupportSelect || _itemSlotNodes == null)
|
if (_itemSlotNodes == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -319,23 +216,7 @@ public class UniversalItemContainer : IItemContainer
|
||||||
|
|
||||||
PrivateSelectItemSlot(oldSelectIndex, newSelectIndex);
|
PrivateSelectItemSlot(oldSelectIndex, newSelectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectItemSlot(int newSelectIndex)
|
|
||||||
{
|
|
||||||
if (!SupportSelect || newSelectIndex == _selectIndex)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var safeIndex = GetSafeIndex(newSelectIndex);
|
|
||||||
if (safeIndex == UnknownIndex)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrivateSelectItemSlot(_selectIndex, newSelectIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Select an item slot</para>
|
/// <para>Select an item slot</para>
|
||||||
/// <para>选中某个物品槽</para>
|
/// <para>选中某个物品槽</para>
|
||||||
|
@ -360,7 +241,7 @@ public class UniversalItemContainer : IItemContainer
|
||||||
});
|
});
|
||||||
_selectIndex = newSelectIndex;
|
_selectIndex = newSelectIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>HideItem</para>
|
/// <para>HideItem</para>
|
||||||
/// <para>隐藏某个物品</para>
|
/// <para>隐藏某个物品</para>
|
||||||
|
@ -368,7 +249,7 @@ public class UniversalItemContainer : IItemContainer
|
||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
private void HideItem(int index)
|
private void HideItem(int index)
|
||||||
{
|
{
|
||||||
var oldItem = _itemSlotNodes?[index].GetItemStack()?.GetItem();
|
var oldItem = _itemSlotNodes?[index].GetItem();
|
||||||
if (oldItem is not Node2D oldNode2D) return;
|
if (oldItem is not Node2D oldNode2D) return;
|
||||||
oldNode2D.ProcessMode = Node.ProcessModeEnum.Disabled;
|
oldNode2D.ProcessMode = Node.ProcessModeEnum.Disabled;
|
||||||
oldNode2D.Hide();
|
oldNode2D.Hide();
|
||||||
|
@ -385,22 +266,25 @@ public class UniversalItemContainer : IItemContainer
|
||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
private void DisplayItem(int index)
|
private void DisplayItem(int index)
|
||||||
{
|
{
|
||||||
var item = _itemSlotNodes?[index].GetItemStack()?.GetItem();
|
var item = _itemSlotNodes?[index].GetItem();
|
||||||
if (item is not Node2D newNode2D) return;
|
if (item is not Node2D newNode2D) return;
|
||||||
newNode2D.ProcessMode = Node.ProcessModeEnum.Inherit;
|
newNode2D.ProcessMode = Node.ProcessModeEnum.Inherit;
|
||||||
newNode2D.Show();
|
newNode2D.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SelectItemSlot(int newSelectIndex)
|
||||||
[MustDisposeResource]
|
|
||||||
public IEnumerator<ItemSlotNode> GetEnumerator()
|
|
||||||
{
|
{
|
||||||
return _itemSlotNodes?.GetEnumerator() ?? Enumerable.Empty<ItemSlotNode>().GetEnumerator();
|
if (newSelectIndex == _selectIndex)
|
||||||
}
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[MustDisposeResource]
|
var safeIndex = GetSafeIndex(newSelectIndex);
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
if (safeIndex == UnknownIndex)
|
||||||
{
|
{
|
||||||
return GetEnumerator();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateSelectItemSlot(_selectIndex, newSelectIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
using ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>The special item interface makes the item a normal item, in other words, will be stacked in<see cref="CommonItemStack"/></para>
|
|
||||||
/// <para>该特殊的物品接口使得物品成为普通的物品,换言之,将会堆叠在<see cref="CommonItemStack"/>中。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// Notice when you implement: To avoid unexpected behavior, unless you understand what you're doing, the <see cref="IItem.CanStackWith"/> method
|
|
||||||
/// of an item that implements the interface must only match its own exact same instance.
|
|
||||||
/// </para>
|
|
||||||
/// <para>实现时注意:为避免意外行为,除非你明白自己在做什么,否则实现接口的物品的<see cref="IItem.CanStackWith"/>方法必须只和自己完全相同的实例匹配。</para>
|
|
||||||
/// </remarks>
|
|
||||||
public interface ICommonItem : IItem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Method to clone an instance same with self. Will be used to pick out item instance from a <see cref="CommonItemStack"/></para>
|
|
||||||
/// <para>复制与自身相同的实例的方法。将用于从 <see cref="CommonItemStack"/> 中拿取新的物品实例。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
ICommonItem CloneInstance();
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
using ColdMint.scripts.item.itemStacks;
|
using Godot;
|
||||||
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item;
|
namespace ColdMint.scripts.item;
|
||||||
|
|
||||||
|
@ -11,29 +9,36 @@ public interface IItem
|
||||||
/// <para>当前项目的ID</para>
|
/// <para>当前项目的ID</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Id { get; }
|
string Id { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Icon of current item</para>
|
/// <para>Icon of current item</para>
|
||||||
/// <para>当前项目的图标</para>
|
/// <para>当前项目的图标</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Texture2D Icon { get; }
|
Texture2D Icon { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Display name of current item</para>
|
/// <para>Display name of current item</para>
|
||||||
/// <para>显示当前Item的名称</para>
|
/// <para>显示当前Item的名称</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Description of current item, which may show in inventory</para>
|
/// <para>Description of current item, which may show in inventory</para>
|
||||||
/// <para>当前项目的描述</para>
|
/// <para>当前项目的描述</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string? Description { get; }
|
string? Description { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>
|
/// <para>Quantity</para>
|
||||||
/// Whether the current item can be put into item containers like packsack.<br/>
|
/// <para>当前的数量</para>
|
||||||
/// This attribute is usually set to false for items of the backpack class to avoid pack nesting.
|
|
||||||
/// </para>
|
|
||||||
/// <para>当前物品是否可以放入背包类的容器中。一般将背包类物品的该属性设为false来避免背包嵌套。</para>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool CanPutInPack { get; }
|
int Quantity { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>MaxItemQuantity</para>
|
||||||
|
/// <para>最大物品数量</para>
|
||||||
|
/// </summary>
|
||||||
|
int MaxQuantity { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Execute when current item is used <br/> e.g. when player clicks left mouse button with current item in hand</para>
|
/// <para>Execute when current item is used <br/> e.g. when player clicks left mouse button with current item in hand</para>
|
||||||
|
@ -42,43 +47,4 @@ public interface IItem
|
||||||
/// <param name="owner">Owner of current item, if any</param>
|
/// <param name="owner">Owner of current item, if any</param>
|
||||||
/// <param name="targetGlobalPosition">Target position, such as the position of the cursor when used by the player</param>
|
/// <param name="targetGlobalPosition">Target position, such as the position of the cursor when used by the player</param>
|
||||||
void Use(Node2D? owner, Vector2 targetGlobalPosition);
|
void Use(Node2D? owner, Vector2 targetGlobalPosition);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Execute when current item be removed from game.</para>
|
|
||||||
/// <para>当前物品从游戏中移除时执行。</para>
|
|
||||||
/// </summary>
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Return true if this item can be stacked with the given item in one stack</para>
|
|
||||||
/// <para>若该物品是否能与给定物品堆叠在同一个物品堆上,返回true</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// ! Note in the implementation: the correspondence of this predicate must be an equivalence relation over the full set of stackable items
|
|
||||||
/// (i.e., be able to derive a division into the full set of stackable items).<br/>
|
|
||||||
/// Or if the item is not stackable, make it always return false.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// !实现时注意:该谓词的对应关系必须是在全部可堆叠的物品集合上的等价关系(即能导出一个对可堆叠物品全集的划分)。<br/>
|
|
||||||
/// 或如果该物品不可堆叠,令其永远返回false。<br/>
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// If it is necessary to implement special stacking relationships (e.g. containers that can be stacked to hold items),
|
|
||||||
/// customize the special <see cref="IItemStack"/> type, implement the special stacking determination in it by overriding <see cref="IItemStack.CanAddItem"/>,
|
|
||||||
/// and override the <see cref="SpecialStack"/> method so that it returns an instance of that custom ItemStack.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// 如果有必要实现特殊的堆叠关系(如可以用堆叠来收纳物品的容器),请自定义特殊的<see cref="IItemStack"/>类型,在其中重写<see cref="IItemStack.CanAddItem"/>以实现特殊的堆叠判定,
|
|
||||||
/// 并重写<see cref="SpecialStack"/>方法使其返回该自定义ItemStack实例。
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
bool CanStackWith(IItem item);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>If this item need a special stack type, return the special item stack instance that contains the item. If else, just leave this null.</para>
|
|
||||||
/// <para>如果该项目需要特殊的物品堆类型,重写此方法来返回包含该物品的特殊物品堆实例。否则,保留原本的null返回值。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="CanStackWith"/>
|
|
||||||
IItemStack? SpecialStack() => null;
|
|
||||||
}
|
}
|
|
@ -120,9 +120,7 @@ public static class ItemTypeRegister
|
||||||
string ScenePath,
|
string ScenePath,
|
||||||
string IconPath,
|
string IconPath,
|
||||||
int MaxStackValue,
|
int MaxStackValue,
|
||||||
IList<CustomArg>? CustomArgs)
|
IList<CustomArg>? CustomArgs);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly record struct CustomArg(string Name, CustomArgType Type, string Value)
|
private readonly record struct CustomArg(string Name, CustomArgType Type, string Value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,17 +19,7 @@ public partial class Packsack : PickAbleTemplate
|
||||||
public int NumberSlots { get; set; }
|
public int NumberSlots { get; set; }
|
||||||
|
|
||||||
public override bool CanPutInPack => false;
|
public override bool CanPutInPack => false;
|
||||||
|
|
||||||
public override void Destroy()
|
|
||||||
{
|
|
||||||
if (ItemContainer == null) return;
|
|
||||||
foreach (var itemSlot in ItemContainer)
|
|
||||||
{
|
|
||||||
itemSlot.ClearSlot();
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
using System;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>An ordinary item pile, in which only one instance of the item is actually saved.</para>
|
|
||||||
/// <para>普通的物品堆,堆中实际保存的物品实例仅有一个。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
///<para>When the <see cref="AddItem"/> method is called in this implementation, the number of internal items is increased by one and new items passed in are destroyed.</para>
|
|
||||||
///<para>在此实现下调用<see cref="AddItem"/>方法时,会对内部物品的数量加一,并销毁传递进来的新物品。</para>
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="innerItem">
|
|
||||||
///<para>innerItem</para>
|
|
||||||
///<para>内部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <seealso cref="UniqueItemStack"/>
|
|
||||||
/// <seealso cref="SingleItemStack"/>
|
|
||||||
public class CommonItemStack(ICommonItem innerItem) : IItemStack
|
|
||||||
{
|
|
||||||
public int MaxQuantity { get; } = ItemTypeManager.MaxStackQuantityOf(innerItem.Id);
|
|
||||||
public int Quantity { get; private set; } = 1;
|
|
||||||
public bool Empty => Quantity == 0;
|
|
||||||
public Texture2D Icon => innerItem.Icon;
|
|
||||||
public string Name => $"{innerItem.Name}({Quantity})";
|
|
||||||
public string? Description => innerItem.Description;
|
|
||||||
|
|
||||||
public bool CanAddItem(IItem item1)
|
|
||||||
{
|
|
||||||
return innerItem.CanStackWith(item1) && (Quantity < MaxQuantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddItem(IItem item)
|
|
||||||
{
|
|
||||||
if (!CanAddItem(item)) return false;
|
|
||||||
Quantity++;
|
|
||||||
item.Destroy();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CanTakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
var item = itemStack.GetItem();
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (itemStack.Empty || !innerItem.CanStackWith(item)) return 0;
|
|
||||||
return Math.Min(itemStack.Quantity, MaxQuantity - Quantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
var number = CanTakeFrom(itemStack);
|
|
||||||
itemStack.RemoveItem(number);
|
|
||||||
Quantity += number;
|
|
||||||
return itemStack.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? GetItem()
|
|
||||||
{
|
|
||||||
return Empty ? null : innerItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? PickItem()
|
|
||||||
{
|
|
||||||
if(Empty) return null;
|
|
||||||
Quantity--;
|
|
||||||
var result = innerItem.CloneInstance();
|
|
||||||
if(Empty) innerItem.Destroy();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItems(int value)
|
|
||||||
{
|
|
||||||
if (Empty) return null;
|
|
||||||
var result = new CommonItemStack(innerItem.CloneInstance());
|
|
||||||
var n = Math.Min(Quantity, value);
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
n = Quantity;
|
|
||||||
}
|
|
||||||
result.Quantity = n;
|
|
||||||
Quantity -= n;
|
|
||||||
if (Empty) innerItem.Destroy();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
|
||||||
var n = Math.Min(number, Quantity);
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
n = Quantity;
|
|
||||||
}
|
|
||||||
Quantity -= n;
|
|
||||||
if (Empty) innerItem.Destroy();
|
|
||||||
return number - n;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearStack()
|
|
||||||
{
|
|
||||||
if (Empty) return;
|
|
||||||
Quantity = 0;
|
|
||||||
innerItem.Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,175 +0,0 @@
|
||||||
using System;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>物品槽中的物品堆</para>
|
|
||||||
/// <para>Item stack in an inventory slot</para>
|
|
||||||
/// </summary>
|
|
||||||
public interface IItemStack
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Max number of current stack</para>
|
|
||||||
/// <para>当前物品堆的最大物品数量</para>
|
|
||||||
/// </summary>
|
|
||||||
int MaxQuantity { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Quantity of current stack</para>
|
|
||||||
/// <para>当前物品堆的物品数量</para>
|
|
||||||
/// </summary>
|
|
||||||
int Quantity { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>True if this stack is empty</para>
|
|
||||||
/// <para>当物品堆空时为真</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// This attribute is used to check if the item stack is empty after the operation for subsequent processing,<br/>
|
|
||||||
/// i.e. there should not be any item stacks with this attribute true outside of the operation process
|
|
||||||
/// </para>
|
|
||||||
/// <para>此属性用于检查操作后该物品堆是否为空以便后续处理,也就是说在操作过程以外的时候不应当存在任何该属性为true的物品堆</para>
|
|
||||||
/// </remarks>
|
|
||||||
bool Empty { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Icon of current item stack</para>
|
|
||||||
/// <para>当前物品堆显示的图标</para>
|
|
||||||
/// </summary>
|
|
||||||
Texture2D Icon { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Display name of current item stack</para>
|
|
||||||
/// <para>当前物品堆显示的名称</para>
|
|
||||||
/// </summary>
|
|
||||||
string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Description of current item stack, which may show in inventory</para>
|
|
||||||
/// <para>当前物品堆的描述,可能显示在物品栏中</para>
|
|
||||||
/// </summary>
|
|
||||||
string? Description { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Determine whether a specified item can be accommodated</para>
|
|
||||||
/// <para>判断能否容纳指定物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool CanAddItem(IItem item);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Add items to the itemStack</para>
|
|
||||||
/// <para>添加物品到物品堆内</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">
|
|
||||||
///<para>Items to add</para>
|
|
||||||
///<para>需要添加的物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
///<para>Whether successful</para>
|
|
||||||
///<para>是否成功</para>
|
|
||||||
/// </returns>
|
|
||||||
public bool AddItem(IItem item);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Determines the number of items that can be received from the specified pile</para>
|
|
||||||
/// <para>判断能从指定物品堆中接收的物品数量</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStack">
|
|
||||||
/// <para>Item stack to add to the current stack</para>
|
|
||||||
/// <para>向该物品堆中放入物品的物品堆</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public int CanTakeFrom(IItemStack itemStack);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Move as many items as possible from the specified item pile to the current item pile. Items that have been moved to the current item pile should be removed from the original item pile.</para>
|
|
||||||
/// <para>将指定物品堆中尽可能多的物品移动至当前物品堆中,被移入当前堆的物品应从原物品堆中移除。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStack">
|
|
||||||
/// <para>The pile of items that are moved into the current pile</para>
|
|
||||||
/// <para>被移入当前堆的物品堆</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>Whether the original stack is empty after the operation</para>
|
|
||||||
/// <para>操作结束后原物品堆是否为空</para>
|
|
||||||
/// </returns>
|
|
||||||
public bool TakeFrom(IItemStack itemStack);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Gets an item instance of the current item pile without retrieving the item</para>
|
|
||||||
/// <para>获取当前物品堆的物品实例而不取出该物品</para>
|
|
||||||
/// <seealso cref="PickItem"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IItem? GetItem();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Pop the item instance at the top of current item stack and return it</para>
|
|
||||||
/// <para>取出当前物品堆顶部的物品实例并返回该物品</para>
|
|
||||||
/// <seealso cref="GetItem"/><seealso cref="PickItems"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IItem? PickItem();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove the specified number of items and return them as a new item stack</para>
|
|
||||||
/// <para>取出当前堆中指定数量的物品,并作为新的物品堆返回</para>
|
|
||||||
/// <seealso cref="PickItem"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">
|
|
||||||
/// <para>Quantity to be taken out, inputs below zero represent all items</para>
|
|
||||||
/// <para>要取出的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>The item stack that is taken out, can be null if out nothing, should not be the current item stack itself</para>
|
|
||||||
/// <para>取出的物品堆,没有取出物品时可为null,不应是当前物品堆自身</para>
|
|
||||||
/// </returns>
|
|
||||||
public IItemStack? PickItems(int value);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>
|
|
||||||
/// Removes the specified number of items from current item stack,removed items should be removed from the game<br/>
|
|
||||||
/// If you don't want remove them from game, consider <see cref="PickItem"/> and <see cref="PickItems"/>
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// 在当前物品堆移除指定数量的物品,被移除的物品应当从游戏中移除。<br/>
|
|
||||||
/// 如果您并不打算将它们从游戏中移除,请考虑使用 <see cref="PickItem"/> 和 <see cref="PickItems"/>
|
|
||||||
/// </para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="number">
|
|
||||||
/// <para>Quantity to be removed, inputs below zero represent all items</para>
|
|
||||||
/// <para>要删除的数量,小于0的输入代表全部物品</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
|
|
||||||
/// <para>若物品槽内物品少于指定的数量,返回相差的数量。否则返回0</para>
|
|
||||||
/// </returns>
|
|
||||||
public int RemoveItem(int number);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Clear current stack, which means should remove all items inside current stack from the game here</para>
|
|
||||||
/// <para>清除当前物品堆,意味着从游戏中移除当前堆中的所有物品</para>。
|
|
||||||
/// </summary>
|
|
||||||
public void ClearStack();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Create a new ItemStack with the given item as the first item</para>
|
|
||||||
/// <para>以给定的物品为第一个物品创建物品堆</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
///<para>Assuming the item implements the <see cref="IItem.SpecialStack"/> method, then use the return value of the SpecialStack method, otherwise extrapolate from the maximum number of stacks of items.</para>
|
|
||||||
///<para>假设物品实现了<see cref="IItem.SpecialStack"/>方法,那么使用SpecialStack方法的返回值,否则根据物品的最大堆叠数量来推断。</para>
|
|
||||||
/// </remarks>
|
|
||||||
public static IItemStack FromItem(IItem item) =>
|
|
||||||
item.SpecialStack() ??
|
|
||||||
ItemTypeManager.MaxStackQuantityOf(item.Id) switch
|
|
||||||
{
|
|
||||||
1 => new SingleItemStack(item),
|
|
||||||
> 1 => item is ICommonItem commonItem ? new CommonItemStack(commonItem) : new UniqueItemStack(item),
|
|
||||||
var other => throw new ArgumentException(
|
|
||||||
$"item {item} of type '{item.Id}' has unexpected max stack quantity {other}")
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>ItemStack for <see cref="Packsack"/> item. Can add items into pack by stack them to this stack.</para>
|
|
||||||
/// <para>用于<see cref="Packsack"/>物品的堆栈。可以将物品堆叠到此堆栈中,从而将物品添加到背包中。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="packsack"></param>
|
|
||||||
public class PacksackStack(Packsack packsack) : IItemStack
|
|
||||||
{
|
|
||||||
public int MaxQuantity => 1;
|
|
||||||
public int Quantity => 1;
|
|
||||||
public bool Empty { get; private set; }
|
|
||||||
public Texture2D Icon => packsack.Icon;
|
|
||||||
public string Name => packsack.Name;
|
|
||||||
public string? Description => packsack.Description;
|
|
||||||
|
|
||||||
public bool CanAddItem(IItem item)
|
|
||||||
{
|
|
||||||
if (!item.CanPutInPack) return false;
|
|
||||||
return packsack.ItemContainer?.CanAddItem(item) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddItem(IItem item)
|
|
||||||
{
|
|
||||||
if (!item.CanPutInPack) return false;
|
|
||||||
return packsack.ItemContainer?.AddItem(item) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CanTakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
if (itemStack.GetItem() is Packsack) return 0;
|
|
||||||
return packsack.ItemContainer?.CanAddItemStack(itemStack) ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
if (itemStack.GetItem() is Packsack) return false;
|
|
||||||
return packsack.ItemContainer?.AddItemStack(itemStack) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? GetItem()
|
|
||||||
{
|
|
||||||
return Empty ? null : packsack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? PickItem()
|
|
||||||
{
|
|
||||||
if (Empty) return null;
|
|
||||||
Empty = true;
|
|
||||||
return packsack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItems(int value)
|
|
||||||
{
|
|
||||||
if (Empty || value == 0) return null;
|
|
||||||
Empty = true;
|
|
||||||
return new PacksackStack(packsack);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
|
||||||
if (Empty || number == 0) return number;
|
|
||||||
Empty = true;
|
|
||||||
packsack.Destroy();
|
|
||||||
return Math.Max(0, number - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearStack()
|
|
||||||
{
|
|
||||||
if (Empty) return;
|
|
||||||
packsack.Destroy();
|
|
||||||
Empty = true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>One of the basic item stacks, there are always one item in stack(Stack not supported)</para>
|
|
||||||
/// <para>单身狗物品堆,基础物品堆之一,堆中永远只会有一个物品(不支持堆叠)</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="UniqueItemStack"/>
|
|
||||||
/// <seealso cref="CommonItemStack"/>
|
|
||||||
public class SingleItemStack(IItem item) : IItemStack
|
|
||||||
{
|
|
||||||
public IItem Item { get; init; } = item;
|
|
||||||
|
|
||||||
public int MaxQuantity => 1;
|
|
||||||
public int Quantity => 1;
|
|
||||||
public bool Empty { get; private set; }
|
|
||||||
public Texture2D Icon => Item.Icon;
|
|
||||||
public string Name => Item.Name;
|
|
||||||
public string? Description => Item.Description;
|
|
||||||
|
|
||||||
public bool CanAddItem(IItem item) => false;
|
|
||||||
|
|
||||||
public bool AddItem(IItem item) => false;
|
|
||||||
|
|
||||||
public int CanTakeFrom(IItemStack itemStack) => 0;
|
|
||||||
|
|
||||||
public bool TakeFrom(IItemStack itemStack) => false;
|
|
||||||
|
|
||||||
public IItem? GetItem()
|
|
||||||
{
|
|
||||||
return Empty ? null : Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? PickItem()
|
|
||||||
{
|
|
||||||
if (Empty) return null;
|
|
||||||
Empty = true;
|
|
||||||
return Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItems(int value)
|
|
||||||
{
|
|
||||||
if (value == 0 || Empty) return null;
|
|
||||||
|
|
||||||
Empty = true;
|
|
||||||
return new SingleItemStack(Item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
|
||||||
if (number == 0 || Empty) return 0;
|
|
||||||
Empty = true;
|
|
||||||
Item.Destroy();
|
|
||||||
return Math.Max(number - 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearStack()
|
|
||||||
{
|
|
||||||
RemoveItem(1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace ColdMint.scripts.item.itemStacks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>One of the basic item stacks, where each item in the stack maintains its original state (allowing for items that are not identical to each other)</para>
|
|
||||||
/// <para>独特物品堆,基础物品堆之一,堆中的每一个物品会保持各自原本的状态(允许互不相同的物品存在)</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="CommonItemStack"/><seealso cref="SingleItemStack"/>
|
|
||||||
public class UniqueItemStack : IItemStack
|
|
||||||
{
|
|
||||||
private readonly Stack<IItem> _items;
|
|
||||||
|
|
||||||
public UniqueItemStack(IItem item)
|
|
||||||
{
|
|
||||||
_items = [];
|
|
||||||
_items.Push(item);
|
|
||||||
MaxQuantity = ItemTypeManager.MaxStackQuantityOf(item.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private UniqueItemStack(UniqueItemStack from)
|
|
||||||
{
|
|
||||||
_items = from._items;
|
|
||||||
MaxQuantity = from.MaxQuantity;
|
|
||||||
Quantity = from.Quantity;
|
|
||||||
from.Quantity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int MaxQuantity { get; }
|
|
||||||
public int Quantity { get; private set; } = 1;
|
|
||||||
public bool Empty => Quantity == 0;
|
|
||||||
public Texture2D Icon => GetItem()?.Icon ?? new PlaceholderTexture2D();
|
|
||||||
public string Name => $"{GetItem()?.Name}({Quantity})";
|
|
||||||
public string? Description => GetItem()?.Description;
|
|
||||||
|
|
||||||
public bool CanAddItem(IItem item)
|
|
||||||
{
|
|
||||||
//当两个物品相容,且当前堆未满时,我们返回true
|
|
||||||
return (GetItem()?.CanStackWith(item) ?? false) && (Quantity < MaxQuantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddItem(IItem item)
|
|
||||||
{
|
|
||||||
if (!CanAddItem(item)) return false;
|
|
||||||
_items.Push(item);
|
|
||||||
Quantity++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CanTakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
if (!(itemStack.GetItem() is { } item)) return 0;
|
|
||||||
//如果两个物品相容,那么可以获取的数量取决于当前物品堆空位的大小和对方物品数量中较小的一方
|
|
||||||
if (CanAddItem(item))
|
|
||||||
return Mathf.Min(itemStack.Quantity, MaxQuantity - Quantity);
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TakeFrom(IItemStack itemStack)
|
|
||||||
{
|
|
||||||
var value = CanTakeFrom(itemStack);
|
|
||||||
for (int i = 0; i < value; i++)
|
|
||||||
{
|
|
||||||
//一个如果代码没有出错就用不到的安全检查
|
|
||||||
if (!AddItem(itemStack.PickItem()!)) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemStack.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? GetItem()
|
|
||||||
{
|
|
||||||
return Empty ? null : _items.Peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItem? PickItem()
|
|
||||||
{
|
|
||||||
if (Empty) return null;
|
|
||||||
Quantity--;
|
|
||||||
return _items.Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IItemStack? PickItems(int value)
|
|
||||||
{
|
|
||||||
if (Empty) return null;
|
|
||||||
|
|
||||||
if (value < 0) value = Quantity;
|
|
||||||
|
|
||||||
var result = new UniqueItemStack(PickItem()!);
|
|
||||||
//Calculate the amount left to take out
|
|
||||||
//计算剩余的要取出的数量
|
|
||||||
var restToMove = Math.Min(value - 1, Quantity);
|
|
||||||
for (var i = 0; i < restToMove; i++)
|
|
||||||
{
|
|
||||||
result.AddItem(PickItem()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
|
||||||
if (number < 0) number = Quantity;
|
|
||||||
while (number > 0 && Quantity > 0)
|
|
||||||
{
|
|
||||||
PickItem()!.Destroy();
|
|
||||||
number--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearStack()
|
|
||||||
{
|
|
||||||
while (Quantity > 0)
|
|
||||||
{
|
|
||||||
PickItem()!.Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,146 +22,146 @@ namespace ColdMint.scripts.loader.uiLoader;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainMenuLoader : UiLoaderTemplate
|
public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
{
|
{
|
||||||
private Button? _startGameButton;
|
private Button? _startGameButton;
|
||||||
private Label? _copyrightLabel;
|
private Label? _copyrightLabel;
|
||||||
private StringBuilder? _copyrightBuilder;
|
private StringBuilder? _copyrightBuilder;
|
||||||
private PackedScene? _gameScene;
|
private PackedScene? _gameScene;
|
||||||
private PackedScene? _contributor;
|
private PackedScene? _contributor;
|
||||||
private PackedScene? _levelGraphEditor;
|
private PackedScene? _levelGraphEditor;
|
||||||
private Label? _sloganLabel;
|
private Label? _sloganLabel;
|
||||||
private Label? _versionLabel;
|
private Label? _versionLabel;
|
||||||
private Button? _levelGraphEditorButton;
|
private Button? _levelGraphEditorButton;
|
||||||
private LinkButton? _contributorButton;
|
private LinkButton? _contributorButton;
|
||||||
|
|
||||||
public override void InitializeData()
|
public override void InitializeData()
|
||||||
{
|
{
|
||||||
if (Config.IsDebug())
|
if (Config.IsDebug())
|
||||||
{
|
{
|
||||||
//Set the minimum log level to Info in debug mode.(Print all logs)
|
//Set the minimum log level to Info in debug mode.(Print all logs)
|
||||||
//在调试模式下将最小日志等级设置为Info。(打印全部日志)
|
//在调试模式下将最小日志等级设置为Info。(打印全部日志)
|
||||||
LogCat.MinLogLevel = LogCat.InfoLogLevel;
|
LogCat.MinLogLevel = LogCat.InfoLogLevel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Disable all logs in the release version.
|
//Disable all logs in the release version.
|
||||||
//在发行版禁用所有日志。
|
//在发行版禁用所有日志。
|
||||||
LogCat.MinLogLevel = LogCat.DisableAllLogLevel;
|
LogCat.MinLogLevel = LogCat.DisableAllLogLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ContributorDataManager.RegisterAllContributorData();
|
ContributorDataManager.RegisterAllContributorData();
|
||||||
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
||||||
//Register the corresponding encoding provider to solve the problem of garbled Chinese path of the compressed package
|
//Register the corresponding encoding provider to solve the problem of garbled Chinese path of the compressed package
|
||||||
//注册对应的编码提供程序,解决压缩包中文路径乱码问题
|
//注册对应的编码提供程序,解决压缩包中文路径乱码问题
|
||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
//创建游戏数据文件夹
|
//创建游戏数据文件夹
|
||||||
var dataPath = Config.GetGameDataDirectory();
|
var dataPath = Config.GetGameDataDirectory();
|
||||||
if (!Directory.Exists(dataPath))
|
if (!Directory.Exists(dataPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(dataPath);
|
Directory.CreateDirectory(dataPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Registered camp
|
//Registered camp
|
||||||
//注册阵营
|
//注册阵营
|
||||||
var defaultCamp = new Camp(Config.CampId.Default)
|
var defaultCamp = new Camp(Config.CampId.Default)
|
||||||
{
|
{
|
||||||
FriendInjury = true
|
FriendInjury = true
|
||||||
};
|
};
|
||||||
CampManager.SetDefaultCamp(defaultCamp);
|
CampManager.SetDefaultCamp(defaultCamp);
|
||||||
var mazoku = new Camp(Config.CampId.Mazoku);
|
var mazoku = new Camp(Config.CampId.Mazoku);
|
||||||
CampManager.AddCamp(mazoku);
|
CampManager.AddCamp(mazoku);
|
||||||
var aborigines = new Camp(Config.CampId.Aborigines);
|
var aborigines = new Camp(Config.CampId.Aborigines);
|
||||||
CampManager.AddCamp(aborigines);
|
CampManager.AddCamp(aborigines);
|
||||||
_gameScene = GD.Load<PackedScene>("res://scenes/game.tscn");
|
_gameScene = GD.Load<PackedScene>("res://scenes/game.tscn");
|
||||||
_contributor = GD.Load<PackedScene>("res://scenes/contributor.tscn");
|
_contributor = GD.Load<PackedScene>("res://scenes/contributor.tscn");
|
||||||
_levelGraphEditor = GD.Load<PackedScene>("res://scenes/levelGraphEditor.tscn");
|
_levelGraphEditor = GD.Load<PackedScene>("res://scenes/levelGraphEditor.tscn");
|
||||||
|
|
||||||
//Register ItemTypes from file
|
//Register ItemTypes from file
|
||||||
//从文件注册物品类型
|
//从文件注册物品类型
|
||||||
ItemTypeRegister.RegisterFromFile();
|
ItemTypeRegister.RegisterFromFile();
|
||||||
//Hardcoded ItemTypes Register
|
//Hardcoded ItemTypes Register
|
||||||
//硬编码注册物品类型
|
//硬编码注册物品类型
|
||||||
ItemTypeRegister.StaticRegister();
|
ItemTypeRegister.StaticRegister();
|
||||||
|
|
||||||
//静态注册掉落表
|
//静态注册掉落表
|
||||||
LootRegister.StaticRegister();
|
LootRegister.StaticRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void InitializeUi()
|
public override void InitializeUi()
|
||||||
{
|
{
|
||||||
_contributorButton = GetNode<LinkButton>("VBoxContainer2/ContributorButton");
|
_contributorButton = GetNode<LinkButton>("VBoxContainer2/ContributorButton");
|
||||||
_startGameButton = GetNode<Button>("StartGameButton");
|
_startGameButton = GetNode<Button>("StartGameButton");
|
||||||
_levelGraphEditorButton = GetNode<Button>("levelGraphEditorButton");
|
_levelGraphEditorButton = GetNode<Button>("levelGraphEditorButton");
|
||||||
//The level map editor is only available in debug mode.
|
//The level map editor is only available in debug mode.
|
||||||
//关卡图编辑器仅在调试模式可用。
|
//关卡图编辑器仅在调试模式可用。
|
||||||
_levelGraphEditorButton.Visible = Config.IsDebug();
|
_levelGraphEditorButton.Visible = Config.IsDebug();
|
||||||
_startGameButton.GrabFocus();
|
_startGameButton.GrabFocus();
|
||||||
_versionLabel = GetNode<Label>("VBoxContainer2/VersionLabel");
|
_versionLabel = GetNode<Label>("VBoxContainer2/VersionLabel");
|
||||||
//Generative copyright
|
//Generative copyright
|
||||||
//生成版权
|
//生成版权
|
||||||
_copyrightLabel = GetNode<Label>("VBoxContainer/CopyrightLabel");
|
_copyrightLabel = GetNode<Label>("VBoxContainer/CopyrightLabel");
|
||||||
_sloganLabel = GetNode<Label>("CenterContainer2/SloganLabel");
|
_sloganLabel = GetNode<Label>("CenterContainer2/SloganLabel");
|
||||||
_copyrightBuilder = new StringBuilder();
|
_copyrightBuilder = new StringBuilder();
|
||||||
_copyrightBuilder.Append('\u00a9');
|
_copyrightBuilder.Append('\u00a9');
|
||||||
var currentYear = DateTime.Now.Year;
|
var currentYear = DateTime.Now.Year;
|
||||||
_copyrightBuilder.Append(Config.CreationYear);
|
_copyrightBuilder.Append(Config.CreationYear);
|
||||||
if (currentYear != Config.CreationYear)
|
if (currentYear != Config.CreationYear)
|
||||||
{
|
{
|
||||||
_copyrightBuilder.Append('-');
|
_copyrightBuilder.Append('-');
|
||||||
_copyrightBuilder.Append(currentYear);
|
_copyrightBuilder.Append(currentYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
_copyrightBuilder.Append(' ');
|
_copyrightBuilder.Append(' ');
|
||||||
_copyrightBuilder.Append(Config.CompanyName);
|
_copyrightBuilder.Append(Config.CompanyName);
|
||||||
_copyrightBuilder.Append(" all rights reserved.");
|
_copyrightBuilder.Append(" all rights reserved.");
|
||||||
_copyrightLabel.Text = _copyrightBuilder.ToString();
|
_copyrightLabel.Text = _copyrightBuilder.ToString();
|
||||||
_versionLabel.Text = "ver." + Config.GetVersion();
|
_versionLabel.Text = "ver." + Config.GetVersion();
|
||||||
_sloganLabel.Text = SloganProvider.GetSlogan();
|
_sloganLabel.Text = SloganProvider.GetSlogan();
|
||||||
_contributorButton.Text =
|
_contributorButton.Text =
|
||||||
TranslationServerUtils.TranslateWithFormat("ui_contributor_tips",
|
TranslationServerUtils.TranslateWithFormat("ui_contributor_tips",
|
||||||
ContributorDataManager.GetContributorTotals());
|
ContributorDataManager.GetContributorTotals());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadUiActions()
|
public override void LoadUiActions()
|
||||||
{
|
{
|
||||||
if (_startGameButton != null)
|
if (_startGameButton != null)
|
||||||
{
|
{
|
||||||
_startGameButton.Pressed += () =>
|
_startGameButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
if (_gameScene == null)
|
if (_gameScene == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GetTree().ChangeSceneToPacked(_gameScene);
|
GetTree().ChangeSceneToPacked(_gameScene);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_contributorButton!=null)
|
if (_contributorButton!=null)
|
||||||
{
|
{
|
||||||
_contributorButton.Pressed += () =>
|
_contributorButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
if (_contributor == null)
|
if (_contributor == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GetTree().ChangeSceneToPacked(_contributor);
|
GetTree().ChangeSceneToPacked(_contributor);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_levelGraphEditorButton != null)
|
if (_levelGraphEditorButton != null)
|
||||||
{
|
{
|
||||||
_levelGraphEditorButton.Pressed += () =>
|
_levelGraphEditorButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
LogCat.Log("level_graph_editor");
|
LogCat.Log("level_graph_editor");
|
||||||
if (_levelGraphEditor == null)
|
if (_levelGraphEditor == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GetTree().ChangeSceneToPacked(_levelGraphEditor);
|
GetTree().ChangeSceneToPacked(_levelGraphEditor);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using ColdMint.scripts.camp;
|
using ColdMint.scripts.camp;
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.pickable;
|
namespace ColdMint.scripts.pickable;
|
||||||
|
@ -39,6 +37,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
|
||||||
[Export] private int _maxContactInjury = 2;
|
[Export] private int _maxContactInjury = 2;
|
||||||
|
|
||||||
public string? Description => UniqueDescription ?? ItemTypeManager.DefaultDescriptionOf(Id);
|
public string? Description => UniqueDescription ?? ItemTypeManager.DefaultDescriptionOf(Id);
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>The number of tile maps that come into contact with this item</para>
|
/// <para>The number of tile maps that come into contact with this item</para>
|
||||||
|
@ -58,7 +57,11 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Picked { get; set; }
|
public bool Picked { get; set; }
|
||||||
|
|
||||||
public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition) { }
|
public int MaxQuantity { get; set; }
|
||||||
|
|
||||||
|
public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
@ -125,7 +128,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
|
||||||
//Determine if your side can cause damage
|
//Determine if your side can cause damage
|
||||||
//判断所属的阵营是否可以造成伤害
|
//判断所属的阵营是否可以造成伤害
|
||||||
var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId),
|
var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId),
|
||||||
CampManager.GetCamp(characterTemplate.CampId));
|
CampManager.GetCamp(characterTemplate.CampId));
|
||||||
if (!canCauseHarm)
|
if (!canCauseHarm)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -155,7 +158,9 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
|
||||||
/// <para>翻转物品</para>
|
/// <para>翻转物品</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="facingLeft"></param>
|
/// <param name="facingLeft"></param>
|
||||||
public void Flip(bool facingLeft) { }
|
public void Flip(bool facingLeft)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void Destroy()
|
public virtual void Destroy()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user