feat(rust): RunicNPC profiles, their push and adoption, per-profile kills (runicnpc stage 4, WIP)

Schema for site NPC profiles (per server, shared or fleet), the per-server
push record, and kills by profile. The push adopts a server's own profiles
before its first push (D244), keeping one whose name a site profile already
has as replaced (D251). The tally's npcProfileKills are stored per profile
and credited to the site profile pushed under that name (D247).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-09-30 04:21:46 -05:00
parent b0143801a2
commit 564a234890
12 changed files with 1200 additions and 0 deletions

View File

@@ -40,6 +40,8 @@ const db = require('./model/events/events.db')
const engagement = require('./engagement/emit')
const eventWorld = require('./eventWorld')
const links = require('./model/links/links.model')
const npcs = require('./model/npcs/npcs.model')
const npcsDb = require('./model/npcs/npcs.db')
const permissionsDb = require('./model/permissions/permissions.db')
const sidecar = require('./sidecarClient')
@@ -158,6 +160,15 @@ async function apply(serverId, item, server = null) {
for (const [weapon, kills] of Object.entries(weapons)) {
await db.addWeaponKills(at, weapon, Math.floor(Number(kills) || 0))
}
// RunicNPC's NPCs, by profile name (D247). Credited to the site profile
// that name was last pushed as on this server, so "this profile only"
// can be counted; 0 for a name the site never pushed.
const profiles = frame.npcProfileKills && typeof frame.npcProfileKills === 'object' ? frame.npcProfileKills : {}
for (const [profile, kills] of Object.entries(profiles)) {
const n = Math.floor(Number(kills) || 0)
if (n > 0) await npcsDb.addKills(at, profile, await npcs.siteProfileFor(serverId, profile), n)
}
break
}