Combat Combos

The key words MUST, MUST NOT, SHOULD, and MAY are used as in RFC 2119.

Melee attacks chain in a 3-hit combo (per-weapon combo_steps). Chaining is governed by two-tier timing (#461) measured as a fraction of the current swing's animation — not a wall-clock timer. A single boundary, just_start, splits the swing: a press before it fumbles, a press at or after it queues the next step, which fires when the current swing completes. This preserves action commitment (#377 — a swing always fully executes, see Player State Machine).

There is no just-attack tier. An earlier draft (#155/PR #459) added a third, "just-attack" window granting a damage bonus for precise timing; Rozalin's #459 playtest found this both inaccurate to PSZ and counterintuitive (#461). Crit and damage bonuses come from character stats and equipment, not combo timing. Players use the accept window to decide when to advance the combo (reposition / stagger), not to farm a per-hit bonus.

The two tiers

  frame 0                    animation end
  |------------|-------------|
   miss-early    chain-accept   too-late
   (fumble)      (queue chain)  (swing ended un-queued →
                 |              combo broken, back to IDLE)
              just_start
  
TierWindow (fraction of swing)On attack press (MUST)
miss-early[0, just_start)Fumble — the press is NOT buffered, does not advance the combo, and locks out chaining for the remainder of this swing: every later press in the same swing MUST be ignored, so the swing ends un-queued and the combo breaks. Muted-red flash on the fumbling press.
chain-accept[just_start, 1.0]Queue the next step at standard damage (green flash; yellow for a special/strong chain). No timing-based damage bonus.
too-lateafter animation endUnreachable as a press — the swing ending un-queued has already broken the combo and returned to IDLE.

PSO:BB reference frames

The boundary is runtime-computed from the animation fraction — PSO:BB's motion files carry no timing events (see psobb-re, combo-timing investigation). Motion frame counts from plymotion-profile.tsv inform per-weapon tuning (e.g. Saber A1 = 19 frames → earlier accept; finishers A3 = 59–80 frames → no window). The in-repo starting values are feel-tuning defaults, expected to move via playtest.

Feedback

Queue-time flash by outcome (green = normal chain, yellow = special chain, muted red = fumbled press, red = chain broken), drawn by the combo ring and gated on the Combo Timing debug toggle exactly as before. The PSO:BB chain sounds (SE_PL_CHAIN1/2/HIT) are not in the pack yet — audio cues land as a follow-up with the next pack republish.

Combo-timing debug overlay

The Combo Timing debug toggle (DebugConfig.show_combo_timing, default OFF, toggled from the field start menu) draws the at-feet timing ring, visualizing the chain-accept window: visible in green from just_start to animation end, shrinking toward the swing's end. When the toggle is OFF it MUST hide every timing ring — both the combo ring (_combo_ring) and the element-tinted heavy/special-attack charge ring (_charge_ring); #415 fixed the charge ring leak. The heavy attack's rising particles and model glow are permanent attack VFX, not timing rings, and are unaffected by the toggle.

Implemented by

Status: implemented (#461)test_combo_two_tier pins the accept boundary, queue semantics, and finisher; test_combo_miss_early_fumble pins the fumble lockout; test_mechgun_final_step_no_root pins the safety net; the PSZ_AUTOPILOT_COMBO=1 probe drives a live fumble + normal-chain end-to-end.

These attacks are the ATTACKING state of the Player State Machine.

← Mechanics