using System.Threading.Tasks; using AceFieldNewHorizon.Scripts.System; using Godot; using Vector2 = Godot.Vector2; namespace AceFieldNewHorizon.Scripts.Tiles; public partial class BaseTile : Node2D { [Export] public string TileId { get; set; } public BuildingData TileData { get; set; } private CollisionShape2D _collisionShape; private Sprite2D _sprite; private ColorRect _progressOverlay; private AudioStreamPlayer _completionSound; public override void _Ready() { _collisionShape = GetNodeOrNull("CollisionShape2D"); _sprite = GetNodeOrNull("Sprite2D"); _progressOverlay = GetNodeOrNull("ProgressOverlay"); if (_progressOverlay != null) _progressOverlay.Visible = false; // Setup audio player _completionSound = new AudioStreamPlayer(); AddChild(_completionSound); var sound = GD.Load("res://Sounds/Events/ConstructionComplete.wav"); if (sound != null) { _completionSound.Stream = sound; } } public void SetGhostMode(bool canPlace) { if (_collisionShape != null) _collisionShape.Disabled = true; if (_sprite != null) _sprite.Modulate = canPlace ? new Color(0, 1, 0, 0.5f) : new Color(1, 0, 0, 0.5f); } public void FinalizePlacement() { if (_collisionShape != null) _collisionShape.Disabled = false; if (_sprite != null) _sprite.Modulate = Colors.White; } // Building progress visualization public void StartConstruction(float buildTime) { if (_progressOverlay == null || _sprite?.Texture == null) return; var texSize = new Vector2(GridUtils.TileSize, GridUtils.TileSize); _progressOverlay.Visible = true; _progressOverlay.Modulate = Colors.White; _progressOverlay.Color = new Color(0, 0, 1, 0.4f); // semi-transparent blue async void RunProgress() { var elapsed = 0f; while (elapsed < buildTime) { await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame); elapsed += (float)GetProcessDeltaTime(); var ratio = Mathf.Clamp(elapsed / buildTime, 0, 1); // Fill from bottom to top, aligned with sprite center pivot _progressOverlay.Size = new Vector2(texSize.X, texSize.Y * ratio); _progressOverlay.Position = new Vector2( -texSize.X / 2, // align left edge texSize.Y / 2 - _progressOverlay.Size.Y // move upward ); } // Fade out the overlay instead of making it instantly disappear await FadeOutOverlay(0.5f); } RunProgress(); } private async Task FadeOutOverlay(float duration) { var elapsed = 0f; var startAlpha = _progressOverlay.Modulate.A; // Play completion sound if (_completionSound?.Stream != null) { _completionSound.Play(); } while (elapsed < duration) { await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame); elapsed += (float)GetProcessDeltaTime(); var alpha = Mathf.Lerp(startAlpha, 0f, elapsed / duration); _progressOverlay.Modulate = new Color(1, 1, 1, alpha); } _progressOverlay.Visible = false; _progressOverlay.Modulate = Colors.White; // Reset alpha for next use } }