diff --git a/Scripts/Board/CellView.cs b/Scripts/Board/CellView.cs index faa5805..9c53714 100644 --- a/Scripts/Board/CellView.cs +++ b/Scripts/Board/CellView.cs @@ -134,4 +134,24 @@ public partial class CellView : Node2D .SetEase(Tween.EaseType.Out).SetTrans(Tween.TransitionType.Cubic); tween.TweenCallback(Callable.From(() => _highlight.Visible = false)); } + + /// + /// Transformer conversion flash: bright copper pulse + scale punch. + /// Uses a distinct color from production so the two phases read apart. + /// + public void FlashTransform(float duration = 0.45f) + { + _highlight.Color = new Color(1f, 0.5f, 0.15f, 0.7f); // bright copper + _highlight.Visible = true; + + var tween = CreateTween(); + tween.SetParallel(true); + tween.TweenProperty(_highlight, "color", new Color(1f, 0.5f, 0.15f, 0f), duration) + .SetEase(Tween.EaseType.Out).SetTrans(Tween.TransitionType.Cubic); + tween.TweenProperty(_background, "scale", new Vector2(1.08f, 1.08f), duration * 0.45f) + .SetEase(Tween.EaseType.Out); + tween.Chain().TweenProperty(_background, "scale", Vector2.One, duration * 0.55f) + .SetEase(Tween.EaseType.InOut); + tween.Chain().TweenCallback(Callable.From(() => _highlight.Visible = false)); + } } diff --git a/Scripts/Pieces/PieceView.cs b/Scripts/Pieces/PieceView.cs index 68f61f6..57431e6 100644 --- a/Scripts/Pieces/PieceView.cs +++ b/Scripts/Pieces/PieceView.cs @@ -25,6 +25,9 @@ public partial class PieceView : Node2D private static readonly Color QueenColor = new("#8E3D5A"); // deep burgundy private static readonly Color WoodCargoColor = new("#A67C32"); private static readonly Color StoneCargoColor = new("#7A7A7A"); + private static readonly Color ToolsCargoColor = new("#C87533"); + private static readonly Color ArmsCargoColor = new("#8B0000"); + private static readonly Color GoldCargoColor = new("#FFD700"); private static readonly Color ShadowColor = new Color(0, 0, 0, 0.18f); public void Setup(int pieceId, PieceKind kind, Coords startCell, Coords endCell, BoardView boardView) @@ -136,6 +139,9 @@ public partial class PieceView : Node2D { CargoType.Wood => WoodCargoColor, CargoType.Stone => StoneCargoColor, + CargoType.Tools => ToolsCargoColor, + CargoType.Arms => ArmsCargoColor, + CargoType.Gold => GoldCargoColor, _ => Colors.White }; diff --git a/Scripts/Presentation/EventAnimator.cs b/Scripts/Presentation/EventAnimator.cs index 141ed7b..f58889a 100644 --- a/Scripts/Presentation/EventAnimator.cs +++ b/Scripts/Presentation/EventAnimator.cs @@ -80,6 +80,7 @@ public partial class EventAnimator : Node tween.SetParallel(false); var produceEvents = new List(); + var transformerEvents = new List(); var transferEvents = new List(); var moveEvents = new List(); var collisionEvents = new List(); @@ -92,7 +93,7 @@ public partial class EventAnimator : Node switch (evt) { case TurnStartedEvent ts: - FlushPhases(tween, produceEvents, transferEvents, moveEvents, collisionEvents); + FlushPhases(tween, produceEvents, transformerEvents, transferEvents, moveEvents, collisionEvents); tween.TweenCallback(Callable.From(() => _controlBar.UpdateTurn(ts.TurnNumber))); break; @@ -101,8 +102,7 @@ public partial class EventAnimator : Node break; case CargoConvertedEvent converted: - // Visual flash on transformer cell (treat like a produce event for animation) - produceEvents.Add(new CargoProducedEvent(converted.TurnNumber, converted.TransformerCell, converted.OutputCargo)); + transformerEvents.Add(converted); break; case CargoTransferredEvent: @@ -119,7 +119,7 @@ public partial class EventAnimator : Node break; case MissionCompleteEvent: - FlushPhases(tween, produceEvents, transferEvents, moveEvents, collisionEvents); + FlushPhases(tween, produceEvents, transformerEvents, transferEvents, moveEvents, collisionEvents); tween.TweenCallback(Callable.From(() => { SfxManager.Instance?.PlayVictory(); @@ -130,7 +130,7 @@ public partial class EventAnimator : Node break; case MissionStartedEvent: - FlushPhases(tween, produceEvents, transferEvents, moveEvents, collisionEvents); + FlushPhases(tween, produceEvents, transformerEvents, transferEvents, moveEvents, collisionEvents); tween.TweenCallback(Callable.From(() => { EmitSignal(SignalName.MissionAdvanced); @@ -142,7 +142,7 @@ public partial class EventAnimator : Node break; case TurnEndedEvent: - FlushPhases(tween, produceEvents, transferEvents, moveEvents, collisionEvents); + FlushPhases(tween, produceEvents, transformerEvents, transferEvents, moveEvents, collisionEvents); break; default: @@ -150,7 +150,7 @@ public partial class EventAnimator : Node } } - FlushPhases(tween, produceEvents, transferEvents, moveEvents, collisionEvents); + FlushPhases(tween, produceEvents, transformerEvents, transferEvents, moveEvents, collisionEvents); tween.TweenCallback(Callable.From(() => { @@ -162,10 +162,29 @@ public partial class EventAnimator : Node private void FlushPhases( Tween tween, List produceEvents, + List transformerEvents, List transferEvents, List moveEvents, List collisionEvents) { + // Phase 1a: Transformer conversions — copper flash, distinct from production + if (transformerEvents.Count > 0) + { + var captured = transformerEvents.ToList(); + tween.TweenCallback(Callable.From(() => + { + SfxManager.Instance?.PlayProduce(); + foreach (var evt in captured) + { + var cell = _boardView.GetCellView(evt.TransformerCell); + cell?.FlashTransform(0.45f); + SpawnProduceParticles(evt.TransformerCell, evt.OutputCargo); + } + })); + tween.TweenInterval(0.45f); + transformerEvents.Clear(); + } + // Phase 1: Produce — warm golden flash + particle burst if (produceEvents.Count > 0) { diff --git a/docs/PLAN.md b/docs/PLAN.md index a79e04f..8fe1d18 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -20,14 +20,12 @@ les surfaces d'interaction et d'animation. Fou → Dame + 2 transformateurs). La vision GDD/plan prevoit une campagne plus longue et un final orchestrant toutes les chaines. -### 2.2 Demandes recurrentes (post-campagne 1) -Pour forcer la preservation des automatisations entre missions : -- Une demande consomme N unites par tour. -- Si plus approvisionnee → etat "en penurie". -- Condition : aucune demande en penurie pendant X tours consecutifs. - -Implique : nouveau champ sur `DemandState`, flag shortage, regle de victoire -parametrable par mission. A valider via playtest avant d'ajouter au scope. +### 2.2 Demandes recurrentes — wiring restant +Le moteur gere le mode recurrent (`ConsumptionPerTurn`, `SustainTurns`, +shortage tracking, events `DemandShortageStarted/Cleared`). Il reste : +- Concevoir des missions utilisant le mode recurrent (post-campagne 1). +- Visualisation UI du shortage (jauge buffer rouge, pulsation d'alerte). +- Ajuster la condition de fin si un mix classique + recurrent coexiste. ---