mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 17:02:42 +00:00
N7/B2: Renown — prestige past the L20 cap
Overflow XP that grantDnDXP used to drop at L20 now accumulates as Renown on player_meta.renown_xp (cumulative, atomic +=; renown_level derived as renown_xp/25000). The reward is prestige-only: a derived rank ladder (Renowned→…→Eternal), a cosmetic ✦N marker on the sheet and leaderboard, a games-room shout on rank promotion, and !level progress once capped. Renown perks are the two combat-neutral economy levers only — +loot / +XP, capped at a streak-30 grant's economic half (+15% / +20%). combat_stats.go reads DeathModifier/SuccessBonus/ExceptionalBonus (which map to Defense/ Attack/CritRate) but never LootQuality/XPMultiplier, so renown pays out even through loadCombatBonuses without moving the golden or the balance corpus. The plan's "-death penalty" perk is deliberately dropped (it would inflate Defense). The overflow→renown conversion and the character save commit in one transaction (saveDnDCharacterExec now takes an executor), so a crash can neither drop the overflow nor double-credit it on the next grant. Schema: renown_xp column, DEFAULT 0 correct for every existing row, no bootstrap (journal_pages/epilogue_cleared pattern). Claude-Session: https://claude.ai/code/session_017mEwUmmS7aQTP2NQXj6rUa
This commit is contained in:
@@ -127,15 +127,26 @@ func (p *AdventurePlugin) grantDnDXP(userID id.UserID, amount int) ([]LevelUpEve
|
||||
events = append(events, LevelUpEvent{NewLevel: c.Level, HPGain: gain})
|
||||
}
|
||||
|
||||
// Cap at L20 — overflow XP is silently dropped.
|
||||
if c.Level >= dndMaxLevel {
|
||||
// N7/B2 Renown — persist the character; at the cap, overflow XP that used to
|
||||
// be dropped converts to Renown in the SAME transaction as the save, so a
|
||||
// crash can neither lose the overflow nor double-credit it on the next grant.
|
||||
// Renown is title + cosmetic + capped loot/XP perks, never combat stats, so
|
||||
// the balance corpus stays valid.
|
||||
var renownFrom, renownTo int
|
||||
if c.Level >= dndMaxLevel && c.XP > 0 {
|
||||
overflow := c.XP
|
||||
c.XP = 0
|
||||
}
|
||||
|
||||
if err := SaveDnDCharacter(c); err != nil {
|
||||
from, to, err := saveDnDCharacterWithOverflow(c, overflow)
|
||||
if err != nil {
|
||||
return events, err
|
||||
}
|
||||
renownFrom, renownTo = renownLevelFor(from), renownLevelFor(to)
|
||||
} else if err := SaveDnDCharacter(c); err != nil {
|
||||
return events, err
|
||||
}
|
||||
|
||||
p.announceRenown(userID, renownFrom, renownTo)
|
||||
|
||||
if len(events) > 0 {
|
||||
// Phase 10 SUB3a-ii — Battle Master Relentless (L15) raises the
|
||||
// superiority cap from 4 → 5; reconcile any level-gated subclass pool
|
||||
|
||||
Reference in New Issue
Block a user