Field banter ships: heroes speak during fights — solo on cast, pair on same-target combo, trio on three in a row
2026-06-05
Server-authoritative selection. Banter is picked on the API side inside resolveCastSpells, not in the client. The cascade tries an element chain first (when element chains exist for the cast), then a same-target pair (two heroes' casts landing on the same enemy consecutively), then a same-target trio (three in a row), and falls back to a solo line. A three-per-turn cap keeps any single turn from feeling like a sitcom.
Six-fight dedup. The selector tracks recently-used exchanges per pool over a rolling six-fight window. A line you just heard in the last fight won't replay in the next one, even if it's eligible — so combat doesn't repeat itself across short sessions. The window survives replay (the recentBanter state is part of the player), so save-scumming a fight doesn't reroll the dedup.
Authored content for all five Chapter 1 heroes. Solo, pair, and trio pools have lines for every reachable party combination; per-fight slots are intentionally empty for now, and the element-chain pool is split out into a separate future feature. Every line is tagged with one of twelve emotions, which the frontend renders as a kaomoji face on the speaker's portrait — same hero, different face per line.
Frontend overlay and tests. A FightBanterOverlay component plays the turn's selected barks after action playback resolves, with the emotion → face map driving the speaker's expression. Twenty-two unit tests cover the selection logic. A hero-voices reference doc lands alongside, so future banter writing has a per-hero voice guide instead of getting reinvented every time.