Mob Encounters And Scene Combat
What This System Is
Mob encounters connect authored scene geometry, mob catalog definitions, server lifecycle memory, authoritative combat state, and loot resolution. Scene files say where and when mobs can appear. Mob catalogs say what a spawned mob is. The game server owns live actors, combat damage, defeat memory, respawn eligibility, and drop rolls.
How Authors Use It
Scene encounter authoring is split between [mob_spawn_areas], [mob_spawners], and optional [triggers] records.
SceneMobSpawnArea is scene-local geometry. Its id is referenced by spawners, and its bounds, layer, shape, enabled flag, tags, optional region id, population cap, and activation conditions describe where an encounter can place actors.
SceneMobSpawner is the controller. It has a scene-local id, references spawn_area_id, and owns activation mode, lifecycle policy, memory scope, spawn counts, spawn safety, concurrent population cap, cooldown, despawn rule, conditions, and spawn table.
Activation modes are shared-domain values: area_population, trigger_burst, scheduled, and manual. Lifecycle policies are cooldown, dungeon_run, calendar, and manual. Memory scopes are realm, zone, dungeon_run, party, account, character, and none.
Spawn safety is stored as JSON policy: require scene bounds, require walkable tiles, reject transition tiles, avoid occupied tiles, maximum attempts, and leash radius. assets/scenes/scene_1.scene shows the common pattern: one area, one trigger-burst spawner, and one spawn_encounter trigger per starter mob.
Tags, region ids, and activation conditions are authored and validated metadata. The server encounter projection currently carries activation mode, lifecycle, memory scope, population policy, spawn safety, and spawn table data. Projection also skips disabled spawners, empty spawn tables, and spawners without matching areas.
Rules And Invariants
Spawn Tables And Trigger Spawns
Each spawn-table entry names a mob catalog mob_id, a relative weight, and pack_min/pack_max. Runtime projection converts those into EncounterSpawnTableEntry values, ignores entries that cannot participate in weighted selection, and the server chooses entries deterministically from spawner id plus spawn sequence.
Trigger-driven spawns use SceneTriggerAction::SpawnEncounter, serialized as kind="spawn_encounter" with spawner_id and optional count_override. The server accepts explicit spawns only for manual and trigger_burst encounter projections, then still checks lifecycle eligibility and population cap before spawning.
The trigger path is authority-owned: local trigger effects request a server-authoritative spawn command, and EncounterRuntimeRegistry::spawn_explicit_scene_mobs performs the final projection, eligibility, and actor creation.
Area-population and scheduled spawners are evaluated by refresh and tick paths instead of explicit trigger commands.
Mob Catalog Contract
The mob catalog entry id is the stable catalog reference used by scene spawn tables and runtime actor snapshots. The encounter payload includes:
- spawn conditions and actions
- stats: health, attack power, defense
- attacks: id, kind, damage kind, damage, range, cooldown, action key
- aggro and leash tuning
- resistances by damage kind
- rewards: experience and gold
- loot table id, loot rolls, and inline or hydrated drops
- death cleanup tags and hooks
- reset behavior
- AI graph states and transitions
MobDefinition::combat_projection converts this catalog data into the shared mob combat projection that scene combat stores on each spawned actor.
Server Runtime Ownership
EncounterRuntimeRegistry owns one EncounterRuntime per hosted zone plus isolated runtimes per dungeon run. Each runtime indexes projected spawners by spawner id and delegates cooldown, calendar, dungeon-run, and persisted defeat facts to the encounter lifecycle service.
AuthoritativeSceneCombatState owns live actor state for the hosted zone or session-visible copy. It indexes actors by id, live mob actors by spawner id, and live actors by tile. Scene mob actor ids are stable strings in the form scene_mob:<spawner_id>:<sequence>.
Hostile NPCs share the scene-combat state, but only mobs are governed by encounter memory.
Lifecycle And Memory
On refresh, the server rebuilds desired scene-combat state from zone data and catalogs, then filters mob actors through encounter eligibility. Defeated actors are preserved when their authored spawner still exists.
On defeat, scene combat records the encounter defeat through EncounterRuntime::record_defeat_snapshot. A memory scope of none keeps the defeat local and writes no durable record. Other scopes build memory keys from realm, zone, dungeon run, party, account, or character context.
Respawn ticks query encounter eligibility for mobs and local defeated timers for NPCs. When a mob becomes eligible, the server clears its defeated state, returns it to its spawn tile, emits a respawn event, and keeps lifecycle events tied to zone_id:spawner_id.
Loot Resolution
Server catalog loading hydrates encounter.loot_table_id from game-data loot tables. Hydration copies drops into the mob encounter projection and copies the table roll count into loot_rolls.
When a mob is defeated, scene combat resolves drops from a deterministic seed built from actor id and request id. Guaranteed drops roll first. Weighted drops roll loot_rolls.max(1) times, use positive weights, apply chance_percent, and roll a count inside min_count..=max_count. Outcomes for the same item id are combined, and a loot-roll audit is emitted with roll kind, seed, pool weight, chance roll, count range, and final count.
Validation And Debugging
Scene validation checks spawn-area ids, bounds, layers, spawner-to-area references, population caps, spawn-count ranges, spawn-table ids, weights, pack ranges, lifecycle/memory compatibility, and suspicious area pressure. It also validates spawn-table mob ids against the current mob catalog when catalog data is available.
Mob catalog validation checks mob ids, combat fields, AI graph references, loot table ids, item drop ids, weights, counts, and chance percentages. Cross-catalog validation also checks gameplay action intents such as SpawnEncounter against known scene spawner ids when that context is supplied.
The game server repeats critical loot hydration checks during catalog load. Missing loot tables or missing drop items are reported as catalog health issues before scene combat treats the catalog as healthy.
Before runtime testing, run cargo run --bin aether-bake -- --fail-on-diagnostics, then verify hosted-zone scene-combat catalog health if mobs fail to spawn or loot does not resolve.
Examples
assets/scenes/scene_1.scene shows the common encounter pattern: a spawn area, a trigger-burst spawner that references that area, a mob catalog id in the spawn table, and a spawn_encounter trigger action that names the spawner. After changing this shape, run bake diagnostics and then test the scene online because live actor state, lifecycle memory, and loot are server-owned.