Reactor, and enemies attacking the tiles

This commit is contained in:
2025-08-31 14:30:18 +08:00
parent c72353716f
commit 09511b37c9
17 changed files with 517 additions and 222 deletions

View File

@@ -9,30 +9,46 @@ namespace AceFieldNewHorizon.Scripts.Tiles;
public partial class BaseTile : Node2D
{
[Export] public string TileId { get; set; }
[Export] public GridManager Grid { get; set; }
protected GridManager Grid { get; set; }
protected BuildingRegistry Registry { get; set; }
public int MaxDurability { get; private set; }
public int CurrentDurability { get; private set; }
public bool IsDestroyed { get; private set; }
private CollisionShape2D _collisionShape;
private Sprite2D _sprite;
private ColorRect _progressOverlay;
private Action _onConstructionComplete;
private Tween _damageTween;
public bool IsConstructing;
public bool IsConstructed;
public override void _Ready()
{
Grid = DependencyInjection.Container.GetInstance<GridManager>();
Registry = DependencyInjection.Container.GetInstance<BuildingRegistry>();
_collisionShape = GetNodeOrNull<CollisionShape2D>("CollisionShape2D");
_sprite = GetNodeOrNull<Sprite2D>("Sprite2D");
_progressOverlay = GetNodeOrNull<ColorRect>("ProgressOverlay");
if (_progressOverlay != null)
_progressOverlay.Visible = false;
// Get durability from BuildingRegistry
var buildingData = Registry?.GetBuilding(TileId);
MaxDurability = buildingData?.Durability ?? 100; // Default to 100 if not found
CurrentDurability = MaxDurability;
IsDestroyed = false;
}
public virtual void SetGhostMode(bool canPlace)
{
// Don't modify collision for constructing buildings
if (IsConstructing) return;
if (_collisionShape != null)
_collisionShape.Disabled = true;
@@ -50,6 +66,78 @@ public partial class BaseTile : Node2D
_sprite.Modulate = Colors.White;
}
public virtual bool TakeDamage(int damage)
{
if (IsDestroyed || IsConstructing) return false;
GD.Print($"[Tile] {TileId} {GetInstanceId()} took {damage} damage");
CurrentDurability = Mathf.Max(0, CurrentDurability - damage);
// Visual feedback for taking damage
ShowDamageEffect();
if (CurrentDurability <= 0)
{
Destroy();
return true; // Tile was destroyed
}
return false; // Tile is still alive
}
private void ShowDamageEffect()
{
if (_sprite == null) return;
// Cancel any existing tween
_damageTween?.Kill();
_damageTween = CreateTween();
// Flash red briefly
_damageTween.TweenProperty(_sprite, "modulate", Colors.Red, 0.1f);
_damageTween.TweenProperty(_sprite, "modulate", Colors.White, 0.1f);
// Shake effect
var originalPosition = _sprite.Position;
_damageTween.TweenMethod(
Callable.From<Vector2>(pos => _sprite.Position = pos),
originalPosition + new Vector2(-2, -2),
originalPosition + new Vector2(2, 2),
0.05f
).SetTrans(Tween.TransitionType.Bounce).SetEase(Tween.EaseType.InOut);
_damageTween.TweenMethod(
Callable.From<Vector2>(pos => _sprite.Position = pos),
originalPosition + new Vector2(2, 2),
originalPosition,
0.05f
).SetTrans(Tween.TransitionType.Bounce).SetEase(Tween.EaseType.InOut);
}
public virtual void Destroy()
{
if (IsDestroyed) return;
IsDestroyed = true;
// Disable collision using SetDeferred to avoid physics update conflicts
_collisionShape?.SetDeferred("disabled", true);
// Fade out and remove
var tween = CreateTween();
tween.TweenProperty(this, "modulate:a", 0f, 0.3f);
tween.TweenCallback(Callable.From(() => CallDeferred("queue_free")));
// Emit signal or call method when tile is destroyed
CallDeferred(nameof(OnTileDestroyed));
}
protected virtual void OnTileDestroyed()
{
// Can be overridden by derived classes for custom destruction behavior
}
// Building progress visualization
public void StartConstruction(float buildTime, Action onComplete = null)
{
@@ -57,7 +145,7 @@ public partial class BaseTile : Node2D
if (_collisionShape != null)
_collisionShape.Disabled = true;
if (_progressOverlay == null || _sprite?.Texture == null)
if (_progressOverlay == null || _sprite?.Texture == null)
{
IsConstructing = false;
onComplete?.Invoke();
@@ -95,15 +183,15 @@ public partial class BaseTile : Node2D
// Fade out the overlay
await FadeOutOverlay(0.5f);
// Construction complete - restore full opacity and enable collision
if (_sprite != null)
_sprite.Modulate = Colors.White;
IsConstructing = false;
if (_collisionShape != null)
_collisionShape.Disabled = false;
_onConstructionComplete?.Invoke();
IsConstructed = true;
}