Skip to content

Warden rebuild (design)

Warden rebuild: Nova look, player-grade attack FX, smarter Survival AI

Section titled “Warden rebuild: Nova look, player-grade attack FX, smarter Survival AI”

Date: 2026-10-01. Approved by Chris in conversation (“yes lets plan and do all of that”), Survival-only AI with the new look + FX everywhere (tutorial included).

Telemetry (D1 runs.timeline_json.bosses, builds 208-235):

Group Fights Warden killed Warden landed the killing blow
Survival, human (211-230) 7 2 0 (5 died to swarmers/shooters while it lived)
Survival, autopilot (209-235) 56 45 8 (~14%)

Small human sample, but it agrees with the code. The Warden is not under-damaged (swing 56, missile 18, contact 34) — it rarely threatens:

  1. Fixed attack order (swing → barrage → missiles → spiral → swarm → summon), learnable in one cycle.
  2. Range-blind: it swings (its biggest hit) even when the pilot is far outside the 240 px reach.
  3. Nothing aimed: barrage + spiral are fixed radial patterns (36-shot ring ≈ 70 px gaps at 400 px).
  4. Stationary ~1.5-2.9 s of every ~3-4.4 s cycle; speed 88 vs pilot 260 → trivially kited.
  5. Enrage = faster cadence + 3 spiral arms; nothing new. Barrage wind-up (2.0 s) never shortens.
  6. Any drone soaks its missiles.
  7. Visually the dullest thing on screen: calm boss shots are tinted Color.WHITE, missiles and telegraphs are draw_circle/draw_arc primitives, the body is a painterly Recraft sprite that clashes with the Nova units.
  • The Warden reads as a Nova-look unit, the most imposing one on screen.
  • Every Warden attack has an effect on par with the player’s Weapon FX v2 looks, in a hostile colour language that can never be mistaken for player fire.
  • Survival Warden is scarier: it adapts to range, aims, moves while attacking, has a real phase 2. Still fair: every attack keeps a readable telegraph.
  • We can measure whether it worked (per-attack damage telemetry).

Non-goals: damage-number increases (hit rate is the problem, not hit size); tutorial/story AI changes; other bosses; the bestiary/codex art (beyond the stale stats noted below).

  • New radial design warden in tools/nova_units/nova_unit_designs.py, “jailer” theme: a central eye (iris + pupil plate), an inner ring of 8 locking plates, an outer ring of 6 heavy blades — the same negative-space plate construction / facet shading as the other units. Baked at 512 px (boss scale; swarm units export at 128) to render/enemy_sprites/nova/warden_{body,glow}.png plus separate ring layers warden_ring_inner_{body,glow}.png and warden_ring_outer_{body,glow}.png.
  • The core (eye + hub) is a Nova bucket in ArchetypeRenderer (row in _NOVA_UNITS, gated by VisualLook.nova like every unit). ArchetypeRenderer never rotates, so the two ring layers are drawn by a new render/warden_body_renderer.gd (child of main, z just above the swarm) as rotating sprites centred on the boss.
  • The rings carry state (the telegraph language):
    • idle: slow counter-rotation (inner +, outer −);
    • telegraph swing: outer ring spins up and its blades flare outward (scale 1.0 → 1.15);
    • telegraph barrage/fan: inner plates part (radial offset), eye brightens;
    • enraged: tint crimson (existing BOSS_COLOR rule), spin ×1.6, the eye pupil narrows.
  • Classic look (VisualLook.nova == false) keeps the old sprite bucket untouched.
  • A/B: VisualLook.warden_v2 (default true) switches body + FX back to the old renderer; Debug Settings row “Warden Look (A/B)” + Remote Console parity, per the toggle-competing-techniques rule.

B. Attack FX — on the Weapon FX v2 system

Section titled “B. Attack FX — on the Weapon FX v2 system”

All new looks are WeaponFxLayer subclasses (one draw call each, saved _mat.tres, prewarm family, MultiMeshCulling.disable), living in fx/boss/ so they don’t collide with the in-flight player-FX branches. Palette: void crimson body #ff2e57 → white-hot core, with a violet rim — distinct from every player element accent. Enraged: hotter (more white, faster turbulence).

Attack Current New look
Barrage / spiral / fan shots (enemy_proj from TYPE_BOSS) white dots in the shared enemy-proj MultiMesh warden_bolt: elongated crimson plasma bolt along velocity, white core, short tail. Drawn in place of the dot for boss-sourced projectiles (their dot gets alpha 0 in _enemy_proj_colors while warden_v2 is on).
Homing missiles (sim.boss_missiles) two draw_circles + a line warden_missile: arrow-head body + flickering exhaust plume + fading trail
Missile impact / launch ring primitive in FxManager warden_burst: shader shock-ring + sparks (shared by launch/impact/summon)
Swing telegraph + slash draw_arc + jagged lines warden_swing: shader danger ring that fills as the wind-up completes, then a crescent shear sweeping the full circle on hit
Barrage wind-up + eruption draw_circle vibration + rings warden_charge: converging energy ring + noise corona while charging; eruption = plasma ring burst (Plasma Nova technique, hostile palette)
Swarm drones (is_homing == 2) overbright magenta dot warden_drone: tiny dart with comet trail
Aimed fan / lunge telegraphs (new) — warden_lane: a thin flickering lane wedge showing the fan arc / lunge path for its telegraph time

C. Survival behaviour (gated BossWarden.survival(sim))

Section titled “C. Survival behaviour (gated BossWarden.survival(sim))”

Tutorial/story Warden keeps its current 4-attack loop exactly.

  1. Range-aware attack deck. Replace attack_idx = (idx+1) % n with a weighted pick by distance band (close < 300, mid 300-600, far > 600), drawn from sim.rng (deterministic; Warden spawns at 90 s, after every 600-tick baseline). Same attack never twice in a row; summon at most once per 3 attacks and only when < SUMMON_MAX_ADDS alive. Weights are tunables.
    • close: swing 4, slam-double (enraged only) 3, fan 2, barrage 1
    • mid: fan 4, spiral 3, barrage 2, missiles 2, swarm 1
    • far: lunge 4, missiles 3, swarm 3, summon 1
  2. Aimed fan (new attack ATTACK_FAN). 3 volleys of 7 bolts in a 50° cone aimed at the pilot’s predicted position (pos + vel * t_flight, clamped lead), 0.18 s apart; enraged: 5 volleys. Telegraph shows the cone (warden_lane).
  3. Barrage closes its gaps. Two rings, the second offset by half a step and fired 0.12 s later.
  4. Lunge (new attack ATTACK_LUNGE). Telegraphed charge along a lane aimed at the predicted position; contact damage on the path; ends with a short radial burst. Replaces the “dash only at the start of an approach”.
  5. Moves while attacking. During telegraph of ranged attacks it strafes (orbit at 0.6× speed, direction flips each attack); during rest it repositions to its preferred band for the next pick. Base Survival speed 88 → 120 (tunable).
  6. Phase 2 (enraged). Barrage telegraph shortens by the cadence multiplier too; swing becomes a double swing (second ring 0.45 s later, catches a dash back in); missiles fire WITH a spiral (paired attack); drone swarm count already rises.
  7. No missile soak. Survival missiles home on the pilot only; drones no longer absorb them (decoy aggro rules untouched).

Fairness guard: every attack has a visible telegraph ≥ 0.45 s (enraged) and every aimed pattern leaves a dodge path (fan cone ≤ 50°, double-swing gap 0.45 s).

  • Tag each Warden hit with its attack ("boss:swing", "boss:fan", …) and accumulate a per-boss dmg map + hits count into the run timeline’s boss entry ([type, spawn_t, kill_t, {attack: dmg}]). death_cause keeps "boss" for compatibility. Same data class as existing run summaries — confirm the privacy page wording still covers it; no new table.
  • data/bestiary.json Warden stats are stale (hp 1500/speed 40) — sync to the live values + new attacks.
  • tools/vfx_library/library_manifest.gd: new entries (with scores) for each new look; Warden body.
  • docs/architecture/enemies-bosses-survival.md: the new attack deck + phase 2.
  • RELEASE-1.0.1 entry.
  • Sim (GUT, TDD): deck picks by band, no-repeat, summon cap, fan aim leads a moving pilot, barrage double ring, lunge path damage, strafe during telegraph, enraged double swing + paired attack, survival missiles ignore drones, tutorial Warden unchanged (attack order + counts pinned), telemetry dmg map.
  • Render: shader compile under mobile + gl_compatibility (windowed), prewarm family covered, test_baked_shader_materials, VFX library manifest, a capture of the new body + each attack for Chris to eyeball, A/B toggle verified.
  • scripts/gate.sh green; determinism baselines unchanged.