mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 17:02:42 +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:
@@ -18,6 +18,11 @@ func TestRecipeRegistry_IngredientsExistInResources(t *testing.T) {
|
||||
}
|
||||
}
|
||||
for _, r := range thomCraftRecipes {
|
||||
// AlwaysKnown pity recipes consume zone-loot crafting anchors, not
|
||||
// gather-resource materials — validated separately below.
|
||||
if r.AlwaysKnown {
|
||||
continue
|
||||
}
|
||||
for ing := range r.Ingredients {
|
||||
if !known[ing] {
|
||||
t.Errorf("recipe %s references unknown ingredient %q", r.ID, ing)
|
||||
@@ -26,12 +31,59 @@ func TestRecipeRegistry_IngredientsExistInResources(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestPityRecipes_AnchorsAndOutputsResolve — the T6 signature-item pity
|
||||
// recipes consume a zone-loot UniqueAlways crafting anchor and emit a real
|
||||
// registry magic item. Validate both ends: every ingredient name matches a
|
||||
// UniqueAlways zone-loot drop's inventory name, and every OutputSkillSource
|
||||
// points at a magicItemRegistry ID.
|
||||
func TestPityRecipes_AnchorsAndOutputsResolve(t *testing.T) {
|
||||
anchorNames := map[string]bool{}
|
||||
for _, z := range allZones() {
|
||||
for _, e := range z.Loot {
|
||||
if e.UniqueAlways {
|
||||
anchorNames[titleCaseUnderscored(e.ItemID)] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
pity := 0
|
||||
for _, r := range thomCraftRecipes {
|
||||
if !r.AlwaysKnown {
|
||||
continue
|
||||
}
|
||||
pity++
|
||||
for ing := range r.Ingredients {
|
||||
if !anchorNames[ing] {
|
||||
t.Errorf("pity recipe %s ingredient %q is not a zone-loot anchor name", r.ID, ing)
|
||||
}
|
||||
}
|
||||
if r.OutputType != "magic_item" {
|
||||
t.Errorf("pity recipe %s OutputType = %q, want magic_item", r.ID, r.OutputType)
|
||||
}
|
||||
id, ok := strings.CutPrefix(r.OutputSkillSource, "magic_item:")
|
||||
if !ok {
|
||||
t.Errorf("pity recipe %s OutputSkillSource %q missing magic_item: prefix", r.ID, r.OutputSkillSource)
|
||||
continue
|
||||
}
|
||||
if _, ok := magicItemRegistry[id]; !ok {
|
||||
t.Errorf("pity recipe %s output %q not in magicItemRegistry", r.ID, id)
|
||||
}
|
||||
}
|
||||
if pity != 5 {
|
||||
t.Errorf("expected 5 T6 pity recipes, found %d", pity)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRecipeRegistry_OutputValuesMatchTier — outputs should land in §8.1
|
||||
// rarity brackets given their tier (rare 100–300, very rare 500–1200,
|
||||
// epic 500–1200 in §8.1 — recipes here lean tier 3–4, so 200..1200 is the
|
||||
// reasonable band).
|
||||
func TestRecipeRegistry_OutputValuesInBand(t *testing.T) {
|
||||
for _, r := range thomCraftRecipes {
|
||||
// Pity recipes emit Legendary magic items priced well above the §8.1
|
||||
// crafting band by design — excluded from this invariant.
|
||||
if r.AlwaysKnown {
|
||||
continue
|
||||
}
|
||||
if r.OutputValue < 200 || r.OutputValue > 1200 {
|
||||
t.Errorf("recipe %s output value %d outside band [200,1200] (tier %d)",
|
||||
r.ID, r.OutputValue, r.OutputTier)
|
||||
|
||||
Reference in New Issue
Block a user