From 45df79d712e1ebc2e39ca6487efdaf3648f9db03 Mon Sep 17 00:00:00 2001 From: slaguru666 <111923774+slaguru666@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:13:30 +0100 Subject: [PATCH] make-portraits: draw the body plan, not the species MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit portraitSvg read `spec.species` for both the silhouette and the hit-location table. Every creature with a non-human body carries `species: "baseline"` and says what it is in `bodyPlan`, so the guildhall gryphon's own generated portrait described it as "baseline, 7 hit locations" and drew a human figure for an eagle-lion with wings. 48 creatures were affected — 32 quadrupeds and 16 winged. It is the same defect, in the same shape, as the anatomy clause in mj-queue.mjs: that one read `species` where the shape lives in `bodyPlan`, and drew a wingless gryphon. I fixed it there earlier tonight and did not look one file over, in the other tool that draws a creature from its statblock. R-264 settled this rule for the harness — `bodyPlan ?? species` — and build-packs:294 writes it to the actor's speciesProfile. Only two files change on disk, because 46 of the 48 already have hand-drawn plates and are correctly skipped. Those two are martlet and moor_cat, whose Midjourney art has now failed twice, so they are exactly the creatures falling back on the generated figure: martlet is winged with 10 locations and moor_cat quadruped with 8, where both were human before. The other 139 rewrote byte-identically, which is what a deterministic generator should do and is worth knowing. Co-Authored-By: Claude Opus 5 --- art/portraits/martlet.svg | 23 ++++++++------- art/portraits/moor_cat.svg | 36 ++++++++++++----------- packs/weapons/{000014.log => 000006.log} | 0 packs/weapons/CURRENT | 2 +- packs/weapons/MANIFEST-000004 | Bin 0 -> 120 bytes packs/weapons/MANIFEST-000013 | Bin 120 -> 0 bytes tools/make-portraits.mjs | 17 +++++++++-- 7 files changed, 47 insertions(+), 31 deletions(-) rename packs/weapons/{000014.log => 000006.log} (100%) create mode 100644 packs/weapons/MANIFEST-000004 delete mode 100644 packs/weapons/MANIFEST-000013 diff --git a/art/portraits/martlet.svg b/art/portraits/martlet.svg index e0a94b4..3c0dcf4 100644 --- a/art/portraits/martlet.svg +++ b/art/portraits/martlet.svg @@ -1,17 +1,20 @@ The martlet - The martlet — baseline, SIZ 3, 7 hit locations, natural armour 0, antique. Generated by tools/make-portraits.mjs; do not edit by hand. + The martlet — winged, SIZ 3, 10 hit locations, natural armour 0, antique. Generated by tools/make-portraits.mjs; do not edit by hand. - - - - - - - - - + + + + + + + + + + + + diff --git a/art/portraits/moor_cat.svg b/art/portraits/moor_cat.svg index e968f27..6cdbb83 100644 --- a/art/portraits/moor_cat.svg +++ b/art/portraits/moor_cat.svg @@ -1,24 +1,26 @@ The moor cat - The moor cat — baseline, SIZ 14, 7 hit locations, natural armour 2, antique. Generated by tools/make-portraits.mjs; do not edit by hand. + The moor cat — quadruped, SIZ 14, 8 hit locations, natural armour 2, antique. Generated by tools/make-portraits.mjs; do not edit by hand. - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/packs/weapons/000014.log b/packs/weapons/000006.log similarity index 100% rename from packs/weapons/000014.log rename to packs/weapons/000006.log diff --git a/packs/weapons/CURRENT b/packs/weapons/CURRENT index 625d147..cacca75 100644 --- a/packs/weapons/CURRENT +++ b/packs/weapons/CURRENT @@ -1 +1 @@ -MANIFEST-000013 +MANIFEST-000004 diff --git a/packs/weapons/MANIFEST-000004 b/packs/weapons/MANIFEST-000004 new file mode 100644 index 0000000000000000000000000000000000000000..e0cdc92ce4701ad0a5865d08240665a4041b6579 GIT binary patch literal 120 zcmWIhx#Ncn10$nUPHI_dPD+xVQ)NkNd1i5{bAE0?Vo_pAeo^I_9n<|77@62O8JO8w z+}Igd=QT3QD`u9Y<`yd&W>*zdC8reo1!j19n0pm5$}xZeOuj0`wJg6XJEJ19$k)?7 Kx0q1@A`bvRyd!)7 literal 0 HcmV?d00001 diff --git a/packs/weapons/MANIFEST-000013 b/packs/weapons/MANIFEST-000013 deleted file mode 100644 index c0ec63e94e52e6aaf6bb1fd748eb83ea329cdf07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmexix@UC~10$nUPHI_dPD+xVQ)NkNd1i5{bAE0?Vo_pAei1tZ>%2xrdBx0<)ZAi4 z!|bYps^pYnzrYMn4|A^~MmYvBfXP>-xR&KtWoJ}G7WsO*=N2<6K;%CizkQ#Bfsu)i KlYyC^#SH*xxg-Dp diff --git a/tools/make-portraits.mjs b/tools/make-portraits.mjs index b266ea0..8ef8ebc 100644 --- a/tools/make-portraits.mjs +++ b/tools/make-portraits.mjs @@ -250,9 +250,20 @@ function part(shape, attrs) { } export function portraitSvg(spec, kind = "npc") { + /* THE BODY PLAN, not the species — `spec.bodyPlan ?? spec.species`, which is the rule + R-264 settled for the harness and build-packs:294 writes to the actor's + speciesProfile. This read `species` alone, and every creature with a non-baseline + body has `species: "baseline"`: the guildhall gryphon's own generated portrait + described it as "baseline, 7 hit locations" and drew a human silhouette for an + eagle-lion with wings. 48 creatures were affected, 32 quadrupeds and 16 winged. + + The same defect, in the same shape, as the one in mj-queue's anatomy clause — fixed + there earlier and not looked for here, one file away, in the other tool that draws a + creature from its statblock. */ const species = spec.species ?? "baseline"; - const art = BODY_ART[species] ?? BODY_ART.baseline; - const table = LOCATION_TABLES[species] ?? LOCATION_TABLES.baseline; + const plan = spec.bodyPlan ?? species; + const art = BODY_ART[plan] ?? BODY_ART[species] ?? BODY_ART.baseline; + const table = LOCATION_TABLES[plan] ?? LOCATION_TABLES[species] ?? LOCATION_TABLES.baseline; const era = eraOf(spec); const muted = era === "antique"; @@ -329,7 +340,7 @@ export function portraitSvg(spec, kind = "npc") { return ` ${esc(spec.name)} - ${esc(spec.name)} — ${species}, SIZ ${spec.ch?.siz ?? "?"}, ` + ${esc(spec.name)} — ${plan}, SIZ ${spec.ch?.siz ?? "?"}, ` + `${table.locations.length} hit locations, natural armour ${nat}, ${era}. ` + `Generated by tools/make-portraits.mjs; do not edit by hand.