Merge stack

💫 Better miner tile vfx
This commit is contained in:
2025-08-29 17:44:49 +08:00
parent 56cd4c2db2
commit 483773f042
2 changed files with 76 additions and 32 deletions

View File

@@ -1,9 +1,14 @@
using System.Collections;
using AceFieldNewHorizon.Scripts.Entities;
using Godot;
namespace AceFieldNewHorizon.Scripts.System;
public partial class ItemPickup : Area2D
{
[Signal]
public delegate void StackMergedEventHandler(string itemId, int totalQuantity);
public const string PickupGroupName = "ItemPickupTarget";
[Export] public string ItemId { get; set; } = "";
@@ -11,6 +16,50 @@ public partial class ItemPickup : Area2D
[Export] public bool Infinite { get; set; } = false;
[Export] public float MagnetRange { get; set; } = 64f;
public int GetItemQuantity(string itemId)
{
if (itemId == ItemId)
return Quantity;
return 0;
}
public void SetItemQuantity(string itemId, int newQuantity)
{
if (itemId == ItemId)
{
Quantity = newQuantity;
// Update the quantity label if it exists
if (_quantityLabel != null)
{
if (Quantity > 1)
_quantityLabel.Text = Quantity.ToString();
else
_quantityLabel.Text = string.Empty;
}
}
}
public bool HasItem(string itemId)
{
return itemId == ItemId;
}
public void AddItem(string itemId, int amount)
{
if (itemId == ItemId)
{
Quantity += amount;
// Update the quantity label if it exists
if (_quantityLabel != null)
{
if (Quantity > 1)
_quantityLabel.Text = Quantity.ToString();
else
_quantityLabel.Text = string.Empty;
}
}
}
private Sprite2D _sprite;
private Label _quantityLabel;
private Sprite2D _shadowSprite;
@@ -19,7 +68,8 @@ public partial class ItemPickup : Area2D
// Called when the node enters the scene tree
public override void _Ready()
{
BodyEntered += OnBodyEntered;
BodyEntered += OnEntered;
AreaEntered += OnEntered;
_sprite = GetNode<Sprite2D>("Sprite2D");
UpdateTexture();
@@ -65,11 +115,9 @@ public partial class ItemPickup : Area2D
if (_playerTarget != null)
{
var distance = Position.DistanceTo(_playerTarget.Position);
const float speed = 10f;
if (distance <= MagnetRange)
{
float speed = 10f;
Position = Position.Lerp(_playerTarget.Position, (float)delta * speed);
}
}
}
@@ -108,37 +156,32 @@ public partial class ItemPickup : Area2D
_sprite.Texture = texture;
}
private void OnBodyEntered(Node body)
private void OnEntered(Node body)
{
if (body.IsInGroup(PickupGroupName))
if (body is ItemPickup itemStack)
{
if (body.HasMethod("AddItem"))
// Only process the merge for the item with the lower instance ID to prevent double merging
if (itemStack.ItemId != ItemId || GetInstanceId() > body.GetInstanceId())
return;
// Get current quantity and add to it
var currentQuantity = itemStack.GetItemQuantity(ItemId);
var newQuantity = currentQuantity + Quantity;
itemStack.SetItemQuantity(ItemId, newQuantity);
// Emit signal for stack merge
EmitSignal(nameof(StackMerged), ItemId, newQuantity);
QueueFree();
}
else if (body.IsInGroup(PickupGroupName))
{
if (body is Player player)
{
// First check if we can merge with existing items
if (body.HasMethod("HasItem"))
{
var hasItem = (bool)body.Call("HasItem", ItemId);
if (hasItem && body.HasMethod("GetItemQuantity"))
{
// Get current quantity and add to it
var currentQuantity = (int)body.Call("GetItemQuantity", ItemId);
body.Call("SetItemQuantity", ItemId, currentQuantity + Quantity);
}
else
{
// No existing item, add as new
body.Call("AddItem", ItemId, Quantity);
}
}
else
{
// Fallback to original behavior if HasItem method doesn't exist
body.Call("AddItem", ItemId, Quantity);
}
player.AddItem(ItemId, Quantity);
}
if (!Infinite)
QueueFree(); // remove the pickup from the world
QueueFree();
}
}
}

View File

@@ -40,11 +40,12 @@ public partial class MinerTile : BaseTile
itemPickup.Quantity = 1;
// Initial position (slightly below the spawn point)
const int halfTileSize = GridUtils.TileSize / 2;
var spawnPosition = GridUtils.GridToWorld(_gridPosition);
var targetY = spawnPosition.Y - 27f; // Target Y position
var targetX = spawnPosition.X + 27f + (GD.Randf() * 10f - 5f);
var targetY = spawnPosition.Y - halfTileSize; // Target Y position
var targetX = spawnPosition.X + halfTileSize + (GD.Randf() * 10f - 5f);
itemPickup.Position =
new Vector2(spawnPosition.X + 27f, spawnPosition.Y + 16); // Start below
new Vector2(spawnPosition.X + halfTileSize, spawnPosition.Y + 16); // Start below
itemPickup.Scale = Vector2.Zero; // Start invisible
// Add to the scene