mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
N7/B4: Renown achievements wing
Three passive achievements (renown_1/5/10) gated on the derived Renown level via renownAtLeast, reading player_meta.renown_xp through the achievements plugin's existing Check(d, userID) seam. No event hook — the passive checker grants them on the next message once the level is reached. Claude-Session: https://claude.ai/code/session_017mEwUmmS7aQTP2NQXj6rUa
This commit is contained in:
@@ -1206,9 +1206,39 @@ func (p *AchievementsPlugin) buildAchievements() []achievementDef {
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// N7/B4 — the Renown wing (gogobee_engagement_plan.md §B4). Passive checks
|
||||||
|
// against the derived Renown level (N7/B2); no event hook needed.
|
||||||
|
{
|
||||||
|
ID: "renown_1", Name: "Beyond the Cap", Description: "Earned your first level of Renown. The story was supposed to be over.",
|
||||||
|
Emoji: "✦",
|
||||||
|
Check: func(d *sql.DB, u id.UserID) bool { return renownAtLeast(d, u, 1) },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "renown_5", Name: "Storied", Description: "Reached Renown 5. They tell versions of your runs that never happened.",
|
||||||
|
Emoji: "✦",
|
||||||
|
Check: func(d *sql.DB, u id.UserID) bool { return renownAtLeast(d, u, 5) },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "renown_10", Name: "Fabled", Description: "Reached Renown 10. Somewhere a bard is getting rich off your name.",
|
||||||
|
Emoji: "✦",
|
||||||
|
Check: func(d *sql.DB, u id.UserID) bool { return renownAtLeast(d, u, 10) },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renownAtLeast reports whether the player's derived Renown level (N7/B2) has
|
||||||
|
// reached level, reading player_meta.renown_xp through the passed handle.
|
||||||
|
func renownAtLeast(d *sql.DB, userID id.UserID, level int) bool {
|
||||||
|
var xp int
|
||||||
|
if err := d.QueryRow(
|
||||||
|
`SELECT renown_xp FROM player_meta WHERE user_id = ?`,
|
||||||
|
string(userID),
|
||||||
|
).Scan(&xp); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return renownLevelFor(xp) >= level
|
||||||
|
}
|
||||||
|
|
||||||
// ── Expedition achievement helpers ──────────────────────────────────────────
|
// ── Expedition achievement helpers ──────────────────────────────────────────
|
||||||
|
|
||||||
// clearedZoneIDs returns the zones this player has beaten outright. Boss-
|
// clearedZoneIDs returns the zones this player has beaten outright. Boss-
|
||||||
|
|||||||
@@ -147,6 +147,32 @@ func TestAddRenownXP_Accumulates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRenownAtLeast — the B4 achievement gate reads the derived level correctly.
|
||||||
|
func TestRenownAtLeast(t *testing.T) {
|
||||||
|
newRenownTestDB(t)
|
||||||
|
uid := id.UserID("@renown_ach:example")
|
||||||
|
if err := createAdvCharacter(uid, "Achiever"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d := db.Get()
|
||||||
|
if renownAtLeast(d, uid, 1) {
|
||||||
|
t.Errorf("no renown yet, should not meet level 1")
|
||||||
|
}
|
||||||
|
if _, _, err := addRenownXP(uid, renownXPPerLevel*5); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !renownAtLeast(d, uid, 5) {
|
||||||
|
t.Errorf("renown 5 should meet level 5")
|
||||||
|
}
|
||||||
|
if renownAtLeast(d, uid, 6) {
|
||||||
|
t.Errorf("renown 5 should not meet level 6")
|
||||||
|
}
|
||||||
|
// Absent player → false, not a crash.
|
||||||
|
if renownAtLeast(d, id.UserID("@nobody:nowhere.invalid"), 1) {
|
||||||
|
t.Errorf("absent player should not meet any renown level")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestRenownOverlay — applyPlayerMetaOverlay populates RenownXP and RenownLevel.
|
// TestRenownOverlay — applyPlayerMetaOverlay populates RenownXP and RenownLevel.
|
||||||
func TestRenownOverlay(t *testing.T) {
|
func TestRenownOverlay(t *testing.T) {
|
||||||
newRenownTestDB(t)
|
newRenownTestDB(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user