Adv 2.0 L5a: skills migration off AdvCharacter to player_meta

Eight player_meta columns (combat_level, combat_xp, mining_skill,
mining_xp, foraging_skill, foraging_xp, fishing_skill, fishing_xp).
SkillState struct with HasSkills() marker mirrors PetState/HouseState
shape. loadSkillState / upsertPlayerMetaSkillState /
backfillPlayerMetaSkillState / skillStateFromAdvChar helpers.

Dual-writes wired at every mutation site: consumables craft XP (both
success and failure branches), events.go XP grant across all skills,
arena death + session-complete combat XP. Backfill is idempotent (only
fills rows where every skill column is still zero AND the legacy row
has any non-zero value).

CombatLevel/CombatXP are transitional — dropped at L5g after the DnD
mass-backfill retires the legacy CombatLevel-derived fallback.

Tests: TestPlayerMetaSkillStateBackfill_Idempotent,
TestLoadSkillState_FallsBackToAdvCharacter,
TestUpsertPlayerMetaSkillState_RoundTrip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-09 11:16:07 -07:00
parent cf072f8a8f
commit 79e5d19d23
8 changed files with 317 additions and 1 deletions

View File

@@ -226,6 +226,21 @@ func runMigrations(d *sql.DB) error {
`ALTER TABLE player_meta ADD COLUMN house_missed_payments INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN house_autopay INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN house_current_rate REAL NOT NULL DEFAULT 0`,
// Adv 2.0 Phase L5a — Skills migration off AdvCharacter.
// CombatLevel / MiningSkill / ForagingSkill / FishingSkill and their
// XP counters move to player_meta; AdvCharacter columns keep
// dual-writing during soak (gogobee_legacy_migration.md §7.3 L5a).
// CombatLevel/CombatXP are transitional — dropped after L5g's
// DnDCharacter mass-backfill retires the dndLevelFromCombatLevel
// fallback.
`ALTER TABLE player_meta ADD COLUMN combat_level INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN combat_xp INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN mining_skill INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN mining_xp INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN foraging_skill INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN foraging_xp INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN fishing_skill INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN fishing_xp INTEGER NOT NULL DEFAULT 0`,
}
for _, stmt := range columnMigrations {
if _, err := d.Exec(stmt); err != nil {