mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-17 01:12:41 +00:00
adventure: Tier 6 postgame "Mythic" dungeons (P1–P7 calibration)
Five post-game dungeons above the T5 ceiling, gated on both T5 bosses beaten + level 18. Opt-in endgame: deadly solo, clearable by a party with Pete + pets. - P1 gating: postgameUnlocked (T5 clears + level floor), zonesForLevel excludes T6 unconditionally; wired into startZoneRun, !zone/!expedition, party accept, boredom picker, and the list dividers. - P2 bestiary: 15 elites + 5 signature bosses (Layer-1 stat blocks). - P3 zone defs + 4-region registries; ZoneLootEntry.BossOnly. - P4 five zone graphs on a shared builder (44–52 rooms, no soft-lock; Ossuary secret Verse nodes). - P5 loot: BossOnly enforced; signature items are real registry magic items; five Thom pity recipes off the per-zone crafting anchors. - P6 narration/flavor (5 files), T6 achievements, Pete stays zone-parametric. - P7 (in progress): sim can now reach gated T6 (SimRunner.SeedPostgameUnlock + IsPostgameZone). First calibration pass on millenia — hardened ossuary + drowned_star, softened first_hoard + unplace; last_meridian in band. Fix: party members were refused from every T6 zone because expeditionCmdAccept ran the level gate (which excludes T6) before the postgame check — the intended party endgame was unreachable. Route T6 through postgameUnlocked. Regression tests added.
This commit is contained in:
@@ -160,6 +160,23 @@ func (p *AdventurePlugin) expeditionCmdList(ctx MessageContext, c *DnDCharacter)
|
||||
i+1, z.Display, int(z.Tier), z.LevelMin, z.LevelMax, z.ID, suffix))
|
||||
b.WriteString(fmt.Sprintf(" %s\n", z.Atmosphere))
|
||||
}
|
||||
// Post-game zones under the "Beyond the Map" divider (see zoneCmdList).
|
||||
if pg := postgameZones(); len(pg) > 0 {
|
||||
unlocked, reason := postgameUnlocked(ctx.Sender, c.Level)
|
||||
b.WriteString("\n— Beyond the Map —\n")
|
||||
if !unlocked {
|
||||
b.WriteString(fmt.Sprintf("_%s_\n", reason))
|
||||
}
|
||||
for j, z := range pg {
|
||||
if unlocked {
|
||||
b.WriteString(fmt.Sprintf("**%d.** %s — _T%d, L%d+_ `!expedition start %s`\n",
|
||||
len(zones)+j+1, z.Display, int(z.Tier), z.LevelMin, z.ID))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("🔒 %s — _T%d, L%d+_\n", z.Display, int(z.Tier), z.LevelMin))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(" %s\n", z.Atmosphere))
|
||||
}
|
||||
}
|
||||
if exp, isLeader, _ := activeExpeditionFor(ctx.Sender); exp != nil {
|
||||
zone := zoneOrFallback(exp.ZoneID)
|
||||
tail := "Use `!expedition status` or `!expedition abandon`."
|
||||
@@ -295,9 +312,12 @@ func (p *AdventurePlugin) expeditionCmdStart(ctx MessageContext, c *DnDCharacter
|
||||
if strings.EqualFold(zoneTok, "epilogue") {
|
||||
return p.handleEpilogueEncounter(ctx)
|
||||
}
|
||||
available := zonesForLevel(c.Level)
|
||||
available := availableZonesFor(ctx.Sender, c.Level)
|
||||
zoneID, ok := resolveZoneInput(zoneTok, available)
|
||||
if !ok {
|
||||
if reason := postgameLockReason(zoneTok, ctx.Sender, c.Level); reason != "" {
|
||||
return p.SendDM(ctx.Sender, reason)
|
||||
}
|
||||
return p.SendDM(ctx.Sender,
|
||||
"Unknown zone for your level. Try `!expedition list`.")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user