Adv 2.0 L5h: cold AdvCharacter table — saveAdvCharacter fan-outs to player_meta

saveAdvCharacter no longer writes the legacy adventure_characters row.
It's now a thin fan-out: bumps LastActiveAt and routes through
upsertAllPlayerMetaFromAdvChar, which calls the per-subsystem upserts
for display_name, hospital, arena, masterwork, rival, skills, babysit,
NPC, lifecycle, death, misc, pet, and house.

loadAdvCharacter calls applyPlayerMetaOverlay at the tail to re-source
every migrated subsystem from player_meta. The adventure_characters
SELECT still happens (for the user_id / equipment-table linkage and as
a fallback substrate) but its values are overwritten by the overlay.
This achieves the L4e in-place housing reader flip automatically —
adventure_housing.go's char.HouseFoo reads now see player_meta values
without per-site changes.

npcMidnightReset extended to write player_meta alongside the frozen
adventure_characters.

Per-call-site upsertPlayerMetaXxx duals are now redundant with the
saveAdvCharacter fan-out but kept as defense; cleanup deferred.
player_meta.combat_level column drop deferred — still read by babysit
cost / combat_stats / activities via the overlay; sequenced with the
final combat_engine teardown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-09 11:52:03 -07:00
parent 0d2e554e22
commit 1c7939c3c8
4 changed files with 199 additions and 151 deletions

View File

@@ -428,18 +428,28 @@ func npcRepairMostDamaged(userID id.UserID, equip map[EquipmentSlot]*AdvEquipmen
// npcMidnightReset resets message counts and regenerates roll targets.
// Called from midnightReset. Uses a direct DB update to avoid loading/saving
// every character individually.
// every character individually. Phase L5h: writes player_meta as the
// canonical store; the legacy adventure_characters update is preserved
// only as a defensive sweep for rows that pre-date the L5c backfill.
func npcMidnightReset() {
d := db.Get()
today := time.Now().UTC().Format("2006-01-02")
_, err := d.Exec(`
if _, err := d.Exec(`
UPDATE player_meta
SET npc_msg_count = 0,
npc_msg_count_date = ?,
misty_roll_target = ABS(RANDOM()) % 6 + 5,
arina_roll_target = ABS(RANDOM()) % 6 + 5`,
today); err != nil {
slog.Error("npc: midnight reset (player_meta) failed", "err", err)
}
if _, err := d.Exec(`
UPDATE adventure_characters
SET npc_msg_count = 0,
npc_msg_count_date = ?,
misty_roll_target = ABS(RANDOM()) % 6 + 5,
arina_roll_target = ABS(RANDOM()) % 6 + 5`,
today)
if err != nil {
slog.Error("npc: midnight reset failed", "err", err)
today); err != nil {
slog.Error("npc: midnight reset (adventure_characters) failed", "err", err)
}
}