Fixed an issue where players could pick up items that had already been picked up by other creatures. Reuse floating label instances.
修复玩家能够捡起已被其他生物捡起的物品的问题。复用悬浮标签实例。
This commit is contained in:
parent
61618c13a9
commit
7365434f2b
|
@ -72,4 +72,7 @@ log_state_processor_not_found,找不到状态处理器{0}。,State processor {0}
|
|||
log_chase_no_enemy,追逐没有敌人。,Chase no enemy.,敵がいない追跡です。
|
||||
log_bubble_not_found,找不到气泡{0}。,Bubble {0} not found.,バブル{0}が見つかりません。
|
||||
log_owner_is_not_AiCharacter,所有者不是AiCharacter。,Owner is not AiCharacter.,所有者はAiCharacterではありません。
|
||||
log_weaponContainer_is_null,武器容器为空。,Weapon container is null.,武器コンテナが空です。
|
||||
log_weaponContainer_is_null,武器容器为空。,Weapon container is null.,武器コンテナが空です。
|
||||
log_find_nearest_item,查找最近的物品。,Find the nearest item.,最も近いアイテムを見つけます。
|
||||
log_float_label_instantiate_failed,浮动标签实例化失败。,Float label instantiation failed.,フロートラベルのインスタンス化に失敗しました。
|
||||
log_pickable_picked_up,可拾捡物被捡起了,那么不显示标签。,"If the pickable item is picked up, the label is not displayed.",でも、拾得物が拾い上げられたら、ラベルは表示されません。
|
|
|
@ -218,20 +218,14 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
/// <returns></returns>
|
||||
public Node2D? FindTheNearestItem()
|
||||
{
|
||||
LogCat.Log("find_nearest_item");
|
||||
if (PickingRangeBodiesList == null || PickingRangeBodiesList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
HashSet<Node>? exclude = null;
|
||||
if (_currentItem != null)
|
||||
{
|
||||
//Prevent picking up objects in your hands again.
|
||||
//防止再次捡起自己手上的物品。
|
||||
exclude = new HashSet<Node> { _currentItem };
|
||||
}
|
||||
|
||||
return NodeUtils.GetTheNearestNode(this, PickingRangeBodiesList.ToArray(), exclude);
|
||||
return NodeUtils.GetTheNearestNode(this, PickingRangeBodiesList.ToArray(), true,
|
||||
node => !CanPickItem(node));
|
||||
}
|
||||
|
||||
|
||||
|
@ -308,25 +302,53 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Whether you can pick up specified items</para>
|
||||
/// <para>是否能捡起指定物品</para>
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private bool CanPickItem(Node node)
|
||||
{
|
||||
if (_currentItem != null && node == _currentItem)
|
||||
{
|
||||
//Do not include your own belongings.
|
||||
//不包含自己手上的物品。
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node is PickAbleTemplate pickAbleTemplate)
|
||||
{
|
||||
//Does not contain items that have been picked up.
|
||||
//不包含已被捡起的物品。
|
||||
return !pickAbleTemplate.Picked;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Pick up the specified items</para>
|
||||
/// <para>将指定物品拾起来</para>
|
||||
/// </summary>
|
||||
/// <param name="pickAbleItem"></param>
|
||||
/// <param name="pickAbleItemNode2D"></param>
|
||||
/// <returns>
|
||||
///<para>Whether successfully picked up</para>
|
||||
///<para>是否成功拾起</para>
|
||||
/// </returns>
|
||||
public bool PickItem(Node2D? pickAbleItem)
|
||||
protected bool PickItem(Node2D? pickAbleItemNode2D)
|
||||
{
|
||||
//Empty reference checking is implicitly performed here.
|
||||
//此处隐式的执行了空引用检查。
|
||||
if (pickAbleItem is not IItem item)
|
||||
if (pickAbleItemNode2D is not IItem item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ItemContainer == null)
|
||||
|
||||
//The item store is marked null, or the item container is null.
|
||||
//物品存放的标记为null,或者物品容器为null。
|
||||
if (ItemMarker2D == null || ItemContainer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -339,10 +361,10 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
return false;
|
||||
}
|
||||
|
||||
//First check if we can pick up the item.
|
||||
//先检查我们能否拾起此物品。
|
||||
var canPick = ItemContainer.CanAddItem(item);
|
||||
if (!canPick)
|
||||
//Check to see if you can fit the item into the container first.
|
||||
//先检查是否能将物品放入容器。
|
||||
var canAddItem = ItemContainer.CanAddItem(item);
|
||||
if (!canAddItem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -359,7 +381,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
//设置捡起物品的常规处理。
|
||||
//You can supplement picking up state handling for more types of objects here.
|
||||
//您可以在这里补充更多类型对象的捡起状态处理。
|
||||
if (pickAbleItem is PickAbleTemplate pickAbleTemplate)
|
||||
if (pickAbleItemNode2D is PickAbleTemplate pickAbleTemplate)
|
||||
{
|
||||
pickAbleTemplate.Owner = this;
|
||||
pickAbleTemplate.Picked = true;
|
||||
|
@ -374,16 +396,16 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
{
|
||||
//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.
|
||||
//如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。
|
||||
CurrentItem = pickAbleItem;
|
||||
CurrentItem = pickAbleItemNode2D;
|
||||
}
|
||||
else
|
||||
{
|
||||
pickAbleItem.Hide();
|
||||
pickAbleItem.ProcessMode = ProcessModeEnum.Disabled;
|
||||
pickAbleItemNode2D.Hide();
|
||||
pickAbleItemNode2D.ProcessMode = ProcessModeEnum.Disabled;
|
||||
}
|
||||
|
||||
pickAbleItem.Reparent(ItemMarker2D);
|
||||
pickAbleItem.Position = Vector2.Zero;
|
||||
NodeUtils.CallDeferredReparent(ItemMarker2D, pickAbleItemNode2D);
|
||||
pickAbleItemNode2D.Position = Vector2.Zero;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ namespace ColdMint.scripts.character;
|
|||
/// </summary>
|
||||
public partial class Player : CharacterTemplate
|
||||
{
|
||||
private PackedScene? _floatLabelPackedScene;
|
||||
|
||||
private Control? _floatLabel;
|
||||
|
||||
//Empty object projectile
|
||||
|
@ -52,7 +50,17 @@ public partial class Player : CharacterTemplate
|
|||
CharacterName = TranslationServerUtils.Translate("default_player_name");
|
||||
LogCat.LogWithFormat("player_spawn_debug", LogCat.LogLabel.Default, ReadOnlyCharacterName,
|
||||
GlobalPosition);
|
||||
_floatLabelPackedScene = GD.Load<PackedScene>("res://prefab/ui/FloatLabel.tscn");
|
||||
var floatLabelPackedScene = GD.Load<PackedScene>("res://prefab/ui/FloatLabel.tscn");
|
||||
//Initializes the float label.
|
||||
//初始化悬浮标签。
|
||||
_floatLabel = NodeUtils.InstantiatePackedScene<Control>(floatLabelPackedScene);
|
||||
if (_floatLabel == null)
|
||||
{
|
||||
throw new NullReferenceException(TranslationServer.Translate("float_label_instantiate_failed"));
|
||||
}
|
||||
|
||||
_floatLabel.Hide();
|
||||
NodeUtils.CallDeferredAddChild(this, _floatLabel);
|
||||
_parabola = GetNode<Line2D>("Parabola");
|
||||
_platformDetectionRayCast2D = GetNode<RayCast2D>("PlatformDetectionRayCast");
|
||||
UpdateOperationTip();
|
||||
|
@ -147,9 +155,8 @@ public partial class Player : CharacterTemplate
|
|||
operationTipBuilder.Append(TranslationServerUtils.Translate("action_jump_down"));
|
||||
}
|
||||
|
||||
//If the PickingRangeBodiesList is not null and the length is greater than 0
|
||||
//如果PickingRangeBodiesList不是null,且长度大于0
|
||||
if (PickingRangeBodiesList is { Count: > 0 })
|
||||
var nearestItem = FindTheNearestItem();
|
||||
if (nearestItem != null)
|
||||
{
|
||||
operationTipBuilder.Append(' ');
|
||||
operationTipBuilder.Append("[color=");
|
||||
|
@ -159,6 +166,11 @@ public partial class Player : CharacterTemplate
|
|||
TranslationServerUtils.Translate(InputMap.ActionGetEvents("pick_up")[0].AsText()));
|
||||
operationTipBuilder.Append("[/color]");
|
||||
operationTipBuilder.Append(TranslationServerUtils.Translate("action_pick_up"));
|
||||
if (nearestItem is IItem item)
|
||||
{
|
||||
operationTipBuilder.Append(item.Name);
|
||||
}
|
||||
|
||||
operationTipLabel.Text = operationTipBuilder.ToString();
|
||||
}
|
||||
|
||||
|
@ -232,11 +244,7 @@ public partial class Player : CharacterTemplate
|
|||
PickingRangeBodiesList?.Remove(pickAbleItem);
|
||||
}
|
||||
|
||||
if (_floatLabel != null)
|
||||
{
|
||||
_floatLabel.QueueFree();
|
||||
_floatLabel = null;
|
||||
}
|
||||
RecycleFloatLabel();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,35 +435,41 @@ public partial class Player : CharacterTemplate
|
|||
return;
|
||||
}
|
||||
|
||||
if (_floatLabelPackedScene != null)
|
||||
if (_floatLabel != null)
|
||||
{
|
||||
//If there is a scene of floating text, then we generate floating text.
|
||||
//如果有悬浮文本的场景,那么我们生成悬浮文本。
|
||||
_floatLabel?.QueueFree();
|
||||
_floatLabel = NodeUtils.InstantiatePackedScene<Control>(_floatLabelPackedScene);
|
||||
if (_floatLabel != null)
|
||||
if (node is not PickAbleTemplate pickAbleTemplate)
|
||||
{
|
||||
NodeUtils.CallDeferredAddChild(node, _floatLabel);
|
||||
var rotationDegreesNode2D = node2D.RotationDegrees;
|
||||
var rotationDegreesNode2DAbs = Math.Abs(rotationDegreesNode2D);
|
||||
_floatLabel.Position = rotationDegreesNode2DAbs > 90
|
||||
? new Vector2(0, PromptTextDistance)
|
||||
: new Vector2(0, -PromptTextDistance);
|
||||
_floatLabel.RotationDegrees = 0 - rotationDegreesNode2D;
|
||||
var label = _floatLabel.GetNode<Label>("Label");
|
||||
if (node is PickAbleTemplate pickAbleTemplate)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
if (pickAbleTemplate.Owner is CharacterTemplate characterTemplate)
|
||||
{
|
||||
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
|
||||
stringBuilder.Append(TranslationServerUtils.Translate("de"));
|
||||
}
|
||||
|
||||
stringBuilder.Append(TranslationServerUtils.Translate(pickAbleTemplate.Name));
|
||||
label.Text = stringBuilder.ToString();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pickAbleTemplate.Picked)
|
||||
{
|
||||
//If the pickables are picked up, the label is not displayed.
|
||||
//如果可拾捡物被捡起了,那么不显示标签。
|
||||
LogCat.LogWarning("pickable_picked_up");
|
||||
return;
|
||||
}
|
||||
|
||||
NodeUtils.CallDeferredReparent(node, _floatLabel);
|
||||
var rotationDegreesNode2D = node2D.RotationDegrees;
|
||||
var rotationDegreesNode2DAbs = Math.Abs(rotationDegreesNode2D);
|
||||
_floatLabel.GlobalPosition = node2D.GlobalPosition;
|
||||
_floatLabel.Position = rotationDegreesNode2DAbs > 90
|
||||
? new Vector2(0, PromptTextDistance)
|
||||
: new Vector2(0, -PromptTextDistance);
|
||||
_floatLabel.RotationDegrees = 0 - rotationDegreesNode2D;
|
||||
var label = _floatLabel.GetNode<Label>("Label");
|
||||
|
||||
var stringBuilder = new StringBuilder();
|
||||
if (pickAbleTemplate.Owner is CharacterTemplate characterTemplate)
|
||||
{
|
||||
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
|
||||
stringBuilder.Append(TranslationServerUtils.Translate("de"));
|
||||
}
|
||||
|
||||
stringBuilder.Append(TranslationServerUtils.Translate(pickAbleTemplate.Name));
|
||||
label.Text = stringBuilder.ToString();
|
||||
_floatLabel.Show();
|
||||
}
|
||||
|
||||
UpdateOperationTip();
|
||||
|
@ -469,13 +483,23 @@ public partial class Player : CharacterTemplate
|
|||
return;
|
||||
}
|
||||
|
||||
if (_floatLabel != null)
|
||||
RecycleFloatLabel();
|
||||
UpdateOperationTip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Recycle Float Label</para>
|
||||
/// <para>回收悬浮标签</para>
|
||||
/// </summary>
|
||||
private void RecycleFloatLabel()
|
||||
{
|
||||
if (_floatLabel == null)
|
||||
{
|
||||
_floatLabel.QueueFree();
|
||||
_floatLabel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateOperationTip();
|
||||
_floatLabel.Hide();
|
||||
NodeUtils.CallDeferredReparent(this, _floatLabel);
|
||||
}
|
||||
|
||||
protected override void OnHit(DamageTemplate damageTemplate)
|
||||
|
|
|
@ -175,17 +175,17 @@ public static class NodeUtils
|
|||
///<para>Node array</para>
|
||||
///<para>节点数组</para>
|
||||
/// </param>
|
||||
/// <param name="exclude">
|
||||
///<para>Which nodes are excluded</para>
|
||||
///<para>排除哪些节点</para>
|
||||
/// </param>
|
||||
/// <param name="excludeInvisibleNodes">
|
||||
///<para>Whether or not unseen nodes should be excluded</para>
|
||||
///<para>是否排除不可见的节点</para>
|
||||
/// </param>
|
||||
/// <param name="filter">
|
||||
///<para>Filter, which returns true within the function to filter the specified node.</para>
|
||||
///<para>过滤器,在函数内返回true,则过滤指定节点。</para>
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static Node2D? GetTheNearestNode(Node2D origin, Node[] array, HashSet<Node>? exclude = null,
|
||||
bool excludeInvisibleNodes = true)
|
||||
public static Node2D? GetTheNearestNode(Node2D origin, Node[] array,
|
||||
bool excludeInvisibleNodes = true, Func<Node2D, bool>? filter = null)
|
||||
{
|
||||
var closestDistance = float.MaxValue;
|
||||
Node2D? closestNode = null;
|
||||
|
@ -199,10 +199,10 @@ public static class NodeUtils
|
|||
continue;
|
||||
}
|
||||
|
||||
if (exclude != null && exclude.Contains(node))
|
||||
if (filter != null && filter.Invoke(node2D))
|
||||
{
|
||||
//If the current node, is within our exclusion project. So the next one.
|
||||
//如果当前节点,在我们的排除项目内。那么下一个。
|
||||
//If there is a filter, and the filter returns true, then the next.
|
||||
//如果有过滤器,且过滤器返回true,那么下一个。
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user