mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 00:32:40 +00:00
Tedium-removal pass driven by live play feedback. Three big threads: Expedition autopilot Phase 4 — background auto-run + harvest-until-dry: - New expeditionAutoRunTicker walks active expeditions every 15min (5min tick, per-expedition CAS on new last_autorun_at column). Skips combat sessions, briefing/recap quiet windows, expeditions <30min old. - Walks up to 3 rooms/tick with compact narration; suppresses DMs when 0 rooms walked or just hitting the per-tick cap (no "stretch complete" filler). Player only hears from the bot when a real decision is needed. - Compact mode: one-line combat narration for trash/elite, auto-resolves elite doorways via the forward-sim engine (boss still pauses). Threaded via new advanceOnceWithOpts → resolveRoom → resolveCombatRoom. - Auto-harvest now grinds each Common/Uncommon node until dry (cap at 8 attempts/visit), mirroring manual !scavenge retries. Rare+ still pauses. - Ambient ticker: anti-repeat by Kind via new last_ambient_kind column (avoids two pack_rat DMs in a row when the pool only has 6 lines). - !expedition go <n> now routes to the fork-choice handler when active + numeric; fork footer rewritten to suggest !expedition go instead of !zone go. Boss/Elite doorway: formatNextRoomMessage routes the action hint by next room type and autopilot loop breaks via new nextRoomType field so "Room X/Y — Boss" doesn't double-print with contradictory hints (!zone advance vs !fight). - runAutopilotWalk extracted from expeditionCmdRun so foreground and background share the loop body. Rogue Sneak Attack actually exists now: - Audit found the rogue's "Sneak Attack" passive was AutoCritFirst + 5% damage rider. No Nd6, ever. Phase 2 Monte Carlo masked this with a small flat buff; the class's defining mechanic never matched its tooltip or 5e identity. - Added SneakAttackDie int to CombatModifiers, per-hit Nd6 in combat_primitives.go (same lane as DivineStrikePerHit). Scales with level: 1d6 at L1-2 ... 4d6 at L7-8 ... capped at 10d6 at L19-20. - AutoCritFirst + 5% rider retained as bonuses on top of working sneak attack — preserves the opener-burst feel. - L7 rogue expected per-hit ~8 → ~22 damage. Valdris fight math goes from "16 rounds to kill, die in 8" to winnable. TwinBee voice sweep (Phase B3): - ~530 line changes across 24 files replacing third-person "TwinBee notes/files/tracks/respects/..." constructions with first-person inside flavor string literals. Code identifiers (TwinBeeLine, twinBeeLine, etc.), chat-prefix labels (🎭 **TwinBee:**), item names (TwinBee's Bell), achievements, and game-title references in fun.go (Konami TwinBee ship) left intact. - Catches a real bug: Valdris fight rendered "TwinBee marks the Legendary Resistance" mid-combat in third person, contradicting the Phase B2 convention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
8.1 KiB
Go
87 lines
8.1 KiB
Go
// DO NOT REWRITE, SUMMARIZE, OR SHORTEN ANY ENTRIES IN THIS FILE
|
||
// zone_crypt_valdris_flavor.go
|
||
// Tier 1 zone flavor — The Crypt of Valdris. Additive only. Pools sampled
|
||
// by internal/plugin via deterministic per-run, per-room hashing.
|
||
//
|
||
// Voice rules (from gogobee_dungeon_zones.md §3.3):
|
||
// • Third person for description; second person for outcomes.
|
||
// • Boss callouts get a beat of cinema. Don't overrun.
|
||
// • TwinBee references the right era — NES, SNES, arcade. Not modern.
|
||
|
||
package flavor
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// ELITE ROOM ENTRY — Crypt of Valdris (Wight / Flameskull)
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
var EliteRoomEntryCrypt = []string{
|
||
"The room is colder than the last one. Not by feeling — by measurement. I can tell. There is a presence here that does not believe in the ambient temperature of stone.",
|
||
"A figure sits in the cathedra at the chamber's far end. Robes intact. Skin not. The eyes open as you enter and they were already looking at the door. I draw breath despite not strictly needing to.",
|
||
"Floating above the altar: a skull, lit from within in a color that pretends to be fire. I recognize the pretense. The skull is doing math. The math is about where you are.",
|
||
"The torches in this room are out, but the room is lit anyway. I identify this as a problem worth naming aloud: 'That light has a source. The source is the encounter.'",
|
||
"You step into a chapel. Pews. Altar. A figure rising from the front pew with the unhurried grace of something that has been waiting in this exact pew for a very long time. I respect the patience and refuse to be impressed by it.",
|
||
"The mosaics on the walls show a procession. The procession leads to a king. The king is here. I note that the mosaics are still being added to in real time — one tile per visitor — and you have not been added yet.",
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// BOSS ABILITY CALLOUTS — Valdris the Unburied
|
||
// Used as a one-line cinematic suffix to BossEntryValdris when combat starts.
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
// Corrupting Touch: +4d6 necrotic; target max HP reduced by damage dealt.
|
||
var ValdrisCorruptingTouchLines = []string{
|
||
"His hand passes through your chestplate without touching it. The damage isn't to the plate. I watch your max HP tick down and quietly stops watching.",
|
||
"Necrotic damage lands and lingers. The wound doesn't bleed — it forgets how. Your HP ceiling drops with it. I note: long rest restores. Survive to long rest.",
|
||
"Where Valdris touches, the body takes a piece of permanent. Not permanent-permanent. Long-rest-permanent. I consider this distinction the only good news in the sentence.",
|
||
}
|
||
|
||
// Legendary Resistance: 2/combat; auto-succeed one failed save.
|
||
var ValdrisLegendaryResistanceLines = []string{
|
||
"Your save would have landed. Valdris decides otherwise. The roll resets to a success on his side of the table. I note one charge spent, one remaining.",
|
||
"The spell hits cleanly and Valdris ignores it on principle. I mark the Legendary Resistance and remind you: he has two of these. After two, the math changes.",
|
||
"You rolled the number. The number was correct. Valdris waves it away with a gesture that costs him something but not enough. I keep count. Keep rolling.",
|
||
}
|
||
|
||
// Call of the Grave: recharge 5–6; summons 1d4 skeletons.
|
||
var ValdrisCallOfTheGraveLines = []string{
|
||
"Valdris speaks a word that is not for the living. Bones in the chamber walls remember they were once attached to people. I count the new combatants and recommend crowd control.",
|
||
"From the alcoves: the dry rattle of skeletons reassembling on demand. I note 1d4 new bodies on the field and quietly hopes for the lower end of that range.",
|
||
"The skeletons stand up like a Castlevania stage hazard — same animation, same timing, same exact bad news. I have memories of this and they are not warm ones.",
|
||
}
|
||
|
||
// Phase 2 (<50% HP): gains Fly speed; spells deal +1d6 necrotic.
|
||
var ValdrisPhaseTwoLines = []string{
|
||
"Valdris drops to half HP and stops walking. Not because he's tired — because he doesn't need to anymore. He rises a foot off the floor and I file this under 'phase shift.'",
|
||
"The fight changes shape. Valdris hangs in the air now, robes still, very calm, very lethal. His spells gain a necrotic edge. I say, simply: 'Phase two. Adjust.'",
|
||
"Half-HP is the line. You crossed it and Valdris crossed something else — gravity, mostly. The boss music gets a third instrument. I brace.",
|
||
"Like Castlevania's Death revealing his real attack pattern at half HP — the fight you started is not the fight you're finishing. I respect the pivot and dislike it intensely.",
|
||
}
|
||
|
||
// ValdrisSignatureCallouts — combined pool the boss-entry composer samples
|
||
// from at the start of the boss fight. Phase-two lines are surfaced via
|
||
// the dedicated phase-two helper rather than the entry suffix.
|
||
var ValdrisSignatureCallouts = func() []string {
|
||
out := make([]string, 0,
|
||
len(ValdrisCorruptingTouchLines)+
|
||
len(ValdrisLegendaryResistanceLines)+
|
||
len(ValdrisCallOfTheGraveLines))
|
||
out = append(out, ValdrisCorruptingTouchLines...)
|
||
out = append(out, ValdrisLegendaryResistanceLines...)
|
||
out = append(out, ValdrisCallOfTheGraveLines...)
|
||
return out
|
||
}()
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// LORE — Crypt of Valdris
|
||
// Sampled by !lore inside this zone (zone-specific pool, generic fallback).
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
var LoreLinesCrypt = []string{
|
||
"Valdris was a scholar. Then he was an aspirant. Then he was a failed aspirant. The failure is the part that mattered — the lich ritual completed but completed wrong, and the wrongness has had three centuries to compound. I have read the contemporaneous accounts and find the original scholar likable, which makes the rest harder.",
|
||
"The phylactery shard you'll find here is one of seven. The other six are not in this crypt. I will not say where they are, because it doesn't fully know, and the partial knowledge it has is the kind that gets people followed by things that prefer not to be looked for.",
|
||
"The candles in the crypt do not consume wax. They do not consume time, either, in the strict sense. They were lit on the day Valdris was interred and they have been lit ever since. I respect this kind of consistency in a way that does not extend to approval.",
|
||
"The skeletons here are not all enemies. Some of them are former students, posed in the alcoves where they died, marked with the texts they were translating. I suggest you don't disturb the marked ones unless you mean to. Some lessons end and some lessons keep going.",
|
||
"The iron gate at the entrance has been opened from the inside three times in the last decade, and from the outside zero times. I find the asymmetry instructive. It also finds the pattern instructive: you are walking into the open door, not opening it.",
|
||
"In life, Valdris was patient. In undeath, Valdris is also patient — which is unfair, mathematically, because the same trait scales differently across mortality conditions. I dislike the math but respect the consistency.",
|
||
}
|