Adv 2.0 L5c: NPC counters/debuffs migration off AdvCharacter

Thirteen player_meta columns: misty/arina_last_seen,
misty_buff_expires, misty_debuff_expires, arina_buff_expires (all
nullable DATETIME), npc_msg_count + npc_msg_count_date,
misty/arina_roll_target, misty_encounter_count, misty_donated_count,
thom_animal_line_fired, robbie_visit_count.

NPCState struct with HasNPCActivity() marker + load/upsert/backfill/
projection helpers. Dual-writes wired at every NPC mutation site:
processNPCEncounters msg-count save, npcFireEncounter last-seen,
resolveMisty (insufficient balance, debit failure, buff/donated,
declined-debuff), resolveArina buff, adventure_robbie visit count,
adventure_housing Thom animal line.

Hidden discovery mechanic — buffs/debuffs and counters never surface
in player-facing output.

Tests: TestPlayerMetaNPCStateBackfill_Idempotent,
TestLoadNPCState_FallsBackToAdvCharacter,
TestUpsertPlayerMetaNPCState_RoundTrip.

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

View File

@@ -250,6 +250,23 @@ func runMigrations(d *sql.DB) error {
`ALTER TABLE player_meta ADD COLUMN babysit_skill_focus TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE player_meta ADD COLUMN auto_babysit INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN auto_babysit_focus TEXT NOT NULL DEFAULT ''`,
// Adv 2.0 Phase L5c — NPC counters & debuff timestamps off AdvCharacter.
// Misty/Arina/Robbie/Thom counters and buff/debuff expiry times move
// to player_meta (gogobee_legacy_migration.md §7.3 L5c). Hidden
// discovery mechanics — never surface in player-facing output.
`ALTER TABLE player_meta ADD COLUMN misty_last_seen DATETIME`,
`ALTER TABLE player_meta ADD COLUMN arina_last_seen DATETIME`,
`ALTER TABLE player_meta ADD COLUMN misty_buff_expires DATETIME`,
`ALTER TABLE player_meta ADD COLUMN misty_debuff_expires DATETIME`,
`ALTER TABLE player_meta ADD COLUMN arina_buff_expires DATETIME`,
`ALTER TABLE player_meta ADD COLUMN npc_msg_count INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN npc_msg_count_date TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE player_meta ADD COLUMN misty_roll_target INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN arina_roll_target INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN misty_encounter_count INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN misty_donated_count INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN thom_animal_line_fired INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN robbie_visit_count INTEGER NOT NULL DEFAULT 0`,
}
for _, stmt := range columnMigrations {
if _, err := d.Exec(stmt); err != nil {