diff --git a/ringbrp.mjs b/ringbrp.mjs index fc19255..a844a68 100644 --- a/ringbrp.mjs +++ b/ringbrp.mjs @@ -4230,6 +4230,16 @@ export async function generateNPC({ it.system = { ...it.system, ammo: { ...it.system.ammo, reserve: (Number(it.system.ammo.capacity) || 0) * 2 } }; } if (items.length) await actor.createEmbeddedDocuments("Item", items); + /* Every skill on the sheet, untrained ones at their printed base. + * + * This was the first thing reported about the generator — "when I create a new NPC or + * Threat they do not have a set of skills" — and it was true in a way the kit fix does + * not cover: a generated NPC carried its posting's core plus two support and nothing + * else, about eight rows, so a GM asked for Listen or Dodge or Spot by a player had + * nothing on the sheet to roll. generateCharacter has called this since it was written + * and build-packs gives all 62 to every packed creature, so the generated NPC was the + * only actor in the game without them. */ + await grantFullSkillList(actor); // Issued is not carried. A Containment officer drawing four gear items should not // begin the fight permanently slower for owning her own breaching charges — the same // reason the PC path calls this. diff --git a/tools/check-generator.mjs b/tools/check-generator.mjs index 0e3dc2b..b0205fe 100644 --- a/tools/check-generator.mjs +++ b/tools/check-generator.mjs @@ -118,7 +118,31 @@ if (typeof drawKitFor === "function") { } } -/* ---------- 4. the engine must actually ask ---------- */ +/* ---------- 4. every path that builds an actor must finish the sheet ---------- */ +{ + const src = await readFile(path.join(ROOT, "ringbrp.mjs"), "utf8"); + /* generateCharacter has called grantFullSkillList since it was written, and + build-packs gives all 62 skills to every packed creature. generateNPC did not, so a + generated adversary carried about eight rows and a GM asked for Listen or Dodge had + nothing on the sheet to roll — the first thing reported about this generator. A + shared finishing step that one of three callers omits is invisible from inside that + caller, which is what makes it worth naming here rather than remembering. */ + for (const fn of ["generateCharacter", "generateNPC", "generateCreature"]) { + const at = src.indexOf(`export async function ${fn}(`); + if (at === -1) { problems.push(`ringbrp.mjs no longer defines ${fn}`); continue; } + const after = src.slice(at + 10); + const ends = [after.indexOf("\nexport "), after.indexOf("\nasync function "), after.indexOf("\nfunction ")] + .filter(i => i !== -1); + const body = after.slice(0, ends.length ? Math.min(...ends) : after.length); + if (!/grantFullSkillList\s*\(/.test(body)) { + problems.push(`${fn} never calls grantFullSkillList — the actor it builds reaches the ` + + `table with only the skills it was explicitly given, and every other actor in the ` + + `game has all 62 with the untrained ones at their printed base`); + } + } +} + +/* ---------- 5. the engine must actually ask for the kit ---------- */ { const src = await readFile(path.join(ROOT, "ringbrp.mjs"), "utf8"); const start = src.indexOf("export async function generateNPC(");