Encounter Instance And Wave Director
What This System Is
The Encounter Director turns an authored named encounter into a durable server-authoritative instance. It owns the active wave, exact objective actor set, defeated actor set, inter-wave delay, completion event, reward handoff, and retry health. Scene combat still owns actors and damage; the World Event Director still owns scenario phases.
Encounter state lives inside persisted authoritative gameplay state. Reconnects therefore retain the current wave and objective progress. Starts and wave dispatches use stable ids, and completion rewards enter the existing transactional combat-reward outbox exactly once.
How Authors Use It
Define waves and rewards in assets/gameplay/enemy_content_catalog.json. Every runtime wave needs exactly one manual or trigger-burst scene spawner tagged with both:
encounter:<encounter id>wave:<zero-based wave index>
The World Event spawn_encounter action names the wave-zero spawner. Later waves are located by their tags. Each spawner continues to supply area bounds, walkability and occupancy safety, population caps, lifecycle policy, and actor-id ownership.
The first supported objective is defeat_all. Its target is not inferred from an authored count after spawning: authority records the exact actor ids actually produced. Only authoritative EncounterLifecycle::Defeated events for those actors advance the objective.
Runtime Flow
- A scenario action creates an idempotent encounter instance and persists its first wave dispatch.
- The director loop claims due dispatches under a persisted lease.
- The existing explicit scene-spawn path materializes the tagged wave and returns lifecycle events.
- The director persists the spawned actor set and replicates the objective projection.
- Defeat events update progress. Clearing a wave schedules the next wave after its authored delay.
- Clearing the final wave records the configured runtime event and hands the named encounter reward to the combat outbox.
Spawn failures retry with exponential backoff. After five attempts, the dispatch and encounter become terminally failed. Pending and failed counts plus the last error are replicated to clients and projected into the Event Console.
Replicated UI Model
The gameplay-condition snapshot includes encounter id, instance id, status, current wave and wave count, wave state, defeat-all progress, next-wave time, dispatch health, and last error. PlayerGameplayUiState converts active/failed projections into HUD-ready encounter rows. The projection remains server-owned; UI code never predicts wave completion.
Validation And Debugging
Validate that every wave has exactly one tagged spawner, that spawned actor ids become the objective set, and that completion events and rewards are emitted only once. Dispatch health and terminal failures should be visible in the Event Console before reading server logs.
Examples
The Slime Infestation road defense now has a three-slime opening wave followed by two reinforcements after 1.25 seconds. Its core encounter starts with two guards and erupts into a four-slime final mass after one second. The scenario advances only after the final wave in each encounter is defeated.
Rules And Invariants
- Encounter instance and wave dispatch ids are stable and idempotent.
- A wave cannot become active without a non-empty authoritative actor set.
- Only actors in the current objective set count toward completion.
- A later wave is never dispatched before the previous defeat-all objective completes and its delay expires.
- Scenario completion and encounter bonus rewards occur only on the final wave.
- Reward claims are marked in the same speculative combat state that stages the transactional reward snapshot.