feat(rust): NPC profiles and placements pages, the profile leaderboard (runicnpc stage 4)

Admin: Rust NPC profiles (the form RunicNPC reads, per server, shared or
fleet, each server's push state and refusals, replaced profiles with
Restore) and Rust NPC placements (the live map: click to place, pins for
every placement; edit, rename, respawn, remove). The live map takes a pick
handler and pins, unchanged for the public page.

Public: the leaderboard ranks by a profile's kills (D250), and opening a
row shows that player's kills by profile (D252); the killfeed names a
RunicNPC NPC by its own name. Player: your own kills by profile. Titles: a
rule on a profile's kills picks the profile. npcs.test.js covers the
profile checks, adoption, the push, the picker and verb, the triggers, kill
crediting, titles and placements (481 server tests).

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:42:05 -05:00
parent fa16f0ad2e
commit 7eae4a1e62
13 changed files with 1356 additions and 10 deletions

View File

@@ -161,7 +161,9 @@ function death(frame, name) {
case 'npc':
return {
tone: 'death',
actor: attacker(frame.attackerName) || 'Something',
// One of RunicNPC's (runicnpc stage 4): its own name, as typed on its profile,
// rather than the prefab it is built from. Older frames carry only the prefab.
actor: frame.attackerNpc || attacker(frame.attackerName) || 'Something',
verb: 'killed',
subject: name,
detail: where,