diff --git a/Docs/Vault/06_Roadmap/Roadmap_Lantern_Slice.md b/Docs/Vault/06_Roadmap/Roadmap_Lantern_Slice.md index e424c7452..f1331dd1f 100644 --- a/Docs/Vault/06_Roadmap/Roadmap_Lantern_Slice.md +++ b/Docs/Vault/06_Roadmap/Roadmap_Lantern_Slice.md @@ -54,6 +54,13 @@ The primary verb first. No world, no lanterns — a gym. **Gate:** the gym is fun with two players for 15 minutes on kit alone; relevancy-light verified server-side (gamma test: nothing to see). +> **Phase 1 status (2026-07-15):** ✅ Group A (4-socket kit, [[2026-07-14_Lantern_Phase1_GroupA_Combat_Sockets]]) · +> ✅ Group B **systems + content + gym CODE** — the 5 Sparks (decoy / hook-reel / vortex / blink / light-zone), +> Aoe/Hitscan dispatch, `ReelSystem` / `ZonePulseSystem` / decoy aggro, 3 effect ghosts + 5 Spark defs, on-demand +> enemy-spawn tooling + `GymTag` clean-spawn (497 EditMode green). ◻ the fresh **`Gym.unity` scene assembly** + the +> **L3 feel gate** (operator's eyes; also closes the A1 in-game animated-pipeline confirmation) remain. See +> [[2026-07-15_Lantern_Phase1_GroupB_5Sparks_Systems]]. + ## Phase 2 — The dark & the pocket-graph 1. **Twilight shelf as a pocket-graph:** 3–5 generated dark pockets per descent on a graph; seed-fresh re-knot per descent; pocket transitions. diff --git a/Docs/Vault/07_Sessions/2026/2026-07-15_Lantern_Phase1_GroupB_5Sparks_Systems.md b/Docs/Vault/07_Sessions/2026/2026-07-15_Lantern_Phase1_GroupB_5Sparks_Systems.md new file mode 100644 index 000000000..89f7a1a90 --- /dev/null +++ b/Docs/Vault/07_Sessions/2026/2026-07-15_Lantern_Phase1_GroupB_5Sparks_Systems.md @@ -0,0 +1,88 @@ +--- +date: 2026-07-15 +type: session +tags: [session, lantern, phase-1, combat, sparks, netcode, gym, implementation] +permalink: gamevault/07-sessions/2026/2026-07-15-lantern-phase1-groupb-5sparks-systems +--- + +# Session 2026-07-15 — LANTERN Phase 1 Group B: the 5-Spark systems + gym tooling (code done; scene pending) + +> Continues [[Phase1_Combat_Gym_Build_Spec]] (adopted [[DR-050_Lantern_Phase1_Combat_Design]]) — the "remaining +> Group B" from [[2026-07-14_Lantern_Phase1_GroupA_Combat_Sockets]]. Operator chose the **full 5-Spark feel** +> (steps 3+4) and, folding in the roadmap's **Enemy-test GYM** direction, a **dedicated fresh `Gym.unity`**. All +> the systems + content + gym CODE landed and are verified headless (L1 clean, **497/497 EditMode green**). The +> physical gym SCENE assembly + the L3 feel gate remain — the operator-editor part. + +## Done (L1 clean throughout; L2 497/497, +3 new) + +**Part A — Spark systems (Build Spec §5/§6/§9/§10, step 3 + step-4 new-code):** +- **Blob + flags:** `AbilityDefBlob += byte EffectFlags` (bit = Reel) `+ int DurationTicks`; mirrored on + `AbilityDefinition` SO + the baker; `ProjectileEffectFlag.Reel = 2`. +- **Aoe/Hitscan dispatch** in `AbilityFireSystem` — replaced the `archetype != Projectile → continue` fall-through + with an **Aoe** branch (both-worlds cooldown advance; `ecb.Instantiate` **only inside `if (isServer)`** — the + client-never-instantiates invariant; picks `ZoneEffect` vs `DecoyTag` by PREFAB membership; seeds runtime + radius/damage/lifetime from `EffectiveSocketStats` + `adef.DurationTicks`; preserves baked scale via + `bakedLt.WithPosition`) + a minimal **Hitscan** branch (both-worlds cooldown + server-only inline beam damage; + no Phase-1 Spark uses it — present for spec-completeness). HookPull's `EffectFlags` OR'd into `projFlags`. +- **Reel = homing via re-aimed knockback (the RS-6 "new code, not the pull flag"):** `ReelState` (server-only, + baked inert on Husks via `EnemyAuthoring`) + `ReelSystem` (server, `[UpdateAfter(PredictedSimulationSystemGroup)]` + `[UpdateBefore(EnemyAISystem)]`) re-aims each reeled Husk's `KnockbackState` toward the CASTER's LIVE position + every tick — **EnemyAISystem stays the sole Position writer** (it drives the re-aimed knockback; ReelSystem only + writes Dir/Speed/UntilTick). `ProjectileDamageSystem` stamps `ReelState{CasterNetworkId,…}` on a Reel-flag hit + (skips bosses). Releases on proximity(1.6u)/leash(90t)/caster-gone. +- **`ZonePulseSystem`** — mirrors `GeyserEruptSystem` (INVERTED invalid-tick guard, `= now + period` reschedule) + but ENEMY-ONLY (no friendly fire), stamps `DamageEvent.SourceNetworkId = casterId`, NO region gate; Vortex flag + adds a gentle inward pull each tick; `DestroyEntity` on expiry. **L2: 3 tests** (enemy-only + caster-attribution, + born-0 lazy-stamp no-storm, expiry despawn). +- **Decoy aggro** — `DecoyTag` ghost gathered into `EnemyAISystem`'s Grunt target set (preferred within 30u, + overrides player/structure/core; region-agnostic); soaks contact damage; `DecoySystem` despawns on Health≤0 or + lifetime. (Grunt-pass only — Charger/Spitter decoy-aggro a noted scope edge; the gym's Drowner = Strider = Grunt.) + +**Part B — content:** +- 3 interpolated ownerless-ghost prefabs via the duplicate-`ResourceNode` recipe: `EffectVortex` (Vortex flag), + `EffectLightZone`, `DecoyWisp` — authoring swapped to `ZoneAuthoring`/`DecoyAuthoring` (bake `ZoneEffect`/ + `DecoyTag` inert; decoy also Health+DamageEvent, no HitRadius so shots pass through). No colliders (won't block). +- 5 `AbilityDefinition` SOs (dup of `Ability_Primary`): DecoyWisp(Aoe→decoy prefab), HookPull(Projectile+Reel→ + shared `Projectile`), Vortex(Aoe→EffectVortex), Blink(Movement), LightZone(Aoe→EffectLightZone). + +**Part C — gym CODE (scene pending):** +- `GymTag` + `GymEnemyRoster{byte Kind; Entity Prefab}` + `GymRosterAuthoring` (bakes both; Drowner=0/Grindylow=1). +- `DebugOp.SpawnEnemy = 14` + client `DebugCommandSendSystem.SpawnEnemy(kind,count)` + the server receive case + (spawns the roster prefab of Kind ArgA near the sender, RegionTag Base). +- `GoInGameServerSystem` **GymTag branch**: `GymTag` present ⇒ bypass the meta-catalog spawn guard (a fresh gym + has no CycleDirector) + seed the default Spark loadout `[HookPull, Blink, DecoyWisp, Vortex]` on keys 1–4 + (LightZone off-bar). Class seeds still apply (harmless — AbilityFireSystem reads sockets). + +## Wire/bake churn +Blob re-bake (config); Husk/Drowner re-bake (server-only `ReelState`, no ghost-hash change); **3 additive +interpolated-ghost prefabs**. **No new `[GhostField]` / no command-hash change** (player ghost + command collection +untouched — the SpawnEnemy op reuses the existing scalar `DebugCommandRequest` wire type). + +## Reusable gotchas (candidates for CLAUDE.md / archive) +- **Reel/vortex = re-aim `KnockbackState` from a sibling system, don't add a Position-writer.** A server system in + the plain group `[UpdateBefore(EnemyAISystem)]` writing only `KnockbackState.Dir/Speed/UntilTick` (one tick, + re-stamped) gets homing/pull for free through the existing knockback mover — EnemyAISystem stays sole + Position-writer. Clean way to add forced-movement without fighting the mover. +- **A fresh (CycleDirector-less) subscene bypasses `GoInGameServerSystem`'s meta-catalog spawn guard via a baked + `GymTag`** — else the born-correct-meta guard blocks player spawn forever. +- **`manage_scriptable_object modify` needs `target` as an OBJECT** `{guid|path}` (a bare string errors); enum + + ObjectReference patches work (`{"path":"Field","value":{"guid":"…"}}`). + +## Open / next +- **C1 — the fresh `Gym.unity` + `Subscenes/Gym.unity`** (operator chose fresh-minimal-clean over duplicate). Needs + the singleton set or systems silently stall: ground + Environment collider · `PlayerSpawnerAuthoring` (Player + prefab + spawn point) · `AbilityDatabaseAuthoring` (all abilities incl. the 5 Sparks + characters) · + `NetCodePhysicsConfig` · `WorldCollisionConfig` · `GymRosterAuthoring` (GymTag + Drowner/Grindylow refs). Host + `Gym.unity` = SubScene GameObject + camera/light; add to Build Settings; editor-instant boot (open + Play). + **Fiddly + not fully verifiable headless — do with Unity focused.** +- **D — L3 feel gate (operator's eyes):** in the gym, spawn Drowner/Grindylow on demand (`DebugCommandSendSystem. + SpawnEnemy` or execute_code) → confirm they **animate in-game** (closes the open A1 pipeline confirmation) → fire + all 4 sockets (no flicker) → reel yanks a Drowner to the caster → zone ticks enemy-only damage → decoy pulls + aggro → dash+blink precedence → **server == client** on the 3 new ghosts. Then the **adversarial post-impl diff + review** (netcode/reuse/determinism) before final sign-off (standing practice; not run yet — heavy Workflow). +- Reel-convergence / decoy-aggro / client-never-instantiate / cross-socket dispatch: structurally sound + self- + reviewed, but their behavioural confirmation is L3 (need the full netcode world), not L2. + +## Related +- [[Phase1_Combat_Gym_Build_Spec]] · [[DR-050_Lantern_Phase1_Combat_Design]] · [[Roadmap_Lantern_Slice]] (A1 gym + note) · [[2026-07-14_Lantern_Phase1_GroupA_Combat_Sockets]] · [[DR-023_Enemy_Animation_MonsterMash]]