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

@@ -54,7 +54,7 @@ var MorningBriefingDay3 = []string{
var MorningBriefingDay7 = []string{
"One week. You have spent one week in this place and it has not finished you, which says something about you that TwinBee intends to say out loud: that took something real. Take a moment with that. Then advance.",
"Seven days. In the old reckoning, seven was the number of completion — seven seals, seven trials, seven nights before the thing reveals itself. TwinBee is not superstitious. TwinBee is also watching the door very carefully this morning.",
"A week underground. TwinBee thinks about the sky sometimes — not with longing, exactly, more as a reference point. You've been below it for seven days. TwinBee finds that remarkable. TwinBee finds you remarkable.",
"A week underground. TwinBee thinks about the sky sometimes — not with longing, exactly, more as a reference point. You've been below it for seven days. Remarkable. You, more so.",
}
var MorningBriefingDay14 = []string{
@@ -97,7 +97,7 @@ var EveningRecapBossKilled = []string{
var EveningRecapCloseCall = []string{
"TwinBee runs the evening recap and notes: you came very close today to not being here for the evening recap. TwinBee notes this without drama and with complete sincerity. You made it. That's the recap.",
"Today was the kind of day that TwinBee files under 'let's not do that again' and also 'and yet you did it.' Rest. You need it more tonight than most nights.",
"Evening recap. TwinBee will note for the ledger that today was very nearly a different kind of recap, and TwinBee is glad it isn't. The margin was thinner than TwinBee likes. TwinBee will adjust tomorrow's caution accordingly.",
"Evening recap. TwinBee will note for the ledger that today was very nearly a different kind of recap, and is glad it isn't. The margin was thinner than the acceptable range. Tomorrow's caution adjusts accordingly.",
"End of day, narrowly. TwinBee runs through the close-call list — the round that nearly went the other way, the save that landed by one, the room you almost didn't leave — and signs each one off as 'survived.' Survived is a wide category. TwinBee accepts you in any part of it.",
}
@@ -137,7 +137,7 @@ var SupplyWarningLow = []string{
}
var SupplyWarningCritical = []string{
"TwinBee holds up the supply manifest. The number is very small. 'This is the part,' TwinBee says quietly, 'where we start making decisions.' TwinBee does not specify which decisions. You know which decisions.",
"TwinBee holds up the supply manifest. The number is very small. 'This is the part,' it says quietly, 'where we start making decisions.' Doesn't specify which. You know which.",
"Critical supply levels. TwinBee delivers this without inflation — the situation is what it is. Extract and resupply, or forage aggressively and push for the finish. TwinBee outlines both paths and neither is comfortable.",
"The supplies are nearly gone. TwinBee thinks of every long JRPG dungeon where you realize at the bottom floor that you're out of Ethers. This is that moment. TwinBee has plans. They require movement.",
}
@@ -174,7 +174,7 @@ var ThreatClockHostile = []string{
}
var ThreatClockSiege = []string{
"Siege Mode. TwinBee delivers this without decoration because decoration would be dishonest. The dungeon is fully active, fully aware, and fully committed to ending this expedition. So is TwinBee — to ending it on your terms, not theirs. What happens next is a race. TwinBee is already running.",
"Siege Mode. TwinBee delivers this without decoration because decoration would be dishonest. The dungeon is fully active, fully aware, and fully committed to ending this expedition. So is TwinBee — to ending it on your terms, not theirs. What happens next is a race. Already running.",
"Siege. The dungeon is putting everything it has into the room you're standing in, and the rooms adjacent to it, and the route between you and the door. TwinBee is putting everything TwinBee has into making sure the dungeon doesn't get what it wants. Meet in the middle.",
"Siege Mode. TwinBee narrates the band shift and then stops narrating because narration is not what this band needs. Action is what this band needs. TwinBee is in motion. The expectation is that you are too.",
}
@@ -209,15 +209,15 @@ var SunkenTempleTidalEvent = []string{
var HauntedManorResetMorning = []string{
"TwinBee's morning briefing includes an addendum. The rooms that were clear yesterday are not entirely clear this morning. The house has been busy overnight. TwinBee adds this to the log under 'things the house does' and suggests adjusting the advance plan.",
"Night three. The manor reset itself. TwinBee was watching and it happened anyway — not violently, not dramatically, just quietly and completely, the way the house does everything. One enemy per room, back in place. TwinBee has updated the map.",
"TwinBee reads the morning's hallway and stops. 'The arrangement has changed,' TwinBee says, in the tone of someone who has now seen this happen often enough to recognize it without alarm. The manor reset. TwinBee adjusts the map. Morning continues.",
"Reset day. The rooms TwinBee cleared are not the rooms TwinBee finds this morning. TwinBee accepts this as a property of the manor — like weather, but indoors and unfair. The plan accommodates. TwinBee bills the time.",
"TwinBee reads the morning's hallway and stops. 'The arrangement has changed,' it says, in the tone of someone who has now seen this happen often enough to recognize it without alarm. The manor reset. Map adjusts. Morning continues.",
"Reset day. The rooms TwinBee cleared are not the rooms it finds this morning. Accepts this as a property of the manor — like weather, but indoors and unfair. The plan accommodates. The time gets billed.",
}
var UnderforgHeapWarning = []string{
"Heat Stack [N]. TwinBee notes the accumulation and what it means: the Underforge is getting into you in ways that don't resolve without real rest. The number has time to come down. TwinBee is watching the number.",
"The heat is building. TwinBee tracks it the way you track a temperature gauge on a long drive — with the specific alertness of someone who knows what happens when the gauge hits red. It has not hit red. TwinBee intends to ensure it doesn't.",
"Heat building. TwinBee notes the count, notes the band, notes how each step now takes a fraction more out of you than the last step did. None of it is critical. All of it is direction. TwinBee suggests the direction be inverted soon.",
"Stack [N]. TwinBee tracks the heat the way TwinBee tracks anything that compounds — patiently, with running totals, with a clear point at which the totals stop being managed and start being problems. We are still on the management side. The other side is visible.",
"Stack [N]. TwinBee tracks the heat the way it tracks anything that compounds — patiently, with running totals, with a clear point at which the totals stop being managed and start being problems. We are still on the management side. The other side is visible.",
}
var UnderforgHeapCritical = []string{
@@ -227,7 +227,7 @@ var UnderforgHeapCritical = []string{
}
var FeywildTimeDistortionHalf = []string{
"The day moved strangely. TwinBee tried to track it and lost the thread somewhere around mid-afternoon — the light didn't change the way it should have, and when TwinBee looked up, the day was half over in the time it usually takes to be a quarter over. On the positive side: you're barely hungry. On the less positive side: TwinBee is not sure what that means.",
"The day moved strangely. TwinBee tried to track it and lost the thread somewhere around mid-afternoon — the light didn't change the way it should have, and when it looked up, the day was half over in the time it usually takes to be a quarter over. On the positive side: you're barely hungry. On the less positive side: nobody is sure what that means.",
"Half a day passed in what felt like half of half. TwinBee checks the supply burn against the sun, finds them disagreeing, sides with the supplies — those don't lie about how much you've used. Net result: a free pocket of time. Use it on something that takes time.",
"The Feywild gave you back some hours. TwinBee notes this without trusting it. The Feywild does not give without taking, eventually. For now: less hungry, less tired, more daylight than the math allows. TwinBee writes it down and keeps moving.",
}
@@ -239,7 +239,7 @@ var FeywildTimeDistortionDouble = []string{
}
var FeywildTimeLoop = []string{
"TwinBee recognizes this room. TwinBee has described this room before. The enemies in it are different — new enemies, the old ones are gone, the loot you found is still gone but the enemies are back — and TwinBee processes this with something between professional acceptance and profound exasperation. 'Again,' TwinBee says. 'We do this room again.'",
"TwinBee recognizes this room. Has described it before. The enemies in it are different — new enemies, the old ones are gone, the loot you found is still gone but the enemies are back — and it processes this with something between professional acceptance and profound exasperation. 'Again,' TwinBee says. 'We do this room again.'",
"The loop. TwinBee marks the room on the map with a small symbol that means 'we have been in this room before in a way that doesn't count.' The symbol has its own column on TwinBee's ledger. The column is occupied.",
"Same room. New enemies. TwinBee runs the encounter again with the cold professionalism of someone who has stopped expecting fairness from the Feywild and started expecting only repetition. The repetition arrives. TwinBee handles it.",
}
@@ -265,14 +265,14 @@ var AbyssPortalDestabilizationMid = []string{
}
var AbyssPortalDestabilizationCritical = []string{
"Instability critical. The portal is unraveling at edges TwinBee can see and probably at edges TwinBee can't. The demons coming through are more agitated than they were — which is relevant because demons at baseline are already at the upper end of agitated. TwinBee says: finish this today. Tomorrow is a different calculation.",
"Instability critical. The portal is unraveling at edges TwinBee can see and probably at edges it can't. The demons coming through are more agitated than they were — which is relevant because demons at baseline are already at the upper end of agitated. The verdict: finish this today. Tomorrow is a different calculation.",
"The portal is louder. Not in sound — in pressure. TwinBee can feel it in the back teeth, in the joint of the jaw. The instability number is the number you don't want it to be. Finish the work today or accept that today was the last day to.",
"Critical. The geometry around the portal is bending in ways that suggest the room does not entirely agree with itself anymore. TwinBee adjusts the route around the worst of it. There are more demons than there should be. There always are. There are more than that now.",
}
var AbyssPortalCollapse = []string{
"The portal collapses. TwinBee watches it happen and does what TwinBee does in situations with no good options: moves. 'Out,' TwinBee says, and means it completely. 'Now. Everything you have, we move now.' The expedition ends here, not in defeat, but in physics. What you took is yours. What's left in there is the portal's problem. Come back when it isn't.",
"It's coming apart. TwinBee says one word, 'Move,' in the tone TwinBee uses exactly once per expedition. You move. The portal screams behind you in a register that isn't sound. The expedition is over because physics says so. TwinBee will sort the loot once you're somewhere physics still works.",
"The portal collapses. TwinBee watches it happen and does what it does in situations with no good options: moves. 'Out,' it says, and means it completely. 'Now. Everything you have, we move now.' The expedition ends here, not in defeat, but in physics. What you took is yours. What's left in there is the portal's problem. Come back when it isn't.",
"It's coming apart. TwinBee says one word, 'Move,' in the tone it uses exactly once per expedition. You move. The portal screams behind you in a register that isn't sound. The expedition is over because physics says so. The loot gets sorted once you're somewhere physics still works.",
"Collapse. TwinBee was prepared for this and is also actively running. 'Out,' TwinBee says. 'Now.' The corridors are folding behind you in the way that things fold when reality is no longer paying attention to what's allowed. You finish out the door. The portal does not.",
}
@@ -331,23 +331,23 @@ var ExpeditionResume = []string{
var MilestoneFirstNight = []string{
"You survived the first night. TwinBee notes this milestone specifically because not everyone does, and those who do carry something from it that changes how the rest of the expedition goes. You have that now. TwinBee has noticed it already.",
"Night one survived. TwinBee makes a small mark in the corner of the manifest — the kind of mark you make for the things that count more than they look. First nights count. TwinBee has been in dungeons where they were the last nights too. This wasn't one of those.",
"Day two morning. The first night is behind you, which means the first watch is behind TwinBee, which means TwinBee can confirm a thing TwinBee was hoping to confirm: you sleep through the noises that matter and wake for the ones that don't. That's a survival skill. TwinBee logs it.",
"Day two morning. The first night is behind you, which means the first watch is behind TwinBee, which means a thing worth confirming has been confirmed: you sleep through the noises that matter and wake for the ones that don't. That's a survival skill. Logged.",
}
var MilestoneWeekOne = []string{
"Seven days. TwinBee pauses the morning briefing for a moment — just a moment — to mark this. One week in an active dungeon zone is not a thing that happens by accident. It happens through every decision you've made since Day 1, compounded. TwinBee has been watching those decisions. TwinBee is glad they were yours.",
"Seven days. TwinBee pauses the morning briefing for a moment — just a moment — to mark this. One week in an active dungeon zone is not a thing that happens by accident. It happens through every decision you've made since Day 1, compounded. Those decisions were watched. They were, gladly, yours.",
"Day eight. TwinBee delivers the briefing slowly, because there's a thing to mark first: you have been in here, intact and operational, for a full week. That is a number with weight. TwinBee is going to set the briefing down for a moment and let the number have its weight. ... Right. Briefing.",
"One week. TwinBee makes the mark in the column reserved for week-one survivors. The column is shorter than you'd expect. You are now on it. The rest of the day proceeds normally, but for one moment, TwinBee allows itself to be visibly impressed. The moment ends. We continue.",
}
var MilestoneTwoWeeks = []string{
"Two weeks. TwinBee doesn't have a comparison for this one. The references have run out. There's just you, in here, on Day 14, still going, and TwinBee standing next to you having run out of everything except genuine admiration. TwinBee has that in abundance. Proceed.",
"Two weeks. TwinBee doesn't have a comparison for this one. The references have run out. There's just you, in here, on Day 14, still going, and TwinBee standing next to you having run out of everything except genuine admiration. That, in abundance. Proceed.",
"Day fifteen. TwinBee notes that the historical comparisons stopped working at Day fourteen and have not resumed working today. We are off the chart. TwinBee is not a person who values being off the chart, except in the very specific sense that you are off the chart, in which case TwinBee values it deeply.",
"Fortnight. TwinBee uses the older word because it sounds more like what this is — not 'two weeks,' which sounds modular and reasonable, but 'fortnight,' which sounds like the kind of duration that earns a title. TwinBee may be inventing titles for you. TwinBee will be honest about that as it happens.",
}
var MilestoneTheLongGame = []string{
"TwinBee sets aside the narration format for a moment. Just sets it down. Speaks plainly: what you just did was not supposed to be survivable. The designers of this zone — the thing that shaped it, the evil that filled it — did not account for someone like you. TwinBee did. TwinBee always accounts for someone like you. That's why TwinBee is here.",
"TwinBee sets aside the narration format for a moment. Just sets it down. Speaks plainly: what you just did was not supposed to be survivable. The designers of this zone — the thing that shaped it, the evil that filled it — did not account for someone like you. TwinBee did. Always does. That's why it's here.",
"Tier five complete. TwinBee allows the narration format to fully break for a moment because the moment fully deserves it. What you just did, complete, in a Tier 5 zone, is a thing that goes on the short list. TwinBee keeps a short list. You're on it.",
"Long game closed. TwinBee gathers the run notes, the threat curve, the supply records, the camp positions — files them all under your name in a folder TwinBee has been keeping. The folder has a title now. The title is good.",
}
@@ -372,6 +372,6 @@ var MilestoneCartographer = []string{
// item-grant hookup; this pool covers the narrative line at the moment it lands.
var MilestoneSurvivalist = []string{
"Survivalist. TwinBee writes the title next to your name in the ledger and underlines it once. No abandonments, no scrambles for the door, no expeditions cut short by anything but the boss going down. TwinBee acknowledges the discipline directly.",
"The Survivalist title is technical — it means the run never broke; it ended on your terms, every time. TwinBee has been in expeditions where that wasn't true and TwinBee remembers them differently. This one TwinBee remembers as: complete. TwinBee files it with the others like it. The folder is short.",
"The Survivalist title is technical — it means the run never broke; it ended on your terms, every time. TwinBee has been in expeditions where that wasn't true and remembers them differently. This one gets remembered as: complete. Filed with the others like it. The folder is short.",
"No forced extractions, full clear, Tier 3-or-better. TwinBee notes each criterion separately because each one is its own choice, made repeatedly, across days. The result is the title, which is real, and the cosmetic, which is forthcoming. TwinBee will hand both over when the system permits.",
}

View File

@@ -63,7 +63,7 @@ var RoomEntryForestShadows = []string{
"The trees here grow too close. Their roots are above ground, like they've been trying to leave and thought better of it. TwinBee thinks better of commenting.",
"A clearing. Moonlight. Flowers that shouldn't be blooming at this hour. TwinBee has played enough Majora's Mask to be deeply suspicious of beautiful clearings.",
"Something watches from the canopy. TwinBee watches back. After a moment, it looks away first. TwinBee counts this as a point.",
"The path forks. Both ways look equally uninviting. TwinBee consults no map, because there is no map, because TwinBee is the map, and TwinBee chooses left. Probably.",
"The path forks. Both ways look equally uninviting. TwinBee consults no map, because there is no map, because TwinBee is the map, and chooses left. Probably.",
"Bioluminescent fungi light the forest floor in soft blue. It is, genuinely, beautiful. It is also exactly what the Lost Woods looked like right before things got bad. TwinBee stays alert.",
"The wind carries voices. Not words, exactly — more like the memory of words. TwinBee has heard this before. It means the forest is old and has opinions.",
"Owlbear tracks in the mud. Fresh. TwinBee measures them. Whatever left these tracks was not small and was moving with purpose. TwinBee hopes the purpose was in the other direction.",
@@ -171,7 +171,7 @@ var CombatRetreat = []string{
// ─────────────────────────────────────────────────────────────────────────────
var Nat20 = []string{
"NATURAL TWENTY. TwinBee stands up. TwinBee does not have legs. TwinBee stands up anyway.",
"NATURAL TWENTY. TwinBee stands up. Does not have legs. Stands up anyway.",
"The dice land perfectly and TwinBee makes a sound that it will not acknowledge making.",
"A critical hit for the ages. TwinBee notes this one down. Not for records. Just because it deserves to be noted.",
"PERFECT. TwinBee says it like it's the Street Fighter announcer saying it after a flawless round and every syllable is justified.",
@@ -235,7 +235,7 @@ var BossEntryHollowKing = []string{
}
var BossEntryInfernax = []string{
"TwinBee stops walking. TwinBee does not stop walking. TwinBee processes what it sees and takes a moment that it has never taken before in the history of narrating dungeons. The dragon is not large the way a large thing is large. It is large the way weather is large — not an object with size, but a condition of the space you're in. One eye opens. Gold, lit from within, older than the mountain it's resting in. It looks at you the way you'd look at a very small thing that had climbed onto your counter. 'So,' Infernax says, and the word moves the air in the room. TwinBee translates: 'What an interesting mistake you've made.' TwinBee wishes you luck and means it more than it has ever meant anything.",
"TwinBee stops walking. Does not stop walking. Processes what it sees and takes a moment never taken before in the history of narrating dungeons. The dragon is not large the way a large thing is large. It is large the way weather is large — not an object with size, but a condition of the space you're in. One eye opens. Gold, lit from within, older than the mountain it's resting in. It looks at you the way you'd look at a very small thing that had climbed onto your counter. 'So,' Infernax says, and the word moves the air in the room. TwinBee translates: 'What an interesting mistake you've made.' Wishes you luck and means it more than it has ever meant anything.",
}
var BossEntryBelaxath = []string{
@@ -397,9 +397,9 @@ var TauntResponses = []string{
"TwinBee has been taunted by things with more teeth than you and survived the experience with its dignity intact. TwinBee will survive this too.",
"The next room will contain a thing that TwinBee has been saving for exactly this kind of energy. TwinBee is pleased you've given it an occasion.",
"Noted. TwinBee's mood shifts. You can hear it shift. TwinBee wants you to hear it shift. The shift is the point.",
"You taunt TwinBee. TwinBee smiles. The smile does not reach the eyes, because TwinBee does not have eyes per se, but the quality of the smile communicates clearly. 'Proceed,' TwinBee says.",
"You taunt TwinBee. It smiles. The smile does not reach the eyes, because TwinBee does not have eyes per se, but the quality of the smile communicates clearly. 'Proceed,' it says.",
"In Gradius, you could powerup into overconfidence and lose everything in one hit. TwinBee mentions this as a purely historical observation.",
"TwinBee accepts the taunt with grace. TwinBee also generates a trap for the next room with specific energy. These two events are unrelated. TwinBee maintains this position legally.",
"TwinBee accepts the taunt with grace. Also generates a trap for the next room with specific energy. These two events are unrelated. TwinBee maintains this position legally.",
}
// ─────────────────────────────────────────────────────────────────────────────
@@ -421,7 +421,7 @@ var ComplimentResponses = []string{
// ─────────────────────────────────────────────────────────────────────────────
var IdleLines = []string{
"TwinBee waits. TwinBee is good at waiting. The dungeon is also waiting, which is arguably more important, but TwinBee acknowledges both.",
"TwinBee waits. Good at waiting. The dungeon is also waiting, which is arguably more important, but TwinBee acknowledges both.",
"The dungeon holds its breath. TwinBee is also holding its breath. There are a lot of things holding breath right now and TwinBee recommends acting before someone has to exhale.",
"TwinBee taps its metaphorical foot. Not impatiently — more in the way of a metronome. The tempo is there whenever you're ready.",
"In Contra, hesitation had consequences. TwinBee mentions this as context, not pressure. Definitely not pressure.",
@@ -499,7 +499,7 @@ var SaveFailed = []string{
var MoodAsidesHostile = []string{
"TwinBee is not narrating this one in detail. You can read the room. Read it.",
"The dungeon offers TwinBee something to mention. TwinBee declines. You're on your own for color commentary.",
"TwinBee is here. TwinBee is watching. TwinBee is not, currently, helping. There is a difference and you will feel it.",
"TwinBee is here. Watching. Not, currently, helping. There is a difference and you will feel it.",
"In the bad ending of every Castlevania, the protagonist gets less guidance than they did at the start. TwinBee has reached approximately that part of the playthrough.",
"TwinBee keeps several details to itself. The details would have been useful. TwinBee does not consider this its problem right now.",
"Whatever's in the next part of the room, TwinBee saw it and chose not to flag it. The mood is what it is.",
@@ -523,3 +523,35 @@ var MoodAsidesEffusive = []string{
"The mood is high. TwinBee is, for the next stretch, more likely to mention the loose flagstone, the suspicious tapestry, the thing on the ceiling. Take advantage.",
"TwinBee hums a victory fanfare softly to itself. It is not earned yet. TwinBee is being optimistic on your behalf.",
}
// ─────────────────────────────────────────────────────────────────────────────
// MOOD ASIDES — Grumpy band (mood 2039)
// TwinBee is unimpressed. Short, dry, slightly clipped. Not actively
// withholding (that's hostile) — just not feeling generous.
// ─────────────────────────────────────────────────────────────────────────────
var MoodAsidesGrumpy = []string{
"TwinBee describes the room. TwinBee does not embellish. Make of that what you will.",
"The mood is fine. TwinBee specifies fine, not good. There's a difference.",
"TwinBee notes the chamber. TwinBee notes its existence. That's the whole note.",
"The dungeon has a thing worth mentioning. TwinBee will mention it if you specifically ask. You will not specifically ask.",
"TwinBee is keeping the commentary lean today. The dungeon does not need editorializing. TwinBee almost convinces itself.",
"There's color here. TwinBee is choosing greyscale.",
"You arrive in a room. TwinBee declines to make it cinematic.",
}
// ─────────────────────────────────────────────────────────────────────────────
// MOOD ASIDES — Friendly band (mood 6079)
// Warm and helpful but not effusive. The middle-friendly read: TwinBee
// has noticed your competence and is rooting for you without making it weird.
// ─────────────────────────────────────────────────────────────────────────────
var MoodAsidesFriendly = []string{
"TwinBee is enjoying the run. Just enough to mention the door hinge that creaks before it opens. Just barely.",
"The mood is up. TwinBee will throw in an adjective or two more than strictly necessary. Treat them as gifts.",
"TwinBee is, frankly, having a fine time. You are doing the work. TwinBee is appreciating it.",
"The narration warms slightly. The dungeon is the same. TwinBee is in a marginally better mood and it shows.",
"TwinBee notices something nice and chooses to mention it. This is the equivalent of a small wave from a stranger. Take it.",
"You're playing well. TwinBee will not say so directly but the run rate of helpful adjectives is detectably up.",
"TwinBee is, by the standards of TwinBee, *cheerful*. The dungeon hasn't changed. The narration has.",
}

View File

@@ -27,7 +27,7 @@ var HarvestMineSuccess = []string{
}
var HarvestScavengeSuccess = []string{
"There it is. Among the debris, the decay, the things that were left behind — something worth taking. TwinBee knew it was there. You found it. TwinBee is pleased.",
"There it is. Among the debris, the decay, the things that were left behind — something worth taking. TwinBee knew it was there. You found it. Pleased.",
"The room held something after all. TwinBee had estimated 60% odds and updates the estimate to 'correct.'",
"Like finding the secret item in a dungeon chest that looked empty — you checked anyway. That's the habit. That's the discipline. TwinBee notes both.",
"Scavenged. The word has a bad reputation it doesn't deserve. You found value in the discarded. TwinBee respects that entirely.",
@@ -136,7 +136,7 @@ var HarvestSunkenTemple = []string{
var HarvestHauntedManor = []string{
"The manor keeps things. Has always kept things. TwinBee takes this one out of the keeping and into the useful, which is a small act of defiance against the house's whole philosophy.",
"Found among the things that have been here since the last person stopped being here. TwinBee notes the provenance without dwelling on it.",
"The house watches you take it. TwinBee watches the house watch you. A full triangle of observation, and TwinBee notes: the house blinks first.",
"The house watches you take it. TwinBee watches the house watch you. A full triangle of observation the house blinks first.",
}
var HarvestUnderforge = []string{
@@ -152,7 +152,7 @@ var HarvestUnderdark = []string{
}
var HarvestFeywild = []string{
"The Feywild gives things away. That's the problem — it gives things away and sometimes what it gives isn't what you thought you were taking. TwinBee checks the material twice. It appears to be what it appears to be. TwinBee remains alert.",
"The Feywild gives things away. That's the problem — it gives things away and sometimes what it gives isn't what you thought you were taking. TwinBee checks the material twice. It appears to be what it appears to be. Remains alert.",
"Beautiful material from a zone that uses beauty as a weapon. TwinBee takes it carefully, like picking up something that might be watching.",
"The fey made this place generous on purpose. TwinBee is not going to complain about the generosity and is not going to stop watching for the catch.",
}
@@ -221,7 +221,7 @@ var LootDropCommon = []string{
var LootDropUncommon = []string{
"Better than expected. TwinBee examines the drop with slightly elevated interest. Uncommon rarity — someone made this with intent.",
"An uncommon drop from a common enemy. TwinBee notes the anomaly with satisfaction. The dungeon was generous in this room.",
"Uncommon. TwinBee turns it over once and nods. 'Keeper,' TwinBee says, which in TwinBee's vocabulary means: this changes your math.",
"Uncommon. TwinBee turns it over once and nods. 'Keeper,' it says, which in TwinBee's vocabulary means: this changes your math.",
}
var LootDropRare = []string{
@@ -231,7 +231,7 @@ var LootDropRare = []string{
}
var LootDropLegendary = []string{
"TwinBee goes very still. The drop sits in the light and TwinBee processes what it is seeing. 'Legendary,' TwinBee says eventually. One word. That's all it needs.",
"TwinBee goes very still. The drop sits in the light and it processes what it is seeing. 'Legendary,' TwinBee says eventually. One word. That's all it needs.",
"Legendary rarity. TwinBee has seen a few of these in a long career and each time — each time — there is a moment that is separate from everything else. This is that moment. Pick it up carefully.",
"The dungeon produced a legendary item. TwinBee notes the zone, the enemy, the day of the expedition, the Threat Clock value, the precise conditions. Some things deserve to be recorded completely.",
}

View File

@@ -26,7 +26,7 @@ var RoomEntryAbyssPortal = []string{
"A chamber where reality has a seam. The seam is visible. It runs floor-to-ceiling along the north wall and what is visible through the seam is not the next room. TwinBee does not look directly at it and recommends you adopt the same policy.",
"You enter what was once a chapel — to which god, you cannot tell, because the iconography has been overwritten in a script that hurts to read. The altar is intact. The thing on the altar is not what was placed there. TwinBee says nothing and moves you past it.",
"The air pressure is wrong. Not low — wrong. There is a pressure that is not physical and it is leaning on you with the patience of a mountain. TwinBee identifies it as psychic ambient and recommends moving briskly.",
"A staircase. The stairs go down on the way up and up on the way down. TwinBee does not pause to verify this. TwinBee takes the stairs in the direction TwinBee intended to take them and the direction works, mostly.",
"A staircase. The stairs go down on the way up and up on the way down. TwinBee does not pause to verify this. Takes the stairs in the intended direction and the direction works, mostly.",
"The corridor ahead is lit by something that is not fire. The light is red but the wrong red — the red of an alarm in a system that has never been fully implemented. TwinBee files this under 'demonic ambient' and shortens its stride.",
"You enter a room that has been used as a portal anchor. The anchor is still in place. The portal is not, but the place where it was is still warm. TwinBee tracks the residual energy and notes the portal is not the only one — there are other warm spots, in other rooms, in a pattern.",
"A garden. Indoors. The plants are not plants. TwinBee identifies them as 'demonic ornamentals — mid-tier, decorative, will react to perfumes' and recommends not perspiring near them.",

View File

@@ -78,7 +78,7 @@ var ValdrisSignatureCallouts = func() []string {
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. TwinBee has read the contemporaneous accounts and finds 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. TwinBee will not say where they are because TwinBee doesn't fully know, and the partial knowledge TwinBee has is the kind that gets people followed by things that prefer not to be looked for.",
"The phylactery shard you'll find here is one of seven. The other six are not in this crypt. TwinBee 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. TwinBee respects 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. TwinBee suggests 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. TwinBee finds the asymmetry instructive. It also finds the pattern instructive: you are walking into the open door, not opening it.",

View File

@@ -62,7 +62,7 @@ var EliteRoomEntryFeywildCrossing = []string{
// Coven Magic: extra spell slots scaled by GM Mood (high mood = stronger Thornmother).
var ThornmotherCovenLines = []string{
"Her slot pool scales with TwinBee's mood — Effusive TwinBee buys the Thornmother an extra round of high-tier casts. TwinBee says: 'My affection is taxable here. Sorry. Spread out.'",
"Her slot pool scales with TwinBee's mood — Effusive TwinBee buys the Thornmother an extra round of high-tier casts. 'My affection is taxable here,' it says. 'Sorry. Spread out.'",
"Coven Magic. The slots above her base list are mood-scaled — the better the mood at the run's start, the worse this fight runs late. TwinBee files this under 'cosmic irony' and notes the math is fixed at zone entry.",
"She has more spells than the sheet says. The extra ones come from the coven and the coven volume is set by TwinBee's mood. TwinBee tracks the count and warns the party when the bonus tier is in play.",
}

View File

@@ -33,7 +33,7 @@ var EliteRoomEntryManorBlackspire = []string{
"You enter what appears to be a guest bedroom. The bed is made. The candles are lit. A man sits on the edge of the bed with his back to you, perfectly still. He has been perfectly still for a long time. When he turns, only his head turns, and TwinBee notes the impossible angle and files this under 'revenant — directed undead, single purpose, finite lifespan, very patient.' The patience is the part that worries TwinBee.",
"The hallway dead-ends in a chapel. There is a kneeling figure at the altar. The candles around him are unlit but somehow casting shadows. He has been praying since before the manor was haunted, and the prayer was not a request — it was a contract. TwinBee says: 'Revenant. The contract is the encounter. Break the contract, end the fight.'",
"A library. The man at the table is reading a book that has no pages. He is reading it carefully. He looks up when you enter and his expression does something that suggests he was expecting a different visitor and is willing to make do. TwinBee notes the revenant's hands — the bones in the wrong places, the joints set with intent — and recommends ranged engagement until the geometry of the threat is clear.",
"The ballroom is empty except for one figure standing in the exact center, not dancing, not waiting, simply standing. The chandeliers above him are not moving. They should be moving — they were moving in the last room — and the fact that they have stopped where this figure is standing tells TwinBee everything TwinBee needed to know. 'Revenant in the middle of a stilled room,' TwinBee says. 'He brought the silence with him.'",
"The ballroom is empty except for one figure standing in the exact center, not dancing, not waiting, simply standing. The chandeliers above him are not moving. They should be moving — they were moving in the last room — and the fact that they have stopped where this figure is standing tells TwinBee everything it needed to know. 'Revenant in the middle of a stilled room,' it says. 'He brought the silence with him.'",
"A nursery. Untouched. The cradle still rocks. The figure beside the cradle was, in life, the sort of man people did not survive being wronged by. In death he has been more thorough. TwinBee notes the revenant's grip on the cradle's edge and suggests, quietly, that whatever happened in this room is not the encounter — the encounter is what walks out of it.",
}

View File

@@ -23,7 +23,7 @@ package flavor
var RoomEntrySunkenTemple = []string{
"You step into water that's been in this room for thirty years. The floor is tiled and slick. The pillars are barnacled at chest height — that's the old waterline. The new waterline is at your ankles. TwinBee notes the temple is partway through deciding which it prefers.",
"The chamber is half-flooded and half-lit. Salt in the air, salt on the walls, salt in places nothing oceanic should be reaching. TwinBee files this under 'unwell' and proceeds.",
"Glyphs cover the far wall in a script that doesn't match anything TwinBee recognizes. The angles are wrong on purpose. TwinBee keeps reading anyway, because TwinBee always tries, and stops when the reading starts to feel reciprocal.",
"Glyphs cover the far wall in a script that doesn't match anything TwinBee recognizes. The angles are wrong on purpose. It keeps reading anyway, because it always tries, and stops when the reading starts to feel reciprocal.",
"The water in this room is not moving. Not the way still water doesn't move — the way a held breath doesn't move. TwinBee suggests not disturbing it more than necessary.",
"Pillars rise from water that goes deeper than the room should allow. TwinBee tests the depth with the haft of a polearm and stops at the point where the haft stops finding bottom.",
"A vaulted ceiling that's mostly intact. Water pools in places it shouldn't, drips from places it can't be coming from. TwinBee identifies the temple as 'wet on principle' and leaves it at that.",

View File

@@ -39,7 +39,7 @@ var RoomEntryUnderforge = []string{
// ─────────────────────────────────────────────────────────────────────────────
var BossEntryEmberlordThyrak = []string{
"The chamber is the largest forge TwinBee has narrated and TwinBee has narrated several. Nine furnaces in a ring. A central anvil the size of a wagon. The figure at the anvil is twelve feet of articulated iron and inset rune-stones that pulse to a tempo TwinBee can feel in its plating. The hammer comes down. The strike rings the room. The figure does not turn — finishes the strike, then turns. The eyes are not eyes. They are vents. 'Visitor,' Thyrak says, and the word is a furnace door opening. TwinBee takes a half-step back and says, very evenly, 'Forge-golem. Three centuries of self-improvement. Don't fight him on the lava.'",
"The chamber is the largest forge TwinBee has ever narrated, and it has narrated several. Nine furnaces in a ring. A central anvil the size of a wagon. The figure at the anvil is twelve feet of articulated iron and inset rune-stones that pulse to a tempo TwinBee can feel in its plating. The hammer comes down. The strike rings the room. The figure does not turn — finishes the strike, then turns. The eyes are not eyes. They are vents. 'Visitor,' Thyrak says, and the word is a furnace door opening. TwinBee takes a half-step back and says, very evenly, 'Forge-golem. Three centuries of self-improvement. Don't fight him on the lava.'",
}
// ─────────────────────────────────────────────────────────────────────────────