Adv 2.0 D&D Phase R R3-R5: Combat-link, zone loot, fishing, economy

R3 — Combat Event Integration:
- dnd_expedition_combat.go: Combat Interrupt rolls (§4.2) with
  threat-clock and Ranger-wilderness modifiers; Patrol Encounters
  scaled by threat level; recordZoneKill writer with monsterKillTags.
- Interrupt gate at head of handleHarvestCmd; patrol gate before
  resolveRoom in zoneCmdAdvance; kill writer wired into combat-win
  paths.

R4a — Zone Loot Tables:
- dnd_zone_loot.go: §5 loot drop tables for all 10 zones × 5 tiers
  with §8.1 sell-value bands. dropTierFromCR brackets + boss floor.
- Hooks on combat-win in resolveCombatRoom, resolveBossRoom,
  runHarvestInterrupt, tryPatrolEncounter.

R4b — Fishing Integration:
- dnd_zone_fish.go: fishingZones allow-list, fishingSkillBonus,
  rangerRareCatchUpgrade (§6.2), feywildFishDistortion narration.
- §6.1 fish entries added to resource registry for Forest, Sunken
  Temple, Underdark, Feywild zones.
- !fish wired through handleHarvestCmd; zoneItemFlavor matrix
  populated for all 10 zones × all loot items.

R5 — Economy Integration:
- dnd_economy.go: !sell (post-expedition gate, single CHA Persuasion
  DC 17 → +15% bump), !craft (§8.2 4 exemplar recipes), !lore
  (INT/Arcana DC 15 recipe discovery).
- dnd_known_recipe table for persistent recipe discovery.

Flavor reuse: HarvestInterrupt, PatrolEncounter, CombatVictory,
PlayerDeath, LootDrop*, FeywildTimeDistortion* — all existing pools.
No new flavor file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-08 18:31:27 -07:00
parent 83cdf07374
commit c170adaf05
13 changed files with 2507 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
package plugin
import (
"math/rand/v2"
"gogobee/internal/flavor"
)
// Resource & Combat Integration §6 — Fishing System Integration.
//
// Fishing reuses the harvest pipeline (HarvestFish action). This file
// adds the §6 zone gate, the existing FishingSkill rank bonus, the
// Ranger +20% rare-catch rule, and the Feywild Time Distortion hook.
// fishingZones is the §6.1 allow-list — only these zones expose !fish.
var fishingZones = map[ZoneID]bool{
ZoneForestShadows: true,
ZoneSunkenTemple: true,
ZoneUnderdark: true,
ZoneFeywildCrossing: true,
}
// isFishingZone returns true if !fish is permitted in zoneID.
func isFishingZone(zoneID ZoneID) bool { return fishingZones[zoneID] }
// fishingSkillBonus folds the legacy FishingSkill (010) into a small
// roll bonus so existing rank progression still pays off inside the
// expedition pipeline. +1 per 5 levels, capped at +2.
func fishingSkillBonus(fishingSkill int) int {
if fishingSkill <= 0 {
return 0
}
bonus := fishingSkill / 5
if bonus > 2 {
bonus = 2
}
return bonus
}
// rangerRareCatchUpgrade implements §6.2 — Ranger +20% rare catch rate.
// When the harvest outcome is Common or Standard for a fishing attempt
// by a Ranger, 20% chance to upgrade to Rich. Returns the (possibly
// upgraded) outcome.
func rangerRareCatchUpgrade(class DnDClass, action HarvestAction, outcome HarvestOutcome, rng *rand.Rand) HarvestOutcome {
if class != ClassRanger || action != HarvestFish {
return outcome
}
if outcome != OutcomeCommon && outcome != OutcomeStandard {
return outcome
}
if rngFloat(rng) < 0.20 {
return OutcomeRich
}
return outcome
}
// feywildFishDistortion narrates a Time Distortion flicker on a fishing
// attempt in Feywild Crossing. 15% chance per attempt; pure flavor for
// R4b (mechanical Time Loop event lives in the temporal-events system
// and is not duplicated here).
func feywildFishDistortion(zoneID ZoneID, action HarvestAction, rng *rand.Rand) string {
if zoneID != ZoneFeywildCrossing || action != HarvestFish {
return ""
}
if rngFloat(rng) >= 0.15 {
return ""
}
line := flavor.Pick(flavor.FeywildTimeDistortionHalf)
if line == "" {
line = flavor.Pick(flavor.FeywildTimeLoop)
}
if line == "" {
return ""
}
return "_⏳ " + line + "_\n\n"
}