Compare commits
3 Commits
7720e74a3d
...
60b6d6f989
Author | SHA1 | Date | |
---|---|---|---|
60b6d6f989 | |||
483773f042 | |||
56cd4c2db2 |
@@ -19,7 +19,7 @@
|
|||||||
"buildTime": 3.0,
|
"buildTime": 3.0,
|
||||||
"allowedRotations": [0],
|
"allowedRotations": [0],
|
||||||
"layer": 1,
|
"layer": 1,
|
||||||
"size": [3, 3]
|
"size": [1, 1]
|
||||||
},
|
},
|
||||||
"ground": {
|
"ground": {
|
||||||
"scene": "res://Scenes/Tiles/GroundTile.tscn",
|
"scene": "res://Scenes/Tiles/GroundTile.tscn",
|
||||||
|
@@ -38,10 +38,8 @@ Inventory = NodePath("../ResourceSystem")
|
|||||||
position = Vector2(-496, -245)
|
position = Vector2(-496, -245)
|
||||||
ItemId = "stone"
|
ItemId = "stone"
|
||||||
Quantity = 64
|
Quantity = 64
|
||||||
Infinite = true
|
|
||||||
|
|
||||||
[node name="ItemPickup2" parent="." instance=ExtResource("7_is6ib")]
|
[node name="ItemPickup2" parent="." instance=ExtResource("7_is6ib")]
|
||||||
position = Vector2(-495, 5)
|
position = Vector2(-495, 5)
|
||||||
ItemId = "ore_iron"
|
ItemId = "ore_iron"
|
||||||
Quantity = 16
|
Quantity = 16
|
||||||
Infinite = true
|
|
||||||
|
@@ -4,18 +4,17 @@
|
|||||||
[ext_resource type="Script" uid="uid://qgcue2doj2lf" path="res://Scripts/System/ItemPickup.cs" id="1_ps3kh"]
|
[ext_resource type="Script" uid="uid://qgcue2doj2lf" path="res://Scripts/System/ItemPickup.cs" id="1_ps3kh"]
|
||||||
|
|
||||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4weev"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4weev"]
|
||||||
size = Vector2(160, 160)
|
size = Vector2(50, 50)
|
||||||
|
|
||||||
[node name="ItemPickup" type="Node2D"]
|
[node name="ItemPickup" type="Area2D"]
|
||||||
script = ExtResource("1_ps3kh")
|
script = ExtResource("1_ps3kh")
|
||||||
|
MagnetRange = 96.0
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
scale = Vector2(0.05, 0.05)
|
scale = Vector2(0.05, 0.05)
|
||||||
texture = ExtResource("1_4weev")
|
texture = ExtResource("1_4weev")
|
||||||
|
|
||||||
[node name="Area2D" type="Area2D" parent="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
|
||||||
shape = SubResource("RectangleShape2D_4weev")
|
shape = SubResource("RectangleShape2D_4weev")
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="."]
|
[node name="Label" type="Label" parent="."]
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
[gd_scene load_steps=4 format=3 uid="uid://cbu81slklwq3u"]
|
[gd_scene load_steps=5 format=3 uid="uid://cbu81slklwq3u"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://dyubkyqtpcg3a" path="res://Scripts/Tiles/MinerTile.cs" id="1_mecoy"]
|
[ext_resource type="Script" uid="uid://dyubkyqtpcg3a" path="res://Scripts/Tiles/MinerTile.cs" id="1_mecoy"]
|
||||||
[ext_resource type="Texture2D" uid="uid://bt6xmcgrbb078" path="res://Scenes/Tiles/MinerTile.png" id="2_mecoy"]
|
[ext_resource type="Texture2D" uid="uid://bt6xmcgrbb078" path="res://Scenes/Tiles/MinerTile.png" id="2_mecoy"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://xwkplaxmye3v" path="res://Scenes/System/ItemPickup.tscn" id="2_xhk0k"]
|
||||||
|
|
||||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_8o613"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_8o613"]
|
||||||
size = Vector2(54, 54)
|
size = Vector2(54, 54)
|
||||||
|
|
||||||
[node name="MinerTile" type="StaticBody2D"]
|
[node name="MinerTile" type="StaticBody2D"]
|
||||||
scale = Vector2(3, 3)
|
|
||||||
script = ExtResource("1_mecoy")
|
script = ExtResource("1_mecoy")
|
||||||
|
ItemPickup = ExtResource("2_xhk0k")
|
||||||
TileId = "miner"
|
TileId = "miner"
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
@@ -1,9 +1,14 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using AceFieldNewHorizon.Scripts.Entities;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace AceFieldNewHorizon.Scripts.System;
|
namespace AceFieldNewHorizon.Scripts.System;
|
||||||
|
|
||||||
public partial class ItemPickup : Node2D
|
public partial class ItemPickup : Area2D
|
||||||
{
|
{
|
||||||
|
[Signal]
|
||||||
|
public delegate void StackMergedEventHandler(string itemId, int totalQuantity);
|
||||||
|
|
||||||
public const string PickupGroupName = "ItemPickupTarget";
|
public const string PickupGroupName = "ItemPickupTarget";
|
||||||
|
|
||||||
[Export] public string ItemId { get; set; } = "";
|
[Export] public string ItemId { get; set; } = "";
|
||||||
@@ -11,6 +16,50 @@ public partial class ItemPickup : Node2D
|
|||||||
[Export] public bool Infinite { get; set; } = false;
|
[Export] public bool Infinite { get; set; } = false;
|
||||||
[Export] public float MagnetRange { get; set; } = 64f;
|
[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 Sprite2D _sprite;
|
||||||
private Label _quantityLabel;
|
private Label _quantityLabel;
|
||||||
private Sprite2D _shadowSprite;
|
private Sprite2D _shadowSprite;
|
||||||
@@ -19,8 +68,8 @@ public partial class ItemPickup : Node2D
|
|||||||
// Called when the node enters the scene tree
|
// Called when the node enters the scene tree
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
var area = GetNode<Area2D>("Area2D");
|
BodyEntered += OnEntered;
|
||||||
area.BodyEntered += OnBodyEntered;
|
AreaEntered += OnEntered;
|
||||||
|
|
||||||
_sprite = GetNode<Sprite2D>("Sprite2D");
|
_sprite = GetNode<Sprite2D>("Sprite2D");
|
||||||
UpdateTexture();
|
UpdateTexture();
|
||||||
@@ -66,11 +115,9 @@ public partial class ItemPickup : Node2D
|
|||||||
if (_playerTarget != null)
|
if (_playerTarget != null)
|
||||||
{
|
{
|
||||||
var distance = Position.DistanceTo(_playerTarget.Position);
|
var distance = Position.DistanceTo(_playerTarget.Position);
|
||||||
|
const float speed = 10f;
|
||||||
if (distance <= MagnetRange)
|
if (distance <= MagnetRange)
|
||||||
{
|
|
||||||
float speed = 10f;
|
|
||||||
Position = Position.Lerp(_playerTarget.Position, (float)delta * speed);
|
Position = Position.Lerp(_playerTarget.Position, (float)delta * speed);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +156,32 @@ public partial class ItemPickup : Node2D
|
|||||||
_sprite.Texture = texture;
|
_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
|
||||||
body.Call("AddItem", ItemId, Quantity);
|
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)
|
||||||
|
{
|
||||||
|
player.AddItem(ItemId, Quantity);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Infinite)
|
if (!Infinite)
|
||||||
QueueFree(); // remove the pickup from the world
|
QueueFree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -4,6 +4,7 @@ using Godot;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AceFieldNewHorizon.Scripts.Entities;
|
using AceFieldNewHorizon.Scripts.Entities;
|
||||||
|
using AceFieldNewHorizon.Scripts.Tiles;
|
||||||
|
|
||||||
namespace AceFieldNewHorizon.Scripts.System;
|
namespace AceFieldNewHorizon.Scripts.System;
|
||||||
|
|
||||||
@@ -376,7 +377,7 @@ public partial class NaturalResourceGenerator : Node2D
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene.Instantiate() is not Node2D instance)
|
if (scene.Instantiate() is not BaseTile instance)
|
||||||
{
|
{
|
||||||
GD.PrintErr($"{LogPrefix} Failed to instantiate scene for: {tileType}");
|
GD.PrintErr($"{LogPrefix} Failed to instantiate scene for: {tileType}");
|
||||||
return false;
|
return false;
|
||||||
@@ -387,6 +388,7 @@ public partial class NaturalResourceGenerator : Node2D
|
|||||||
var offset = GridUtils.GetCenterOffset(rotatedSize, 0f); // 0f for no rotation
|
var offset = GridUtils.GetCenterOffset(rotatedSize, 0f); // 0f for no rotation
|
||||||
instance.GlobalPosition = GridUtils.GridToWorld(cell) + offset;
|
instance.GlobalPosition = GridUtils.GridToWorld(cell) + offset;
|
||||||
instance.ZIndex = (int)building.Layer;
|
instance.ZIndex = (int)building.Layer;
|
||||||
|
instance.Grid = Grid;
|
||||||
AddChild(instance);
|
AddChild(instance);
|
||||||
Grid.OccupyArea(cell, instance, building.Size, 0f, building.Layer);
|
Grid.OccupyArea(cell, instance, building.Size, 0f, building.Layer);
|
||||||
// GD.Print($"{LogPrefix} Successfully placed {tileType} at {cell}");
|
// GD.Print($"{LogPrefix} Successfully placed {tileType} at {cell}");
|
||||||
|
@@ -199,6 +199,7 @@ public partial class PlacementManager : Node2D
|
|||||||
var scene = building.Scene;
|
var scene = building.Scene;
|
||||||
|
|
||||||
_ghostBuilding = (BaseTile)scene.Instantiate();
|
_ghostBuilding = (BaseTile)scene.Instantiate();
|
||||||
|
_ghostBuilding.Grid = Grid;
|
||||||
_ghostBuilding.SetGhostMode(true);
|
_ghostBuilding.SetGhostMode(true);
|
||||||
_ghostBuilding.RotationDegrees = _currentRotation;
|
_ghostBuilding.RotationDegrees = _currentRotation;
|
||||||
_ghostBuilding.ZAsRelative = false;
|
_ghostBuilding.ZAsRelative = false;
|
||||||
@@ -222,6 +223,20 @@ public partial class PlacementManager : Node2D
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First check if area is free
|
||||||
|
if (!IsAreaFree(_hoveredCell, building.Size, _currentRotation, building.Layer))
|
||||||
|
{
|
||||||
|
// Check if the area is occupied by under-construction tiles
|
||||||
|
var occupiedCells = GridUtils.GetOccupiedCells(_hoveredCell, building.Size, _currentRotation);
|
||||||
|
var isUnderConstruction = occupiedCells.Any(cell =>
|
||||||
|
Grid.GetBuildingAtCell(cell, building.Layer) is BaseTile { IsConstructing: true });
|
||||||
|
|
||||||
|
if (!isUnderConstruction)
|
||||||
|
_cannotDeploySound.Play();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Consume resources first
|
// Consume resources first
|
||||||
if (!ConsumeBuildingResources(_currentBuildingId))
|
if (!ConsumeBuildingResources(_currentBuildingId))
|
||||||
{
|
{
|
||||||
@@ -229,23 +244,15 @@ public partial class PlacementManager : Node2D
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the building instance first
|
// Create the building instance
|
||||||
var scene = building.Scene;
|
var scene = building.Scene;
|
||||||
var buildingInstance = (BaseTile)scene.Instantiate();
|
var buildingInstance = (BaseTile)scene.Instantiate();
|
||||||
|
buildingInstance.Grid = Grid;
|
||||||
buildingInstance.RotationDegrees = _currentRotation;
|
buildingInstance.RotationDegrees = _currentRotation;
|
||||||
buildingInstance.ZIndex = (int)building.Layer;
|
buildingInstance.ZIndex = (int)building.Layer;
|
||||||
buildingInstance.Position = _ghostBuilding.Position;
|
buildingInstance.Position = _ghostBuilding.Position;
|
||||||
AddChild(buildingInstance);
|
AddChild(buildingInstance);
|
||||||
|
|
||||||
// First check if area is free
|
|
||||||
if (!IsAreaFree(_hoveredCell, building.Size, _currentRotation, building.Layer))
|
|
||||||
{
|
|
||||||
_cannotDeploySound.Play();
|
|
||||||
RefundBuildingResources(_currentBuildingId);
|
|
||||||
buildingInstance.QueueFree();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, area is free, so we can safely occupy it
|
// If we get here, area is free, so we can safely occupy it
|
||||||
Grid.OccupyArea(_hoveredCell, buildingInstance, building.Size, _currentRotation, building.Layer);
|
Grid.OccupyArea(_hoveredCell, buildingInstance, building.Size, _currentRotation, building.Layer);
|
||||||
|
|
||||||
@@ -284,11 +291,11 @@ public partial class PlacementManager : Node2D
|
|||||||
// Right click to destroy from current layer
|
// Right click to destroy from current layer
|
||||||
var building = Grid.GetBuildingAtCell(_hoveredCell);
|
var building = Grid.GetBuildingAtCell(_hoveredCell);
|
||||||
if (building == null) return;
|
if (building == null) return;
|
||||||
|
|
||||||
// Find all cells occupied by this building
|
// Find all cells occupied by this building
|
||||||
var buildingInfo = Grid.GetBuildingInfoAtCell(_hoveredCell, GridLayer.Building);
|
var buildingInfo = Grid.GetBuildingInfoAtCell(_hoveredCell, GridLayer.Building);
|
||||||
if (buildingInfo == null) return;
|
if (buildingInfo == null) return;
|
||||||
|
|
||||||
// Check if this building is in the build tasks (under construction)
|
// Check if this building is in the build tasks (under construction)
|
||||||
if (_buildTasks.TryGetValue(building, out var buildTask))
|
if (_buildTasks.TryGetValue(building, out var buildTask))
|
||||||
{
|
{
|
||||||
@@ -298,13 +305,13 @@ public partial class PlacementManager : Node2D
|
|||||||
_buildTasks.Remove(building);
|
_buildTasks.Remove(building);
|
||||||
_canceledSound.Play();
|
_canceledSound.Play();
|
||||||
if (buildingTile == null) return;
|
if (buildingTile == null) return;
|
||||||
|
|
||||||
// Refund resources for canceled build
|
// Refund resources for canceled build
|
||||||
var buildingData = Registry.GetBuilding(buildingTile.TileId);
|
var buildingData = Registry.GetBuilding(buildingTile.TileId);
|
||||||
if (buildingData != null)
|
if (buildingData != null)
|
||||||
RefundBuildingResources(buildingTile.TileId);
|
RefundBuildingResources(buildingTile.TileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up the building and grid
|
// Clean up the building and grid
|
||||||
building.QueueFree();
|
building.QueueFree();
|
||||||
Grid.FreeArea(buildingInfo.Value.Position, buildingInfo.Value.Size, buildingInfo.Value.Rotation);
|
Grid.FreeArea(buildingInfo.Value.Position, buildingInfo.Value.Size, buildingInfo.Value.Rotation);
|
||||||
|
@@ -9,12 +9,15 @@ namespace AceFieldNewHorizon.Scripts.Tiles;
|
|||||||
public partial class BaseTile : Node2D
|
public partial class BaseTile : Node2D
|
||||||
{
|
{
|
||||||
[Export] public string TileId { get; set; }
|
[Export] public string TileId { get; set; }
|
||||||
|
[Export] public GridManager Grid { get; set; }
|
||||||
|
|
||||||
private CollisionShape2D _collisionShape;
|
private CollisionShape2D _collisionShape;
|
||||||
private Sprite2D _sprite;
|
private Sprite2D _sprite;
|
||||||
private ColorRect _progressOverlay;
|
private ColorRect _progressOverlay;
|
||||||
private Action _onConstructionComplete;
|
private Action _onConstructionComplete;
|
||||||
private bool _isConstructing = false;
|
|
||||||
|
public bool IsConstructing;
|
||||||
|
public bool IsConstructed;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
@@ -28,7 +31,7 @@ public partial class BaseTile : Node2D
|
|||||||
public void SetGhostMode(bool canPlace)
|
public void SetGhostMode(bool canPlace)
|
||||||
{
|
{
|
||||||
// Don't modify collision for constructing buildings
|
// Don't modify collision for constructing buildings
|
||||||
if (_isConstructing) return;
|
if (IsConstructing) return;
|
||||||
|
|
||||||
if (_collisionShape != null)
|
if (_collisionShape != null)
|
||||||
_collisionShape.Disabled = true;
|
_collisionShape.Disabled = true;
|
||||||
@@ -50,13 +53,13 @@ public partial class BaseTile : Node2D
|
|||||||
// Building progress visualization
|
// Building progress visualization
|
||||||
public void StartConstruction(float buildTime, Action onComplete = null)
|
public void StartConstruction(float buildTime, Action onComplete = null)
|
||||||
{
|
{
|
||||||
_isConstructing = true;
|
IsConstructing = true;
|
||||||
if (_collisionShape != null)
|
if (_collisionShape != null)
|
||||||
_collisionShape.Disabled = true;
|
_collisionShape.Disabled = true;
|
||||||
|
|
||||||
if (_progressOverlay == null || _sprite?.Texture == null)
|
if (_progressOverlay == null || _sprite?.Texture == null)
|
||||||
{
|
{
|
||||||
_isConstructing = false;
|
IsConstructing = false;
|
||||||
onComplete?.Invoke();
|
onComplete?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -97,11 +100,12 @@ public partial class BaseTile : Node2D
|
|||||||
if (_sprite != null)
|
if (_sprite != null)
|
||||||
_sprite.Modulate = Colors.White;
|
_sprite.Modulate = Colors.White;
|
||||||
|
|
||||||
_isConstructing = false;
|
IsConstructing = false;
|
||||||
if (_collisionShape != null)
|
if (_collisionShape != null)
|
||||||
_collisionShape.Disabled = false;
|
_collisionShape.Disabled = false;
|
||||||
|
|
||||||
_onConstructionComplete?.Invoke();
|
_onConstructionComplete?.Invoke();
|
||||||
|
IsConstructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunProgress();
|
RunProgress();
|
||||||
|
@@ -1,8 +1,64 @@
|
|||||||
|
using AceFieldNewHorizon.Scripts.System;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace AceFieldNewHorizon.Scripts.Tiles;
|
namespace AceFieldNewHorizon.Scripts.Tiles;
|
||||||
|
|
||||||
public partial class MinerTile : BaseTile
|
public partial class MinerTile : BaseTile
|
||||||
{
|
{
|
||||||
|
[Export] public PackedScene ItemPickup { get; set; }
|
||||||
}
|
[Export] public string ItemToMine { get; set; } = "OreIron";
|
||||||
|
[Export] public int MiningRate = 1; // Items per second
|
||||||
|
|
||||||
|
private Vector2I _gridPosition;
|
||||||
|
private float _timeSinceLastMine;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
base._Ready();
|
||||||
|
_gridPosition = GridUtils.WorldToGrid(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
// Don't mine if building is not completed
|
||||||
|
if (!IsConstructed || ItemPickup == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_timeSinceLastMine += (float)delta;
|
||||||
|
|
||||||
|
if (!(_timeSinceLastMine >= 1f / MiningRate)) return;
|
||||||
|
_timeSinceLastMine = 0f;
|
||||||
|
SpawnItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnItem()
|
||||||
|
{
|
||||||
|
var itemPickup = ItemPickup?.Instantiate<ItemPickup>();
|
||||||
|
if (itemPickup == null) return;
|
||||||
|
|
||||||
|
itemPickup.ItemId = ItemToMine;
|
||||||
|
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 - halfTileSize; // Target Y position
|
||||||
|
var targetX = spawnPosition.X + halfTileSize + (GD.Randf() * 10f - 5f);
|
||||||
|
itemPickup.Position =
|
||||||
|
new Vector2(spawnPosition.X + halfTileSize, spawnPosition.Y + 16); // Start below
|
||||||
|
itemPickup.Scale = Vector2.Zero; // Start invisible
|
||||||
|
|
||||||
|
// Add to the scene
|
||||||
|
GetTree().CurrentScene.AddChild(itemPickup);
|
||||||
|
|
||||||
|
// Create the pop-up animation
|
||||||
|
var tween = CreateTween().SetTrans(Tween.TransitionType.Elastic).SetEase(Tween.EaseType.Out);
|
||||||
|
|
||||||
|
// Animate the pop-up effect
|
||||||
|
tween.TweenProperty(itemPickup, "position:y", targetY, 0.6f);
|
||||||
|
tween.Parallel().TweenProperty(itemPickup, "scale", Vector2.One, 0.6f);
|
||||||
|
|
||||||
|
// Optional: Add a slight horizontal wobble
|
||||||
|
tween.Parallel().TweenProperty(itemPickup, "position:x", targetX, 0.6f);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user