diff --git a/Data/Buildings.json b/Data/Buildings.json index 316b157..ccb6a7a 100644 --- a/Data/Buildings.json +++ b/Data/Buildings.json @@ -19,7 +19,7 @@ "buildTime": 3.0, "allowedRotations": [0], "layer": 1, - "size": [3, 3] + "size": [1, 1] }, "ground": { "scene": "res://Scenes/Tiles/GroundTile.tscn", diff --git a/Scenes/Root.tscn b/Scenes/Root.tscn index 76b3edf..8daefc5 100644 --- a/Scenes/Root.tscn +++ b/Scenes/Root.tscn @@ -38,10 +38,8 @@ Inventory = NodePath("../ResourceSystem") position = Vector2(-496, -245) ItemId = "stone" Quantity = 64 -Infinite = true [node name="ItemPickup2" parent="." instance=ExtResource("7_is6ib")] position = Vector2(-495, 5) ItemId = "ore_iron" Quantity = 16 -Infinite = true diff --git a/Scenes/System/ItemPickup.tscn b/Scenes/System/ItemPickup.tscn index 4d0b51e..0c72728 100644 --- a/Scenes/System/ItemPickup.tscn +++ b/Scenes/System/ItemPickup.tscn @@ -4,18 +4,17 @@ [ext_resource type="Script" uid="uid://qgcue2doj2lf" path="res://Scripts/System/ItemPickup.cs" id="1_ps3kh"] [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") +MagnetRange = 96.0 [node name="Sprite2D" type="Sprite2D" parent="."] scale = Vector2(0.05, 0.05) texture = ExtResource("1_4weev") -[node name="Area2D" type="Area2D" parent="."] - -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("RectangleShape2D_4weev") [node name="Label" type="Label" parent="."] diff --git a/Scenes/Tiles/MinerTile.tscn b/Scenes/Tiles/MinerTile.tscn index f633e13..f390a87 100644 --- a/Scenes/Tiles/MinerTile.tscn +++ b/Scenes/Tiles/MinerTile.tscn @@ -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="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"] size = Vector2(54, 54) [node name="MinerTile" type="StaticBody2D"] -scale = Vector2(3, 3) script = ExtResource("1_mecoy") +ItemPickup = ExtResource("2_xhk0k") TileId = "miner" [node name="Sprite2D" type="Sprite2D" parent="."] diff --git a/Scripts/System/ItemPickup.cs b/Scripts/System/ItemPickup.cs index d979ef6..6fc294a 100644 --- a/Scripts/System/ItemPickup.cs +++ b/Scripts/System/ItemPickup.cs @@ -2,7 +2,7 @@ using Godot; namespace AceFieldNewHorizon.Scripts.System; -public partial class ItemPickup : Node2D +public partial class ItemPickup : Area2D { public const string PickupGroupName = "ItemPickupTarget"; @@ -19,8 +19,7 @@ public partial class ItemPickup : Node2D // Called when the node enters the scene tree public override void _Ready() { - var area = GetNode("Area2D"); - area.BodyEntered += OnBodyEntered; + BodyEntered += OnBodyEntered; _sprite = GetNode("Sprite2D"); UpdateTexture(); @@ -114,7 +113,29 @@ public partial class ItemPickup : Node2D if (body.IsInGroup(PickupGroupName)) { if (body.HasMethod("AddItem")) - body.Call("AddItem", ItemId, Quantity); + { + // 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); + } + } if (!Infinite) QueueFree(); // remove the pickup from the world diff --git a/Scripts/System/NaturalResourceGenerator.cs b/Scripts/System/NaturalResourceGenerator.cs index 54d0e05..43e0c7a 100644 --- a/Scripts/System/NaturalResourceGenerator.cs +++ b/Scripts/System/NaturalResourceGenerator.cs @@ -4,6 +4,7 @@ using Godot; using System.Collections.Generic; using System.Threading.Tasks; using AceFieldNewHorizon.Scripts.Entities; +using AceFieldNewHorizon.Scripts.Tiles; namespace AceFieldNewHorizon.Scripts.System; @@ -376,7 +377,7 @@ public partial class NaturalResourceGenerator : Node2D 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}"); return false; @@ -387,6 +388,7 @@ public partial class NaturalResourceGenerator : Node2D var offset = GridUtils.GetCenterOffset(rotatedSize, 0f); // 0f for no rotation instance.GlobalPosition = GridUtils.GridToWorld(cell) + offset; instance.ZIndex = (int)building.Layer; + instance.Grid = Grid; AddChild(instance); Grid.OccupyArea(cell, instance, building.Size, 0f, building.Layer); // GD.Print($"{LogPrefix} Successfully placed {tileType} at {cell}"); diff --git a/Scripts/System/PlacementManager.cs b/Scripts/System/PlacementManager.cs index 1446e93..fa159ba 100644 --- a/Scripts/System/PlacementManager.cs +++ b/Scripts/System/PlacementManager.cs @@ -199,6 +199,7 @@ public partial class PlacementManager : Node2D var scene = building.Scene; _ghostBuilding = (BaseTile)scene.Instantiate(); + _ghostBuilding.Grid = Grid; _ghostBuilding.SetGhostMode(true); _ghostBuilding.RotationDegrees = _currentRotation; _ghostBuilding.ZAsRelative = false; @@ -232,6 +233,7 @@ public partial class PlacementManager : Node2D // Create the building instance first var scene = building.Scene; var buildingInstance = (BaseTile)scene.Instantiate(); + buildingInstance.Grid = Grid; buildingInstance.RotationDegrees = _currentRotation; buildingInstance.ZIndex = (int)building.Layer; buildingInstance.Position = _ghostBuilding.Position; diff --git a/Scripts/Tiles/BaseTile.cs b/Scripts/Tiles/BaseTile.cs index dd523d4..f474e1b 100644 --- a/Scripts/Tiles/BaseTile.cs +++ b/Scripts/Tiles/BaseTile.cs @@ -9,12 +9,15 @@ namespace AceFieldNewHorizon.Scripts.Tiles; public partial class BaseTile : Node2D { [Export] public string TileId { get; set; } + [Export] public GridManager Grid { get; set; } private CollisionShape2D _collisionShape; private Sprite2D _sprite; private ColorRect _progressOverlay; private Action _onConstructionComplete; - private bool _isConstructing = false; + + public bool IsConstructing; + public bool IsConstructed; public override void _Ready() { @@ -28,7 +31,7 @@ public partial class BaseTile : Node2D public void SetGhostMode(bool canPlace) { // Don't modify collision for constructing buildings - if (_isConstructing) return; + if (IsConstructing) return; if (_collisionShape != null) _collisionShape.Disabled = true; @@ -50,13 +53,13 @@ public partial class BaseTile : Node2D // Building progress visualization public void StartConstruction(float buildTime, Action onComplete = null) { - _isConstructing = true; + IsConstructing = true; if (_collisionShape != null) _collisionShape.Disabled = true; if (_progressOverlay == null || _sprite?.Texture == null) { - _isConstructing = false; + IsConstructing = false; onComplete?.Invoke(); return; } @@ -97,11 +100,12 @@ public partial class BaseTile : Node2D if (_sprite != null) _sprite.Modulate = Colors.White; - _isConstructing = false; + IsConstructing = false; if (_collisionShape != null) _collisionShape.Disabled = false; _onConstructionComplete?.Invoke(); + IsConstructed = true; } RunProgress(); diff --git a/Scripts/Tiles/MinerTile.cs b/Scripts/Tiles/MinerTile.cs index adb7f99..4e0cc21 100644 --- a/Scripts/Tiles/MinerTile.cs +++ b/Scripts/Tiles/MinerTile.cs @@ -1,8 +1,63 @@ +using AceFieldNewHorizon.Scripts.System; using Godot; namespace AceFieldNewHorizon.Scripts.Tiles; - + 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(); + if (itemPickup == null) return; + + itemPickup.ItemId = ItemToMine; + itemPickup.Quantity = 1; + + // Initial position (slightly below the spawn point) + var spawnPosition = GridUtils.GridToWorld(_gridPosition); + var targetY = spawnPosition.Y - 27f; // Target Y position + var targetX = spawnPosition.X + 27f + (GD.Randf() * 10f - 5f); + itemPickup.Position = + new Vector2(spawnPosition.X + 27f, 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); + } +} \ No newline at end of file