Skip to content

Feat/av visualizer - #1791

Draft
DAVVVVVVVVVVVID wants to merge 23 commits into
fribbels:mainfrom
DAVVVVVVVVVVVID:feat/av-visualizer
Draft

Feat/av visualizer#1791
DAVVVVVVVVVVVID wants to merge 23 commits into
fribbels:mainfrom
DAVVVVVVVVVVVID:feat/av-visualizer

Conversation

@DAVVVVVVVVVVVID

Copy link
Copy Markdown
Contributor

Pull Request

Description

This is an experimental/draft PR. It hasn't been discussed with the team yet — opening it as a draft so
people can check out the branch and try the feature, to gauge interest before deciding whether to keep
developing it. Not requesting a merge at this stage; will follow up in the #dev Discord channel.

Adds a new AV Visualizer tab for visualizing the relationship between speed and Action Value (AV), to help
plan turn order for up to 4 characters.

Added:

  • New tab: select up to 4 characters, see their action markers placed on an AV timeline (AV = 10000 / speed)
  • Simulation engine (simulateTimeline.ts) for speed up/down and advance/delay "interventions", with two timing
    modes — during a character's action, and right after it ends — each bound to a specific action index, plus
    gauge-conservation math for mid-cycle speed changes and same-AV ordering
  • Intervention list panel: per-action grouped list + add/edit form, with click-to-snap AV selection and a hover
    preview on the timeline ruler
  • Memory of Chaos mode toggle (first row becomes 150 AV instead of 100)
  • i18n support (avVisualizerTab namespace, zh_CN + en_US)
  • Dev doc (docs/dev/av-visualizer.md) and user guide (docs/guides/en/av-visualizer.md)
  • Unit tests for the simulation engine and store

Fixed:

  • Restored an accidentally-dropped --no-webstorage test execArgv flag in vite.config.ts (unrelated
    pre-existing regression found while testing this PR; was breaking saveState.test.ts)

Related Issue

  • None — this is an exploratory feature, not tied to a filed issue. Opening for community feedback before
    deciding whether to pursue it further.

Checklist

  • I have added commit messages that are descriptive and meaningful.
  • I have tested the changes locally.
  • I have reviewed the code changes.

Screenshots

048e5fe258f7dd3704d3472663c5dbaa

04472ed9b8edf25bda50fc79012c0159

-d512-4b47-ba6a-7f03cc8af6eb" />

fribbels and others added 23 commits June 14, 2026 00:00
* feat: add per-filter clear button to FilterPill dropdown

Each FilterPill dropdown now shows a Clear button at the bottom of the
options list. The button is disabled when no options are selected, and
clears only that specific filter when clicked without affecting other
active filters or closing the dropdown.

* feat: replace filter button with clear

* feat: replace custom tabler x with mantine X

---------

Co-authored-by: Fribbels <fribbelsgithub@gmail.com>
- Timeline rendering with action markers, multi-action badges, and
  click-to-snap AV selection with hover preview
- Intervention engine (simulateTimeline) supporting before/after
  timing bound to specific character action indices, spd buffs with
  gauge conservation, and av_advance/av_delay with same-AV tiebreaking
- Intervention list panel with structured per-action grouping
  (during/after zones) and a two-column list+form layout
- Memory of Chaos mode: optional 150 AV first row via toggle
- 41 unit tests covering the simulation engine

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New avVisualizerTab i18n namespace (zh_CN + en_US) registered in
  src/lib/i18n/i18n.ts, with resources.d.ts regenerated via
  npm run update-resources
- Replace all hardcoded strings in AvVisualizerTab, Timeline,
  ActionMarker, InterventionMarker, InterventionListPanel, and
  CharacterSlotCard with useTranslation() calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Translate all inline/block comments across the tabAvVisualizer module
(types, engine, store, controller, timeline components, intervention
panel) to English. No behavior changes; vitest (62/62 in this module)
and oxlint both pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the dev-time scratch docs (docs/av_dev/: TASK-*.md breakdowns,
phase1/phase2 plans, and the original pre-implementation design doc)
with a single docs/dev/av-visualizer.md describing the feature as
actually shipped: file layout, simulation engine semantics (timing
model, gauge conservation, same-AV ordering), Memory of Chaos mode,
intervention panel UI, persistence, and i18n — matching the style of
the other docs/dev/*.md files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New docs/guides/en/av-visualizer.md covering the tab's overview,
layout, and a 3-step usage walkthrough (importing/selecting
characters, manually adding interventions, and simulating same-AV
multi-action / self-advance effects), matching the style of the
existing relics-tab.md / warp-planner.md guides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This flag was accidentally dropped (unrelated to AV visualizer work),
which let Node's experimental built-in localStorage partially
activate without --localstorage-file, leaving globalThis.localStorage
undefined and breaking saveState.test.ts (4 failures). Restoring it
fixes all 4; full suite is 924/924 passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Redesign the intervention editing workflow from a click-to-open modal
into a persistent, video-editor-like layout:

- Added: a Playhead that lives on the timeline at all times — click,
  drag (with magnetic snap to nearby character markers), or left/right
  arrow keys (snaps to whole AV ticks) move it
- Added: ActionDisplayPanel, a always-on panel that shows the action
  order + during-action / end-of-action-instant intervention lists for
  whatever AV the Playhead is on, replacing the left half of the old
  modal
- Added: EditPanel, an always-mounted add/edit form driven by a lifted
  EditRequest, replacing the right half of the old modal; shows a
  centered hint when idle
- Removed: InterventionListPanel modal and MarkerClickContext (clicking
  a marker/ruler now just seeks the Playhead, nothing else)
- UI: active add-zone buttons and the intervention being edited are now
  highlighted (filled blue / blue border) so it's clear what the
  EditPanel corresponds to; both panels use Mantine ScrollArea with a
  fixed height (matching the 2x2 character slot grid) instead of
  growing with content; layout width matches OptimizerTab's
- Fix: dragging the Playhead no longer triggers the browser's native
  drag-to-select (img draggable=false, preventDefault + user-select:
  none on the ruler)
- Fix: switching the Playhead now clears any in-flight add/edit
  request, since it's bound to whatever AV was active when created
- Persistence: interventions, rowCount, and mocFirstRow now live in
  AVVisualizerTabSavedSession and persist across reloads like the
  character slots already did (playheadAv intentionally stays
  session-only); persistenceService.ts falls back to defaults for
  saves written before these fields existed
- i18n: added AvLabel key for the two "AV" header labels that were
  previously hardcoded

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add SP/战技点 system: TeamBattleState, sp_gain/sp_loss/sp_cap_up/sp_cap_down
  intervention types, SpCapChange tracking, simulateBattle.ts with full SP logic
- Add SpBar component (segmented horizontal bar) shown above the context panel
- Add battle configs registry (Sparkle, Seele, RuanMei, JingYuan, Huohuo) with
  energy_gain, sp_gain/loss, av_advance, stat_buff, spd_up, spCapBonus templates
- Add intervention panel components: ActionConfigPanel, AddBranchPanel,
  CharacterStatePanel, InterventionEditPanel, UltCasterPanel, UltEffectsPanel
- Overhaul AvVisualizerTab layout: right column is now flex-column with SpBar +
  context panel; playhead-based SP state read from simEvents
- Replace EditPanel with InterventionEditPanel; remove EditPanel.tsx
- Extend types.ts: InterventionTemplate discriminated union, CharacterBattleConfig,
  BattleEntity, BattleEvent, UltInsertion, ActiveIntervention, CharacterBattleState,
  TeamBattleState, TargetType, TurnKind, ActionChoice, ActionNodeOverride
- Add simulateBattle.ts and simulateBattle.test.ts (10 SP tracking tests)
- Update i18n: avVisualizerTab.yaml with new keys; regenerate resources.d.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docs/av_dev/: existing AV visualizer dev notes
- docs/sparkle_dev/dev_plan.md: 5-step plan for Sparkle B1 config refinement
  (data-first ordering: optimizer review → boundary analysis → traces → eidolons → full impl)
- docs/sparkle_dev/step1.md: deep dive into optimizer's eidolon/trace implementation;
  AbilityEidolon pattern, trace stat data flow, dynamicConditionals, borrowable patterns
- docs/sparkle_dev/step2.md: AV Config system reference + optimizer-to-AV mapping table;
  identifies 7 errors in current Sparkle.ts and 2 missing system capabilities
  (battleStart field, factory function + eidolon param)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ergy bar UI overhaul

Engine:
- AbilityResolver: abilities can be a function computed from live caster state
  (energy/buffs), not just static templates — needed for branching kits like
  Saber's skill.
- passiveTrigger (array, function-effect support) and extraAttack: continuously
  re-checked conditions independent of any specific action, for turn-less
  one-off bursts (Gilgamesh's extra attack) and self-syncing buffs.
- GlobalListener: effect can be an array or a function of the listener context
  (incl. the new hitCount field), condition/effect both widened for Gilgamesh's
  hit-count-driven reactions.
- clear_buff template type, including its spdBuffs cleanup; buffStacks template
  condition; energy_set_minimum; everyNOccurrences on listeners.
- actionLock: per-character UI choice lock (e.g. Gilgamesh forced to Basic vs
  Skill depending on Interest stacks).
- Fixed: initial energy now keyed off ultThreshold (not maxEnergy) for
  overflow-style energy caps; SimulationResult.initialActiveInterventions for
  onBattleStart buffs to show up before any action runs.

Characters:
- Saber.ts: Reactor Core energy conversion, Mana Burst self-pull, Crown of the
  Stars, eidolons.
- Gilgamesh.ts: Interest/Interest-Piqued action lock, Hero's Solitude,
  extraAttack shared with Saber's hit count, eidolons.
- TrailblazerRemembrance.ts split out, Huohuo/JingYuan eidolon fixes.

UI:
- EnergyBar/EnergyDisplay/characterEnergyBars: shared energy-bar component with
  per-character custom variants (Saber's segmented overflow bar, Huohuo's
  Rangming turn pips).
- ActionMarker: Ult/extraAttack get their own half-size icon + a circular-
  segment overlay badge when they land on the same AV as their own caster's
  action, using dedicated FUA/ULT artwork.
- ActionConfigPanel/ActionDisplayPanel: dynamic-ability effect preview,
  basicVariants/actionLock-aware choice locking, UltCasterPanel prior-ult state
  fix when stacking insertions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… energy panel drill-down

- Extract shared ActionMarker icon/overlay rendering into SpecialActionIcon.tsx
- Action-order preview strip now includes Ult/extraAttack as their own slots
  (avatar + overlay badge), never merged with the character's normal-action slot
- Ult/extraAttack cards in the action display panel: border now uses the
  character's own element color, icon now uses the custom Ult/FUA artwork, and
  extraAttack cards drop the add/delete affordances it has no use for
- CharacterBattleConfig.actionLock now actually drives the engine's resolved
  action choice (previously UI-only, so a locked Skill silently still resolved
  as Basic and never cleared its own buffs)
- Energy overview panel avatars are clickable to drill into that character's
  live state, with a back button and auto-revert on Playhead movement
- CharacterStatePanel's buff list is now its own scroll region, grouped into
  turn-based vs stack-based buffs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… panel fixes

- Intervention/UltInsertion gain afterItemId for exact insertion ordering
  relative to a specific other item sharing an anchor (not just the old
  coarse "all interventions before any Ult" default), shared via a new
  chainOrder.ts helper used by both the engine and ActionDisplayPanel
- runPassiveTriggers now also runs right before a normal action's/Ult's own
  snapshot, so a clear_buff inside that same action can't outrun the
  passive-synced buff tied to it (previously visible as a stale value in
  the panel for one checkpoint)
- Fix the Ult-card "+" buttons added during the ordering rework dropping
  afterUltId, which silently broke the UltCasterPanel stale-state guard
- Add Wave support (混沌回忆换面): savedSession now holds an array of Waves,
  each with its own rows/interventions/overrides/Ult insertions; cutting the
  current wave at the Playhead truncates it, records where via cutoffAv
  (shown on the timeline as a fixed marker + greyed-out overlay), and seeds
  a new wave with carried-over energy/buffs/team SP (simulateBattle skips
  onBattleStart when seeded). Old flat-shape saves migrate automatically.
- GlobalActionsPanel: wave indicator/switcher, cut/remove-last-wave actions
  gated to only make sense from the latest wave

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ber Reactor Core

- simulateBattle now records a per-item state snapshot (chainSnapshots) for
  every chained Ult AND Intervention, not just Ults — a plain Intervention
  never produced its own BattleEvent, so the "+" right after one had nothing
  to look up and silently fell back to this AV's very first state instead of
  "after everything chained before it"
- Fix ActionDisplayPanel's add-button active-highlight key colliding between
  the leading and trailing "+" in the same before/after chain (both fell back
  to the same coarse per-action key whenever the clicked button had no
  preceding chain item to reference)
- Saber's enhanced Basic now grants its base-kit +2 Reactor Core unconditionally
  (previously gated entirely behind E1, and only +1 there)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s with no ultThreshold/ultEnergyCost set

Mirrors simulateBattle.ts's own processUlt cost resolution (customMaxEnergy
-> real max_sp -> ultThreshold -> ultEnergyCost) instead of stopping at
ultEnergyCost ?? ultThreshold ?? 0 — a character like Trailblazer-Remembrance,
which sets neither, still has a real energy cost (their actual max_sp), so
the refund was silently computing to 0 instead of 30% of that.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…low maxEnergy

EnergyState's maxEnergy (the hard cap, e.g. Saber's 480/560 overflow mechanic)
was also doubling as the "100%" reference for percent-based effects like
Huohuo's Ult ("restore 20% energy"), inflating the restored amount for any
overflow-style character. Added a separate percentBasis (ultThreshold ??
maxEnergy, same baseline the starting-energy calc already uses) for the
percent math specifically; maxEnergy still governs the actual clamp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… the hit counter

- onBattleStart now also grants +1 stack of the shared 本王允许你进攻 hit
  counter (previously only granted Interest), matching its real kit
- Add GilgameshEnergyBar (mirrors HuohuoEnergyBar's slot-row pattern): 8
  fixed slots below the energy bar, lit per held stack of that same counter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… config fixes

UI & Layout:
- New landing page (ShowcaseTab) with background image, slogan system, scramble text, easter egg glitch effect
- Header: custom avatar, updated title, #home routing
- Sidebar: zh-only optimization/tools groups, donate entry replacing Ko-fi
- Language selector: zh_CN + en_US only, default Chinese
- Import tab: simplified to IceDynamix Reliquary Archiver only
- Donate tab: WeChat QR + intro text
- Favicon and page title updated

Battle configs:
- Saber E6: globalListener now only counts Saber's own ults (not any ally) toward everyNOccurrences:3 marker
- Saber E6: ult always clears E6_ENERGY_MARKER after firing (was missing clear_buff)
- Gilgamesh extraAttack: removed Saber's +5 ERR-scaled energy grant

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants