Loading…
a327ex.com

062026 12

Opus 4.8

Summary

Session 12 of 062026 (the working-title, build-heavy action roguelite on the snkrx-template / Anchor 2 stack). Focus: design and build the Magician (the Mage base archetype). Landed the full kit design (locked with the owner), the Primary (Arcane Blast), and — after heavy feel-iteration — the Mobility (Blink) complete with mechanic, visuals, and sound. Also captured an Archer-rework spec for a future session. The Secondary (Magic Missile) and Ultimate (Elemental Storm) are deferred to the next session. Sealed as NDA log "062026 12".

Research + design context (read before designing more mages):

  • Pulled the SNKRX Magician from source: SNKRX/player.lua:41-55 — its base attack places a small instant AoE at a RANDOM nearby enemy (Player:attack(), player.lua:1917), 96px sensor, radius 32, every 2s; main.lua:595 describes it as "creates a small area that deals AoE damage." Class = mage (main.lua:459); mage stats (main.lua:955) = the glass cannon (hp 0.6, dmg 1.4, area_dmg 1.25, area_size 1.2, def 0.75). L3 effect = "Quick Cast" (+50% attack speed every 12s for 6s, main.lua:776). Vestigial magician_invulnerable + blue_transparent draw (player.lua:44,1432,1523) = a cut blink-invuln — canon grounding for the Blink mobility. Key contrast: the Wizard is the projectile mage; the Magician is the placed-area mage.
  • Read the concurrent session-13 class-system log (vault nda-project-14.md, "062026 13") at the owner's direction. It firmed the Mage direction (:708): "elemental spellbook — different elements do different things; precision + debuff/status, not raw AoE. Multi-carrier." The Mage/Nuker split is gated on the Magician's direction (Mage = precision/element/status, Nuker = raw-AoE-boom). Arcanist (Sorcerer root) owns projectiles + the migrating Echo. This overrode my first-message proposal (single-carrier areas) → the Magician is a multi-carrier elemental toolbox.

Magician kit — LOCKED with the owner (abilities-first, gems later):

  • Passive · Overload — a League-of-Legends-style stacking proc (Vayne Silver Bolts / Kai'Sa Plasma / Electrocute): hits apply Arcane Charge; at 3 stacks the enemy Overloads for a small AoE bonus-damage burst. Owner picked: decaying per-enemy stacks (creates the few-vs-many focus-fire decision) + an AoE burst that chips 1 stack onto neighbors. NOT built this session.
  • Primary · Arcane Blast — a placed instant circular AoE at the cursor. BUILT.
  • Secondary · Magic Missile — several homing projectiles, each a small circular AoE on hit. Owner's call. NOT built (next session).
  • Mobility · Blink — teleport→curved enemy-weaving dash + shockwave + i-frames. BUILT + heavily polished.
  • Ultimate · Elemental Storm — a huge roaming AoE that seeks the densest pack and ticks; base is elementless/statusless (classes color it later). Owner flagged it'll likely need redesign for feel. NOT built (next session).
  • Base decision that emerged: the whole base Magician is elementless/statusless arcane; element + status are a class-tree layer. This also keeps the Mage OUT of "raw AoE boom," leaving the Nuker lane open (resolving session-13's gated question).

Primary · Arcane Blast (built):

  • New third playable character. swap_character ('c'/Tab/mouse4-5) became a 3-way cycle swordsman→archer→magician (main.lua). magician_spec = the SNKRX-update Magician blue gradient (snkrx_blue→light_blue linear_gradient, dither bayer2_4, scale 0.5, param 0.25, param2 0.5243), baked byte-identical, F5-registered.
  • player:arcane_blast (mirrors player:cleave): reads main_camera.mouse, spawn_area{shape='circle', radius=ARCANE_BLAST_RADIUS, damage, caster=self, spec, shake=2}, cadence ARCANE_BLAST_CD/self.attack_speed. Dispatch = a new elseif self.character == 'magician' branch in player:update_abilities; a magician row in player:ability_damage (MAGICIAN_DMG × ARCANE_BLAST_COEFF). MAGICIAN tunables block in main.lua; F1 knob blast cd. HUD gatherer hud_slots_magician (primary-only for now); a magician.blast hover card. Free-aim anywhere on screen (owner's call), not range-clamped.
  • Explained attack_speed: it's a stats.lua modifier stat that DIVIDES the primary's cooldown; only the two primaries (Cleave, Piercing Arrow) use it; only Surge buffs it. Arcane Blast follows the convention.
  • Sound: reused SNKRX-update's Magician cast sounds.magic_impact (RPG3_Magic_Impact02 @ 0.4), copied the ogg over.

Mobility · Blink (built — many iteration passes):

  • v1: instant teleport to cursor (clamp inside walls), soft radial shockwave push at the destination (leap_land's query+e:push loop, BLINK_PUSH/BLINK_PUSH_RADIUS), single cooldown, and a post-arrival invulnerability window — added a generic self.invulnerable/invuln_end flag + a player:hit early-return guard (the vestigial SNKRX magician_invulnerable made real). Owner wanted an accelerating i-frame flicker (body strobes, speeding up as it ends) — implemented via the Leap-X-telegraph idiom (shrinking period math.floor(elapsed/period)%2).
  • Redesign → curved enemy-weaving dash: owner wanted the mage to move (faster than a Blade Dance hop, ~a teleport) along a path that curves around enemies, leaving a surge-like trail. Built player:blink_build_path (repulsion-weave: sample A→B, displace each interior sample away from nearby enemies by summed falloff repulsion clamped to BLINK_AVOID_MAX, 2 smoothing passes, clamp in-arena) + start_blink/update_blink/blink_land state machine (mirrors leap/tumble). BLINK_DUR ≈ 0.05→0.08. It became a committed movement state in player:update's branch.
  • Juice pass 1: cone-style particles moved to fire backwards from the origin (launch kick-off); line particles seeded along the curve (low-wobble beam_particles offset to the sides, aimed along the local tangent, delayed to appear as the mage sweeps past); white→blue hit circle + radial burst at arrival; a directional shake_push in the arrival heading (BLINK_SHAKE). Randomized the line particles' perpendicular offset / interval / duration.
  • Removed the invuln flicker visual (owner: "the blinking looks off") but KEPT the invulnerability itself.
  • Trail merge (key architectural fix): the dash-curve trail and the post-landing walk trail were two separate lists that disconnected. Merged into ONE blink_trail: the dash curve is stamped by traversal time (t = launch + path_fraction·BLINK_DUR, so the B-end = landing time), and post-landing walk points append to the same list with real t (always ≥ landing → monotonic). Result: one continuous polyline that drains oldest→newest (A→B→walk) in a single sequence. Dropped invuln_trail + BLINK_TRAIL_STEP.
  • White flash: the merged trail is now drawn as raw per-segment lines — white while age < BLINK_FLASH_DUR, then flat blue, with the age-based alpha fade (no spec bracket; gradient collapses on 2px lines anyway). The player body flashes white while moving during the dash/i-frames (self.blink_flashing = blinking or (invulnerable and moving)flash_spec). Particles' white phase = change_color(BLINK_FLASH_DUR/particle_duration) via a blink_flash_frac helper. New knob BLINK_FLASH_DUR (tuned to 0.1125); F1 blink flash.
  • Cone-particle white bug + a misunderstanding: owner said "cone shot particles should also flash white." I first mis-read it as the Archer's Cone Shot and bumped its change_color 0.5→0.75 — then reverted per the owner ("I meant the Magician Cone-Shot-like particles on Blink"). Fixed the Blink backward cone streaks instead: they now stay white for 0.75 of their travel (a fixed fraction, not BLINK_FLASH_DUR) because the fixed-duration white was too brief for long fast streaks — they'd already turned blue by the time they flew out to be visible. Root-cause writeup: beam particles default to the near-white text (fx.lua:214), draw raw on a passthrough effects_layer (no effect leak — verified), so the white IS drawn; it's just when — the origin-bunched phase, washed by the spark-star.
  • Sounds: cast (in start_blink) layers subtle_whoosh + blink_cast (RPG3_PlasmaMagicBall_Cast01) + blink_cast2 (RPG3_LightMagic_BeamImpact02); arrival (in blink_land) plays blink_land (RPG3_PlasmaMagicBlast2_Impact01). All q10 oggs sourced from RPG Magic Pack 3 [Elemental] via the copy→ffmpeg→delete-wav pipeline; loaded before volumes_apply_overrides(), F3-tunable. (ffmpeg tripped on the bracketed MSYS path → copy-into-assets-first workaround.)
  • F1 knobs added across the passes: blink avoid (BLINK_AVOID_RADIUS=50), blink time (BLINK_DUR=0.08), blink shake (BLINK_SHAKE=10), blink cd, blink flash.

Archer rework — spec captured for a future session (062026/reference/archer-rework.md, owner request):

  • Cone Shot → Arrow Rain: a circular AoE DoT (RoR2-style falling arrows, persistent area DoT mode) where the Archer also jumps up like Leap Slam while casting — brief invuln (reuse the now-generic Blink invuln) + dash-like movement in the OPPOSITE direction.
  • Nova Tumble → cone tumble: swap the radial nova for a cone of projectiles fired opposite the dash (roll_r + π).
  • Barrage → Blade-Dance-style shooting dance: the Archer bezier-dances the arena (dash lines, Blade Dance machinery) but at each stop fires multiple piercing + ricocheting projectiles → generalized chaos in a walled arena (ricochet needs building — crib wall-reflection from parked/homing.lua).

Workflow / process notes:

  • Heavy use of the design-brief-before-code rule for the non-trivial pieces (kit, Blink, the trail merge, the flash system); the pure value-tweak / imperative passes were done directly.
  • All if self.character == '<class>' character-branched (owner's chosen architecture); tunables are main.lua globals for the F1 tuner. Syntax-checked every edit with lua54.exe -e "loadfile(...)".
  • NEXT SESSION: Magician Secondary · Magic Missile + Ultimate · Elemental Storm (both brief-first). Then possibly the Overload passive, the Archer rework (its own session), or the stat/gem systems.

🔒 Only the summary of this log is public. Private because this is 062026.