adventure: T6 Amendment (Custodian) + in-combat round-end boss seam (P8)

First in-combat Layer-2 mechanic. applyBossInCombatRoundEnd is a new
round-boundary seam called from the turn engine's stepRoundEnd, the
counterpart to the pre-combat applyBossRunModifiers. The Custodian snapshots
its HP at end of round 3 and rewinds to it once on the phase-2 crossing
(refunding front-loaded burst); a soft midnight timer past round 20 climbs
its Attack via the existing enemyAtkBuff. New state (EnemyRewindHP/Used)
round-trips through CombatStatuses so a suspend/resume can't replay the
rewind. Sim A/B (n=120 L20 party): last_meridian fighter 65->37.5% clear,
a clean -27.5pp swing attributable to the mechanic; shipped as-is per the
opt-in-endgame difficulty call.

Claude-Session: https://claude.ai/code/session_0156WqjgsbmSY2U8eQ3Kkb1s
This commit is contained in:
prosolis
2026-07-16 09:20:29 -07:00
parent db13ed75b9
commit 189a44e1eb
6 changed files with 323 additions and 12 deletions

View File

@@ -333,6 +333,10 @@ func renderEvent(e CombatEvent, playerName, enemyName string, result CombatResul
return pickRand(narrativeSurvive)
case "phylactery_rebirth":
return pickRand(narrativePhylacteryRebirth)
case "amendment_rewind":
return pickRand(narrativeAmendmentRewind)
case "midnight_toll":
return fmt.Sprintf(pickRand(narrativeMidnightToll), e.Damage)
case "stat_drain":
return fmt.Sprintf(pickRand(narrativeStatDrain), e.Damage)
case "debuff":
@@ -772,6 +776,22 @@ var narrativePhylacteryRebirth = []string{
"💀 That should have been the end of him. A Verse still hums somewhere in the cathedral, and Valdris simply *begins again*.",
}
// narrativeAmendmentRewind fires when the Custodian rewinds itself to its round-3
// HP snapshot — the once-only Amendment. Each line reads as time being undone so
// the mechanic (front-loaded burst is partly refunded) teaches itself over a run.
var narrativeAmendmentRewind = []string{
"🕰️ The Custodian raises a hand and *edits the last few minutes out of the record.* Wounds close in reverse; the clock-golem stands as it did rounds ago.",
"🕰️ \"That entry is amended.\" The damage you dealt simply un-happens — the Custodian rewinds to where it was and resumes, unhurried.",
"🕰️ Verdigris rings spin backward. Time you spent hurting it is refunded to the golem; it returns to its round-three self and keeps working.",
}
// narrativeMidnightToll fires past round 20 — the soft closing-time timer, the
// Custodian's Attack climbing each round a stalled fight refuses to end.
var narrativeMidnightToll = []string{
"🔔 A bell tolls somewhere above. Closing time — the Custodian's swings come harder. (+%d attack)",
"🔔 The hour is nearly spent, and so is its patience; each blow lands with more weight now. (+%d attack)",
}
var narrativeStatDrain = []string{
"🩸 The enemy saps your strength — your swings feel heavier, weaker. (-%d hit damage)",
"🩸 Something drains out of your limbs. Your hits won't bite as deep now. (-%d damage)",