feat(progression): composition root and event republisher (slice 9)
ProgressionRoot autoload builds the JSON stores from
GlobalizePath("user://"), loads the Profile, reads the authored upgrade
tables into a SkillCatalogue, and owns the ProgressionService. Every
mutating operation is wrapped so draining and republishing cannot be
forgotten - the one risk of the DrainEvents design, now confined to one
file.
ProgressionEventRepublisher turns domain records into EventBus signals
(ADR-0004), so existing subscribers and scene wiring keep working. New
RunEnded signal: GameOverScreen reads Lives directly today, which is the
last-life soft-lock.
Registered after SkillManager, since the skill catalogue is built from
AvailableSkills. GameStateStore stays until slice 10 moves the callers.
Transitional: LevelStarted is republished with a catalogue index because
GhostManager names files ghost_level_{index}.json.
This commit is contained in:
@@ -154,6 +154,16 @@ public partial class EventBus : Node
|
||||
[Signal] public delegate void CoinsChangedEventHandler(int totalCoins);
|
||||
[Signal] public delegate void LivesChangedEventHandler(int lives);
|
||||
|
||||
/// <summary>
|
||||
/// The Playthrough has no lives left. Raised as part of the same operation that spends the last
|
||||
/// life, so a subscriber can never observe lives that have not been decremented yet — which is
|
||||
/// the race that lets the death screen sit there forever on the last life.
|
||||
/// </summary>
|
||||
[Signal] public delegate void RunEndedEventHandler();
|
||||
|
||||
public static void EmitRunEnded()
|
||||
=> Instance?.EmitSignal(SignalName.RunEnded);
|
||||
|
||||
public static void EmitCoinsChanged(int totalCoins)
|
||||
=> Instance?.EmitSignal(SignalName.CoinsChanged, totalCoins);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user