mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
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:
@@ -358,6 +358,17 @@ func (p *AdventurePlugin) zoneCmdAdvance(ctx MessageContext) error {
|
||||
prev := run.CurrentRoomType()
|
||||
prevIdx := run.CurrentRoom
|
||||
|
||||
// §4.1 Patrol Encounter: at Threat-Clock Alert+, patrols may move
|
||||
// through cleared rooms. Roll on `!advance` *before* the next room's
|
||||
// own resolution. Player KO ends the run.
|
||||
patrolNarr, patrolEnded, perr := p.tryPatrolEncounter(ctx.Sender, run, zone)
|
||||
if perr != nil {
|
||||
return p.SendDM(ctx.Sender, "Couldn't resolve patrol: "+perr.Error())
|
||||
}
|
||||
if patrolEnded {
|
||||
return p.SendDM(ctx.Sender, patrolNarr)
|
||||
}
|
||||
|
||||
// Resolve the current room *before* clearing it, so combat results
|
||||
// can decide whether the player advances or the run ends.
|
||||
resolution, ended, err := p.resolveRoom(ctx.Sender, run, zone)
|
||||
@@ -375,6 +386,10 @@ func (p *AdventurePlugin) zoneCmdAdvance(ctx MessageContext) error {
|
||||
if next == "" {
|
||||
_, _ = applyMoodEvent(run.RunID, MoodEventZoneComplete)
|
||||
var b strings.Builder
|
||||
if patrolNarr != "" {
|
||||
b.WriteString(patrolNarr)
|
||||
b.WriteString("\n\n")
|
||||
}
|
||||
if resolution != "" {
|
||||
b.WriteString(resolution)
|
||||
b.WriteString("\n\n")
|
||||
@@ -396,6 +411,10 @@ func (p *AdventurePlugin) zoneCmdAdvance(ctx MessageContext) error {
|
||||
|
||||
nextIdx := run.CurrentRoom + 1
|
||||
var b strings.Builder
|
||||
if patrolNarr != "" {
|
||||
b.WriteString(patrolNarr)
|
||||
b.WriteString("\n\n")
|
||||
}
|
||||
if resolution != "" {
|
||||
b.WriteString(resolution)
|
||||
b.WriteString("\n\n")
|
||||
@@ -493,6 +512,11 @@ func (p *AdventurePlugin) resolveCombatRoom(userID id.UserID, run *DungeonRun, z
|
||||
b.WriteString("\n")
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("✅ **%s** down (HP %d→%d).", monster.Name, result.PlayerStartHP, result.PlayerEndHP))
|
||||
recordZoneKillForUser(userID, monster.ID)
|
||||
if drop := p.dropZoneLoot(userID, zone.ID, monster, false); drop != "" {
|
||||
b.WriteString("\n")
|
||||
b.WriteString(drop)
|
||||
}
|
||||
return b.String(), false, nil
|
||||
}
|
||||
|
||||
@@ -532,6 +556,11 @@ func (p *AdventurePlugin) resolveBossRoom(userID id.UserID, run *DungeonRun, zon
|
||||
b.WriteString("\n")
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("🏆 **%s** falls (HP %d→%d).", monster.Name, result.PlayerStartHP, result.PlayerEndHP))
|
||||
recordZoneKillForUser(userID, monster.ID)
|
||||
if drop := p.dropZoneLoot(userID, zone.ID, monster, true); drop != "" {
|
||||
b.WriteString("\n")
|
||||
b.WriteString(drop)
|
||||
}
|
||||
return b.String(), false, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user