✨ Reactor, and enemies attacking the tiles
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user