using AceFieldNewHorizon.Scripts.Tiles; using Godot; namespace AceFieldNewHorizon.Scripts.System; public partial class PlacementManager : Node2D { [Export] public GridManager Grid { get; set; } [Export] public BuildingRegistry Registry { get; set; } private string _currentBuildingId = "miner"; private Vector2I _hoveredCell; private BaseTile _ghostBuilding; public void SetCurrentBuilding(string buildingId) { _currentBuildingId = buildingId; // Replace ghost immediately if (_ghostBuilding == null) return; _ghostBuilding.QueueFree(); _ghostBuilding = null; } public override void _Process(double delta) { // Snap mouse to grid var mousePos = GetGlobalMousePosition(); _hoveredCell = GridUtils.WorldToGrid(mousePos); if (_ghostBuilding == null) { var scene = Registry.GetBuilding(_currentBuildingId)?.Scene; if (scene == null) return; _ghostBuilding = (BaseTile)scene.Instantiate(); _ghostBuilding.SetGhostMode(true); AddChild(_ghostBuilding); } var placementPos = GridUtils.GridToWorld(_hoveredCell); var spaceState = GetWorld2D().DirectSpaceState; var centerPos = placementPos + new Vector2(GridUtils.TileSize / 2f, GridUtils.TileSize / 2f); var query = new PhysicsPointQueryParameters2D { Position = centerPos, CollideWithBodies = true, CollideWithAreas = true, CollisionMask = uint.MaxValue // check against all layers/masks // Exclude = new Godot.Collections.Array() // optional, see below }; var collision = spaceState.IntersectPoint(query, 8); var canPlace = Grid.IsCellFree(_hoveredCell) && collision.Count == 0; _ghostBuilding.Position = placementPos; _ghostBuilding.SetGhostMode(canPlace); // Left click to place if (Input.IsActionPressed("build_tile") && canPlace) { var scene = Registry.GetBuilding(_currentBuildingId)?.Scene; if (scene == null) return; _ghostBuilding.FinalizePlacement(); var buildingData = Registry.GetBuilding(_currentBuildingId); Grid.OccupyCell(_hoveredCell, _ghostBuilding); if (buildingData is { BuildTime: > 0f }) _ghostBuilding.StartConstruction(buildingData.BuildTime); _ghostBuilding = (BaseTile)scene.Instantiate(); _ghostBuilding.SetGhostMode(true); AddChild(_ghostBuilding); } if (Input.IsActionPressed("destroy_tile") && !Grid.IsCellFree(_hoveredCell)) { // Right click to destroy var building = Grid.GetBuildingAtCell(_hoveredCell); if (building == null) return; building.QueueFree(); Grid.FreeCell(_hoveredCell); } } }