WIP: in-flight combat/expedition/flavor changes

Bundle of uncommitted working-tree edits across combat engine, expedition
cycle, flavor pools, and TwinBee/zone narration. Includes new files:
combat_debug.go, dnd_boss_consumables.go, dnd_dex_floor.go, plus
CHANGES_24H.md and REBALANCE_NOTES.md scratch notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-12 21:59:19 -07:00
parent 2b86f3df16
commit 4e412219f3
49 changed files with 1381 additions and 444 deletions

View File

@@ -398,14 +398,17 @@ func complimentResponseLine(runID string, roomIdx int) string {
return "🎭 **TwinBee:** " + line
}
// moodAsidePool returns the mood-banded aside pool when the mood sits at
// an extreme band (hostile or effusive), else nil. Mid-bands (grumpy /
// neutral / friendly) intentionally surface no aside — flavor stays
// strictly extra, never replacing the core narration.
// moodAsidePool returns the mood-banded aside pool. Every band except
// strict Neutral (4059) surfaces flavor — Hostile/Effusive at the
// extremes, Grumpy/Friendly in the mid-bands. Neutral stays silent.
func moodAsidePool(mood int) []string {
switch moodBand(mood) {
case MoodBandHostile:
return flavor.MoodAsidesHostile
case MoodBandGrumpy:
return flavor.MoodAsidesGrumpy
case MoodBandFriendly:
return flavor.MoodAsidesFriendly
case MoodBandEffusive:
return flavor.MoodAsidesEffusive
}
@@ -519,6 +522,33 @@ func clampMood(s int) int {
return s
}
// DMMoodCombatTilt — what the DM's mood does to combat dials.
//
// Effusive: monsters miss more, hit softer; player goes first more often.
// Hostile : monsters meaner, faster off the line.
// Mid-bands: small or zero effects so the DM's voice still matters
// without trivializing math at each step.
type DMMoodCombatTilt struct {
EnemyAttackDelta int // added to monster.Stats.Attack pre-fight
InitiativeBias float64 // added to player initiative roll each round
LootQualityMod float64 // multiplied into AdvBonusSummary.LootQuality
}
// dmMoodCombatTilt maps the run's DM mood score to the combat dials.
func dmMoodCombatTilt(mood int) DMMoodCombatTilt {
switch moodBand(mood) {
case MoodBandEffusive:
return DMMoodCombatTilt{EnemyAttackDelta: -1, InitiativeBias: +5, LootQualityMod: 1.20}
case MoodBandFriendly:
return DMMoodCombatTilt{EnemyAttackDelta: 0, InitiativeBias: +2, LootQualityMod: 1.10}
case MoodBandGrumpy:
return DMMoodCombatTilt{EnemyAttackDelta: +1, InitiativeBias: -2, LootQualityMod: 0.90}
case MoodBandHostile:
return DMMoodCombatTilt{EnemyAttackDelta: +2, InitiativeBias: -5, LootQualityMod: 0.75}
}
return DMMoodCombatTilt{LootQualityMod: 1.0} // Neutral
}
// applyMoodDecayIfStale persists a passive-decay correction when the
// run has been idle long enough to drift. Cheap no-op on fresh runs.
func applyMoodDecayIfStale(r *DungeonRun) error {