feat(rust): NPC sides, the faction table, an event's escort, ally and tether (runicnpc stage 5)
RunicNPC stage 5 on the site (docs runicnpc/PLAN.md, D253-D272):
- profiles gain the guard role, faction, relations (its own exceptions),
alertRadius, turrets, hurtByPlayers, hurtsPlayers and kitUse, checked in
RunicNPC's order and words, and defaulting to "players only" (D255);
- the faction table: one site-wide table, one row per pair and both ways
(D254, D268), stored in rust_npc_factions, edited on the NPC profiles page
(PUT /admin/rust/npcs/factions), pushed to every server with its
profiles and hashed with them, and a standalone server's own pairs
adopted at its first push with the site's winning (D244, D251);
- the Place NPCs step takes escort (a Steam id or a {placeholder}), an ally
(a clan from the new rust.options.clans source, or the team of a player)
and tether (the zone this event made), for a RunicNPC profile only
(D269, D270, D272);
- a placement may be held inside a zone (tether, D272);
- the bridge's RunicNPC API floor is 4.
Tests: 488 server, 66 client. routes.manifest.json regenerated against the
pinned core (one route added).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -217,6 +217,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/rust/npcs/factions": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"Admin · Rust"
|
||||
],
|
||||
"summary": "Replace the NPC faction table",
|
||||
"description": "How factions treat each other (runicnpc stage 5, D254): one row per pair, both ways (D268), each `hostile`, `neutral` or `allied`. A pair that is not listed is neutral, and a faction is always allied to itself. `scientists` and `animals` are Rust’s own two; a pair of those two is refused, since RunicNPC does not change how Rust’s NPCs treat each other. Checked as RunicNPC checks it, stored as one table for the whole site, and pushed to every server with its profiles on the loop’s next tick. A profile with no faction settings still fights players only (D255).",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Saved",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"factions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RustNpcFactionPair"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A pair RunicNPC would refuse, in its own words"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"factions"
|
||||
],
|
||||
"properties": {
|
||||
"factions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RustNpcFactionPair"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/rust/npcs/profiles": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -639,7 +692,7 @@
|
||||
"Admin · Rust"
|
||||
],
|
||||
"summary": "Push the NPC profiles to one server now",
|
||||
"description": "Rather than on the loop’s next tick. A server the site has never pushed to has its own profiles adopted first (D244). The answer says what happened: `pushed` (with the profiles and any RunicNPC refused), `absent` (no RunicNPC, or one older than API 3, and why) or `failed` (with the reason).",
|
||||
"description": "Rather than on the loop’s next tick. A server the site has never pushed to has its own profiles adopted first (D244). The answer says what happened: `pushed` (with the profiles and any RunicNPC refused), `absent` (no RunicNPC, or one older than API 4, and why) or `failed` (with the reason).",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -10889,7 +10942,8 @@
|
||||
"type": "array",
|
||||
"example": [
|
||||
"roamer",
|
||||
"sentry"
|
||||
"sentry",
|
||||
"guard"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -11070,6 +11124,265 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"faction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Its faction (stage 5, D254); null: its allies are its own profile’s NPCs (D256)."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "bandits"
|
||||
}
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"enum": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"hostile",
|
||||
"neutral",
|
||||
"allied"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Its own exceptions, which win over the faction table: a faction, scientists, animals or profile:<name>."
|
||||
},
|
||||
"example": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"scientists": {
|
||||
"type": "string",
|
||||
"example": "hostile"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"alertRadius": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "number"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Metres within which its allies join a fight one of them is in (D256); 0 is off."
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 40
|
||||
}
|
||||
}
|
||||
},
|
||||
"turrets": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"enum": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"default",
|
||||
"ignore",
|
||||
"always"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "default: as Rust’s scientists; ignore: no turret targets it; always: the safe-zone sentries too (D259, D264, D267)."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "default"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hurtByPlayers": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "boolean"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Off: unkillable by players, on every server (D271)."
|
||||
},
|
||||
"example": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"hurtsPlayers": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "boolean"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Off: harmless to players; it still fights NPCs and turrets (D271)."
|
||||
},
|
||||
"example": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kitUse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "The kit’s extras it uses, each used up (D260, D265)."
|
||||
},
|
||||
"example": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"heal": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"grenades": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"melee": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"rockets": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"flamethrower": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustNpcFactionPair": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "One row of the faction table, both ways (D268). scientists and animals are Rust’s own; a pair of those two is refused."
|
||||
},
|
||||
"required": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"a",
|
||||
"b",
|
||||
"relation"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "bandits"
|
||||
}
|
||||
}
|
||||
},
|
||||
"b": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "guards"
|
||||
}
|
||||
}
|
||||
},
|
||||
"relation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"enum": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"hostile",
|
||||
"neutral",
|
||||
"allied"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "hostile"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11458,11 +11771,11 @@
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"example": "0.2.0"
|
||||
"example": "0.3.0"
|
||||
},
|
||||
"api": {
|
||||
"type": "number",
|
||||
"example": 3
|
||||
"example": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11606,6 +11919,167 @@
|
||||
},
|
||||
"defaults": {
|
||||
"$ref": "#/components/schemas/RustNpcProfileBody"
|
||||
},
|
||||
"factions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RustNpcFactionPair"
|
||||
}
|
||||
}
|
||||
},
|
||||
"factionNames": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "The factions the profiles name."
|
||||
},
|
||||
"example": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"bandits",
|
||||
"guards"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"builtInFactions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"scientists",
|
||||
"animals"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"roamer",
|
||||
"sentry",
|
||||
"guard"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"turrets": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"default",
|
||||
"ignore",
|
||||
"always"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kitUses": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"heal",
|
||||
"grenades",
|
||||
"melee",
|
||||
"rockets",
|
||||
"flamethrower"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11947,6 +12421,27 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tether": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "A ZoneManager zone its NPCs never leave (stage 5, D272). The server refuses one it does not have, or that does not hold the spot."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "arena"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user