From 87ae980435d8aac330db553c3e4d457198696a2f Mon Sep 17 00:00:00 2001 From: Tim Evans Date: Wed, 15 Jul 2026 13:57:14 +0100 Subject: [PATCH] Add the Bond: 10 animal companions, with sheet support and rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Companions were a single line on the Ranger's edge; now they are a real subsystem, rollable or pickable, with art, tokens and a place on the sheet. - New compendium "companions" (VANITY · Animal Companions): 10 beasts as full NPC actors with painted core artwork, droppable as tokens — wolf, hawk, owl, raven, hound, lynx, serpent, stag, great bat, ram. Each keeps the printed baseline (Grit 3, attacks at 3 dice) and differs in dodge (2-4d), senses and one distinctive trick, plus which companion action it favours. - New d10 roll table, "The Bond — Animal Companions". - Ranger sheet: the companion block is now a card — art, name, kind, attack, dodge, Grit (with a DOWNED flag), its trick, and one-click Help / Harry / Guard (each posting what it does to chat) plus Attack and Dodge rolls. "Roll the Bond" rolls the d10 and binds the beast straight onto the sheet. - template.json: companion gains kind, img, dodge, trick. - Rules updated in both places: §9a in the Draft 13 source (so the in-world journal carries it) and a new Bond section in the player rulebook, which is regenerated to HTML + PDF (39pp). - Version -> 0.9.6; README/FOUNDRY/system description updated (13 compendia). Co-Authored-By: Claude Opus 4.8 --- packs/armour/LOG | 10 +- packs/bestiary/LOG | 10 +- .../000007.log => companions/000004.log} | 0 packs/companions/000005.ldb | Bin 0 -> 4974 bytes packs/companions/CURRENT | 1 + packs/companions/LOCK | 0 packs/companions/LOG | 5 + packs/companions/MANIFEST-000002 | Bin 0 -> 136 bytes packs/edges/LOG | 10 +- packs/gear/LOG | 10 +- packs/gm/LOG | 10 +- packs/pregens/000004.log | 0 packs/pregens/CURRENT | 2 +- packs/pregens/LOG | 8 +- packs/pregens/LOG.old | 5 - packs/pregens/MANIFEST-000002 | Bin 0 -> 161 bytes packs/pregens/MANIFEST-000006 | Bin 146 -> 0 bytes packs/rules/LOG | 10 +- packs/spells/LOG | 10 +- packs/tables/000005.ldb | Bin 12927 -> 15588 bytes packs/tables/LOG | 10 +- packs/tables/MANIFEST-000002 | Bin 161 -> 161 bytes packs/treasure/LOG | 10 +- packs/vices/LOG | 10 +- packs/weapons/LOG | 10 +- styles/vanity.css | 41 +++++- system.json | 11 +- template.json | 127 ++++++++++++++---- templates/character-sheet.hbs | 44 +++++- vanity.mjs | 71 +++++++++- 30 files changed, 316 insertions(+), 109 deletions(-) rename packs/{pregens/000007.log => companions/000004.log} (100%) create mode 100644 packs/companions/000005.ldb create mode 100644 packs/companions/CURRENT create mode 100644 packs/companions/LOCK create mode 100644 packs/companions/LOG create mode 100644 packs/companions/MANIFEST-000002 create mode 100644 packs/pregens/000004.log delete mode 100644 packs/pregens/LOG.old create mode 100644 packs/pregens/MANIFEST-000002 delete mode 100644 packs/pregens/MANIFEST-000006 diff --git a/packs/armour/LOG b/packs/armour/LOG index 0253fb6..96c4366 100644 --- a/packs/armour/LOG +++ b/packs/armour/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.695783 173683000 Delete type=3 #1 -2026/07/15-11:47:01.696366 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.696541 173f1b000 Level-0 table #5: 2618 bytes OK -2026/07/15-11:47:01.696627 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.696697 173f1b000 Manual compaction at level-0 from '!items!GOAakTqMDZSCDOdE' @ 72057594037927935 : 1 .. '!items!vHyUhdri4IKpq9CW' @ 0 : 0; will stop at (end) +2026/07/15-13:54:31.980954 173337000 Delete type=3 #1 +2026/07/15-13:54:31.982902 173bcf000 Level-0 table #5: started +2026/07/15-13:54:31.983101 173bcf000 Level-0 table #5: 2618 bytes OK +2026/07/15-13:54:31.983209 173bcf000 Delete type=0 #3 +2026/07/15-13:54:31.983289 173bcf000 Manual compaction at level-0 from '!items!GOAakTqMDZSCDOdE' @ 72057594037927935 : 1 .. '!items!vHyUhdri4IKpq9CW' @ 0 : 0; will stop at (end) diff --git a/packs/bestiary/LOG b/packs/bestiary/LOG index f9b11c2..c3acce8 100644 --- a/packs/bestiary/LOG +++ b/packs/bestiary/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.788244 173683000 Delete type=3 #1 -2026/07/15-11:47:01.792649 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.792913 173f1b000 Level-0 table #5: 5226 bytes OK -2026/07/15-11:47:01.793011 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.793107 173f1b000 Manual compaction at level-0 from '!actors!351sA95uALULY3Kv' @ 72057594037927935 : 1 .. '!actors!rPfEYHmSoprnQdrY' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.036496 173337000 Delete type=3 #1 +2026/07/15-13:54:32.036915 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.037137 173bcf000 Level-0 table #5: 5226 bytes OK +2026/07/15-13:54:32.037231 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.037330 173bcf000 Manual compaction at level-0 from '!actors!351sA95uALULY3Kv' @ 72057594037927935 : 1 .. '!actors!rPfEYHmSoprnQdrY' @ 0 : 0; will stop at (end) diff --git a/packs/pregens/000007.log b/packs/companions/000004.log similarity index 100% rename from packs/pregens/000007.log rename to packs/companions/000004.log diff --git a/packs/companions/000005.ldb b/packs/companions/000005.ldb new file mode 100644 index 0000000000000000000000000000000000000000..f8b1c0c803fefd3260bac252e33e576981b0e22c GIT binary patch literal 4974 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 literal 0 HcmV?d00001 diff --git a/packs/companions/CURRENT b/packs/companions/CURRENT new file mode 100644 index 0000000..1a84852 --- /dev/null +++ b/packs/companions/CURRENT @@ -0,0 +1 @@ +MANIFEST-000002 diff --git a/packs/companions/LOCK b/packs/companions/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/companions/LOG b/packs/companions/LOG new file mode 100644 index 0000000..456aa5f --- /dev/null +++ b/packs/companions/LOG @@ -0,0 +1,5 @@ +2026/07/15-13:54:32.041086 173337000 Delete type=3 #1 +2026/07/15-13:54:32.041857 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.042052 173bcf000 Level-0 table #5: 4974 bytes OK +2026/07/15-13:54:32.042132 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.042191 173bcf000 Manual compaction at level-0 from '!actors!1FGl7v1mODKvN9fy' @ 72057594037927935 : 1 .. '!actors!yEfKBqSa4GmIgOpx' @ 0 : 0; will stop at (end) diff --git a/packs/companions/MANIFEST-000002 b/packs/companions/MANIFEST-000002 new file mode 100644 index 0000000000000000000000000000000000000000..a1d9e5fff849b716723d2ea62ddf9f2039e05cf7 GIT binary patch literal 136 zcmWIhx#Ncn10$nUPHI_dPD+xVQ)NkNd1i5{bAE0?Vo_pAe$kRS-TOEg7@3$k8JJmE z7#3XJu-_lZWdU;8Sh(1kSl_8BC?+NYRTe86y1D0=ml@{zyLgxRS*BGoGBSVxTtTI4 WnzvJ7aH5HOu4lS`K?NfhL;(OP^CgS` literal 0 HcmV?d00001 diff --git a/packs/edges/LOG b/packs/edges/LOG index 8382459..06e21b5 100644 --- a/packs/edges/LOG +++ b/packs/edges/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.770669 173683000 Delete type=3 #1 -2026/07/15-11:47:01.771135 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.771347 173f1b000 Level-0 table #5: 5417 bytes OK -2026/07/15-11:47:01.771446 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.771504 173f1b000 Manual compaction at level-0 from '!items!21hRQJtWGk5fDQlo' @ 72057594037927935 : 1 .. '!items!zMphj752klzDFU3Q' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.027062 173337000 Delete type=3 #1 +2026/07/15-13:54:32.028202 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.028447 173bcf000 Level-0 table #5: 5417 bytes OK +2026/07/15-13:54:32.028559 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.028646 173bcf000 Manual compaction at level-0 from '!items!21hRQJtWGk5fDQlo' @ 72057594037927935 : 1 .. '!items!zMphj752klzDFU3Q' @ 0 : 0; will stop at (end) diff --git a/packs/gear/LOG b/packs/gear/LOG index e2835ab..c5fd14c 100644 --- a/packs/gear/LOG +++ b/packs/gear/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.714562 173683000 Delete type=3 #1 -2026/07/15-11:47:01.715170 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.715419 173f1b000 Level-0 table #5: 9529 bytes OK -2026/07/15-11:47:01.715518 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.715585 173f1b000 Manual compaction at level-0 from '!items!27LcrYsIEEF3KYHA' @ 72057594037927935 : 1 .. '!items!yo48EzCVEwNdpkXF' @ 0 : 0; will stop at (end) +2026/07/15-13:54:31.993791 173337000 Delete type=3 #1 +2026/07/15-13:54:31.994306 173bcf000 Level-0 table #5: started +2026/07/15-13:54:31.994579 173bcf000 Level-0 table #5: 9529 bytes OK +2026/07/15-13:54:31.994675 173bcf000 Delete type=0 #3 +2026/07/15-13:54:31.994726 173bcf000 Manual compaction at level-0 from '!items!27LcrYsIEEF3KYHA' @ 72057594037927935 : 1 .. '!items!yo48EzCVEwNdpkXF' @ 0 : 0; will stop at (end) diff --git a/packs/gm/LOG b/packs/gm/LOG index 7ff5688..cb20875 100644 --- a/packs/gm/LOG +++ b/packs/gm/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.833917 173683000 Delete type=3 #1 -2026/07/15-11:47:01.834447 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.834747 173f1b000 Level-0 table #5: 10149 bytes OK -2026/07/15-11:47:01.834842 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.834916 173f1b000 Manual compaction at level-0 from '!journal!JJEgDJvtWBnFbyZA' @ 72057594037927935 : 1 .. '!journal.pages!kBclT2QiwEQmOsX1.HSVD8c7BenQjb45v' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.071464 173337000 Delete type=3 #1 +2026/07/15-13:54:32.071868 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.072129 173bcf000 Level-0 table #5: 10149 bytes OK +2026/07/15-13:54:32.072216 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.072285 173bcf000 Manual compaction at level-0 from '!journal!JJEgDJvtWBnFbyZA' @ 72057594037927935 : 1 .. '!journal.pages!kBclT2QiwEQmOsX1.HSVD8c7BenQjb45v' @ 0 : 0; will stop at (end) diff --git a/packs/pregens/000004.log b/packs/pregens/000004.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/pregens/CURRENT b/packs/pregens/CURRENT index f7753e2..1a84852 100644 --- a/packs/pregens/CURRENT +++ b/packs/pregens/CURRENT @@ -1 +1 @@ -MANIFEST-000006 +MANIFEST-000002 diff --git a/packs/pregens/LOG b/packs/pregens/LOG index 48e0b27..d1dcead 100644 --- a/packs/pregens/LOG +++ b/packs/pregens/LOG @@ -1,3 +1,5 @@ -2026/07/15-11:47:22.058812 172c77000 Recovering log #4 -2026/07/15-11:47:22.059752 172c77000 Delete type=0 #4 -2026/07/15-11:47:22.059797 172c77000 Delete type=3 #2 +2026/07/15-13:54:32.058937 173337000 Delete type=3 #1 +2026/07/15-13:54:32.060571 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.061856 173bcf000 Level-0 table #5: 120604 bytes OK +2026/07/15-13:54:32.061959 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.062074 173bcf000 Manual compaction at level-0 from '!actors!3Kjqu9ibyf8TjSrk' @ 72057594037927935 : 1 .. '!actors.items!zR0OZzFsVQLTSlBM.uc6AKpWyZeREAX2M' @ 0 : 0; will stop at (end) diff --git a/packs/pregens/LOG.old b/packs/pregens/LOG.old deleted file mode 100644 index 7af2515..0000000 --- a/packs/pregens/LOG.old +++ /dev/null @@ -1,5 +0,0 @@ -2026/07/15-11:47:01.820316 173683000 Delete type=3 #1 -2026/07/15-11:47:01.821872 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.824245 173f1b000 Level-0 table #5: 120604 bytes OK -2026/07/15-11:47:01.824415 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.824651 173f1b000 Manual compaction at level-0 from '!actors!3Kjqu9ibyf8TjSrk' @ 72057594037927935 : 1 .. '!actors.items!zR0OZzFsVQLTSlBM.uc6AKpWyZeREAX2M' @ 0 : 0; will stop at (end) diff --git a/packs/pregens/MANIFEST-000002 b/packs/pregens/MANIFEST-000002 new file mode 100644 index 0000000000000000000000000000000000000000..2e5217252d52b20d8fdeee6ea1f792f4de817d28 GIT binary patch literal 161 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 delta 5214 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 diff --git a/packs/tables/LOG b/packs/tables/LOG index d6a9262..7742562 100644 --- a/packs/tables/LOG +++ b/packs/tables/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.839105 173683000 Delete type=3 #1 -2026/07/15-11:47:01.839563 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.839866 173f1b000 Level-0 table #5: 12927 bytes OK -2026/07/15-11:47:01.839954 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.840012 173f1b000 Manual compaction at level-0 from '!tables!JEOcxCxjK6S6pVEZ' @ 72057594037927935 : 1 .. '!tables.results!rurx5ZPcPObdbNDD.bWBU56ZArkeat9DO' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.076783 173337000 Delete type=3 #1 +2026/07/15-13:54:32.077935 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.078454 173bcf000 Level-0 table #5: 15588 bytes OK +2026/07/15-13:54:32.078562 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.078643 173bcf000 Manual compaction at level-0 from '!tables!JEOcxCxjK6S6pVEZ' @ 72057594037927935 : 1 .. '!tables.results!rurx5ZPcPObdbNDD.bWBU56ZArkeat9DO' @ 0 : 0; will stop at (end) diff --git a/packs/tables/MANIFEST-000002 b/packs/tables/MANIFEST-000002 index 3ebedcdc534aa3f2fc4381b9d6be6827ad1f024c..d931d389f9ef5a0b6c721ccf9e48689129ed690a 100644 GIT binary patch delta 38 qcmZ3;xR7yzk;sjVn^qYNj7%(?49sjSzU)k_Pbw$6g|PcDfB^u*5C|y% delta 38 qcmZ3;xR7yzk%+Um(U%McMkW?c24*%ECw3;*|0xsQLf9P{zyJWQX9s!! diff --git a/packs/treasure/LOG b/packs/treasure/LOG index 4d11fef..9b80c57 100644 --- a/packs/treasure/LOG +++ b/packs/treasure/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.747896 173683000 Delete type=3 #1 -2026/07/15-11:47:01.748609 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.748977 173f1b000 Level-0 table #5: 27619 bytes OK -2026/07/15-11:47:01.749069 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.749125 173f1b000 Manual compaction at level-0 from '!items!0NDwQbhQQNeCCEco' @ 72057594037927935 : 1 .. '!items!yxds1AZFNXBpERdk' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.011854 173337000 Delete type=3 #1 +2026/07/15-13:54:32.012716 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.013114 173bcf000 Level-0 table #5: 27619 bytes OK +2026/07/15-13:54:32.013198 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.013256 173bcf000 Manual compaction at level-0 from '!items!0NDwQbhQQNeCCEco' @ 72057594037927935 : 1 .. '!items!yxds1AZFNXBpERdk' @ 0 : 0; will stop at (end) diff --git a/packs/vices/LOG b/packs/vices/LOG index 6584688..de7d94f 100644 --- a/packs/vices/LOG +++ b/packs/vices/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.775377 173683000 Delete type=3 #1 -2026/07/15-11:47:01.775829 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.776000 173f1b000 Level-0 table #5: 1461 bytes OK -2026/07/15-11:47:01.776104 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.776160 173f1b000 Manual compaction at level-0 from '!items!7kO3VzfFPt8QRVXT' @ 72057594037927935 : 1 .. '!items!s50CZgFUaS5puSOp' @ 0 : 0; will stop at (end) +2026/07/15-13:54:32.031270 173337000 Delete type=3 #1 +2026/07/15-13:54:32.031615 173bcf000 Level-0 table #5: started +2026/07/15-13:54:32.031760 173bcf000 Level-0 table #5: 1461 bytes OK +2026/07/15-13:54:32.031837 173bcf000 Delete type=0 #3 +2026/07/15-13:54:32.031883 173bcf000 Manual compaction at level-0 from '!items!7kO3VzfFPt8QRVXT' @ 72057594037927935 : 1 .. '!items!s50CZgFUaS5puSOp' @ 0 : 0; will stop at (end) diff --git a/packs/weapons/LOG b/packs/weapons/LOG index 445264c..0379668 100644 --- a/packs/weapons/LOG +++ b/packs/weapons/LOG @@ -1,5 +1,5 @@ -2026/07/15-11:47:01.686516 173683000 Delete type=3 #1 -2026/07/15-11:47:01.688737 173f1b000 Level-0 table #5: started -2026/07/15-11:47:01.688968 173f1b000 Level-0 table #5: 7415 bytes OK -2026/07/15-11:47:01.689074 173f1b000 Delete type=0 #3 -2026/07/15-11:47:01.689142 173f1b000 Manual compaction at level-0 from '!items!0d6FZCtl78jEPkof' @ 72057594037927935 : 1 .. '!items!v3IghflF7cI2FzbU' @ 0 : 0; will stop at (end) +2026/07/15-13:54:31.973874 173337000 Delete type=3 #1 +2026/07/15-13:54:31.975860 173bcf000 Level-0 table #5: started +2026/07/15-13:54:31.976110 173bcf000 Level-0 table #5: 7415 bytes OK +2026/07/15-13:54:31.976203 173bcf000 Delete type=0 #3 +2026/07/15-13:54:31.976263 173bcf000 Manual compaction at level-0 from '!items!0d6FZCtl78jEPkof' @ 72057594037927935 : 1 .. '!items!v3IghflF7cI2FzbU' @ 0 : 0; will stop at (end) diff --git a/styles/vanity.css b/styles/vanity.css index 3421029..9801c2e 100644 --- a/styles/vanity.css +++ b/styles/vanity.css @@ -425,10 +425,43 @@ /* ---------------- Companion ---------------- */ -.vanity-sheet .companion-grid { display: grid; grid-template-columns: 2fr 1fr 1.4fr auto; gap: 10px; align-items: end; } -.vanity-sheet .companion-grid .wide { grid-column: 1 / -1; } -.vanity-sheet .companion-grid input[type="number"] { width: 44px; text-align: center; } -.vanity-sheet .companion-roll { padding: 5px 12px; } +.vanity-sheet .companion-card { display: flex; gap: 12px; align-items: flex-start; } +.vanity-sheet .cmp-art { + flex: none; width: 92px; height: 92px; border-radius: 6px; overflow: hidden; + border: 1.5px solid var(--v-gold); background: var(--v-paper2); +} +.vanity-sheet .cmp-art img { width: 100%; height: 100%; object-fit: cover; display: block; } +.vanity-sheet .cmp-art-empty { + width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; + color: var(--v-line); font-size: 30px; +} +.vanity-sheet .cmp-body { flex: 1; display: flex; flex-direction: column; gap: 7px; min-width: 0; } +.vanity-sheet .cmp-line { display: flex; gap: 10px; align-items: end; } +.vanity-sheet .cmp-line .grow { flex: 1; min-width: 0; } +.vanity-sheet .companion-card input[type="number"] { width: 42px; text-align: center; } +.vanity-sheet .companion-card .sl { color: var(--v-ink2); padding: 0 2px; } +.vanity-sheet .companion-card .wide { width: 100%; } +.vanity-sheet .cmp-downed { + font-family: "Cinzel", Georgia, serif; font-size: 9px; letter-spacing: .1em; + color: #fff; background: #8a2f2f; border-radius: 8px; padding: 2px 8px; align-self: center; +} +.vanity-sheet .cmp-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } +.vanity-sheet .cmp-actions .cap { width: 100%; margin-bottom: 1px; } +.vanity-sheet .cmp-act, .vanity-sheet .cmp-roll { + padding: 4px 10px; font-size: 11px; border: 1.3px solid var(--v-line); + border-radius: 12px; background: var(--v-paper2); cursor: pointer; white-space: nowrap; +} +.vanity-sheet .cmp-act b { color: var(--v-teal); font-weight: 600; } +.vanity-sheet .cmp-act:hover, .vanity-sheet .cmp-roll:hover { + border-color: var(--v-gold); background: rgba(176,135,47,.10); +} +.vanity-sheet .cmp-roll { border-color: var(--v-teal); color: var(--v-teal-d); } +.vanity-sheet .cmp-bond { + float: right; margin: -2px 0 0; padding: 2px 9px; font-size: 10px; + border: 1.2px solid var(--v-gold); border-radius: 10px; background: transparent; + color: var(--v-paper); cursor: pointer; +} +.vanity-sheet .cmp-bond:hover { background: rgba(255,255,255,.14); } /* ---------------- NPC sheet ---------------- */ diff --git a/system.json b/system.json index b8358a9..399d0d7 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "vanity", "title": "VANITY — the Vanity Role-Playing Game", - "description": "A generic d6 RPG where ego is a resource and the universe keeps score. Pool = Attribute + Knack + situation; 5–6 = a Success; fail with two 1s = a Stumble that banks a Bane of Karma (Draft 13). No hit points — Grit. Vanity, Karma and Glory drive play. Includes the full Draft 13 rulebook, all spells and gear, the starter bestiary, a 100-item Treasures & Relics library, twenty ready-to-play characters (each with cameo art, token and backstory) and the one-shot adventure The Vain Crown.", - "version": "0.9.5", + "description": "A generic d6 RPG where ego is a resource and the universe keeps score. Pool = Attribute + Knack + situation; 5–6 = a Success; fail with two 1s = a Stumble that banks a Bane of Karma (Draft 13). No hit points — Grit. Vanity, Karma and Glory drive play. Includes the full Draft 13 rulebook, all spells and gear, the starter bestiary, a 100-item Treasures & Relics library, twenty ready-to-play characters (each with cameo art, token and backstory), ten animal companions with the d10 Bond table and the one-shot adventure The Vain Crown.", + "version": "0.9.6", "compatibility": { "minimum": 13, "verified": "14.364" @@ -90,6 +90,13 @@ "type": "Actor", "system": "vanity" }, + { + "name": "companions", + "label": "VANITY · Animal Companions", + "path": "packs/companions", + "type": "Actor", + "system": "vanity" + }, { "name": "pregens", "label": "VANITY · Ready-to-Play Characters", diff --git a/template.json b/template.json index 5cf2d77..8e89fed 100644 --- a/template.json +++ b/template.json @@ -1,27 +1,65 @@ { "Actor": { - "types": ["character", "npc"], + "types": [ + "character", + "npc" + ], "character": { "attributes": { - "brawn": { "value": 2 }, - "flair": { "value": 2 }, - "wits": { "value": 2 }, - "poise": { "value": 2 } + "brawn": { + "value": 2 + }, + "flair": { + "value": 2 + }, + "wits": { + "value": 2 + }, + "poise": { + "value": 2 + } + }, + "grit": { + "value": 8, + "max": 8 + }, + "vanity": { + "value": 3 + }, + "karma": { + "value": 0 + }, + "glory": { + "value": 0 }, - "grit": { "value": 8, "max": 8 }, - "vanity": { "value": 3 }, - "karma": { "value": 0 }, - "glory": { "value": 0 }, "knacks": { - "fight": { "rank": 0 }, - "shoot": { "rank": 0 }, - "athletics": { "rank": 0 }, - "stealth": { "rank": 0 }, - "notice": { "rank": 0 }, - "lore": { "rank": 0 }, - "survive": { "rank": 0 }, - "charm": { "rank": 0 }, - "command": { "rank": 0 } + "fight": { + "rank": 0 + }, + "shoot": { + "rank": 0 + }, + "athletics": { + "rank": 0 + }, + "stealth": { + "rank": 0 + }, + "notice": { + "rank": 0 + }, + "lore": { + "rank": 0 + }, + "survive": { + "rank": 0 + }, + "charm": { + "rank": 0 + }, + "command": { + "rank": 0 + } }, "locked": { "name": "", @@ -32,12 +70,23 @@ "class": "", "concept": "", "fightingStyle": "", - "coin": { "cp": 0, "sp": 0, "gp": 15 } + "coin": { + "cp": 0, + "sp": 0, + "gp": 15 + } }, "companion": { "name": "", - "grit": { "value": 3, "max": 3 }, + "kind": "", + "img": "", + "grit": { + "value": 3, + "max": 3 + }, "pool": 3, + "dodge": 3, + "trick": "", "notes": "" }, "notes": "", @@ -45,18 +94,42 @@ }, "npc": { "category": "mook", - "attack1": { "name": "Attack", "pool": 3, "note": "" }, - "attack2": { "name": "", "pool": 0, "note": "" }, - "defence": { "pool": 2, "note": "" }, - "grit": { "value": 1, "max": 1 }, - "resolve": { "value": 0, "max": 0 }, + "attack1": { + "name": "Attack", + "pool": 3, + "note": "" + }, + "attack2": { + "name": "", + "pool": 0, + "note": "" + }, + "defence": { + "pool": 2, + "note": "" + }, + "grit": { + "value": 1, + "max": 1 + }, + "resolve": { + "value": 0, + "max": 0 + }, "nerve": 2, "trick": "", "notes": "" } }, "Item": { - "types": ["weapon", "armour", "gear", "spell", "edge", "vice"], + "types": [ + "weapon", + "armour", + "gear", + "spell", + "edge", + "vice" + ], "weapon": { "dice": 0, "hands": 1, @@ -98,4 +171,4 @@ "description": "" } } -} +} \ No newline at end of file diff --git a/templates/character-sheet.hbs b/templates/character-sheet.hbs index 5234d1f..a187be5 100644 --- a/templates/character-sheet.hbs +++ b/templates/character-sheet.hbs @@ -273,13 +273,43 @@ {{!-- ============ TAB: STORY ============ --}}
-
Companion
-
- - - - - +
Companion — the Bond + +
+
+
+ {{#if sys.companion.img}}{{sys.companion.name}} + {{else}}
{{/if}} +
+
+
+ + +
+
+ + + + {{#if companionDowned}}DOWNED — not dead{{/if}} +
+ +
+ Each round, one action + + + + + +
+
diff --git a/vanity.mjs b/vanity.mjs index 97c3125..d892463 100644 --- a/vanity.mjs +++ b/vanity.mjs @@ -633,6 +633,8 @@ class VanityActorSheet extends foundry.appv1.sheets.ActorSheet { items: ctx.conditions.filter(c => c.group === g) })); ctx.activeConditions = ctx.conditions.filter(c => c.active); + const cmp = this.actor.system.companion; + ctx.companionDowned = !!cmp?.name && (cmp.grit?.value ?? 3) <= 0; ctx.focusCond = this._focusCond ? ctx.conditions.find(c => c.id === this._focusCond) ?? null : null; @@ -881,11 +883,69 @@ class VanityActorSheet extends foundry.appv1.sheets.ActorSheet { this.render(false); }); - // Companion roll - html.find(".companion-roll").click(() => { - const c = actor.system.companion; - if (!c?.name) return; - promptAndRoll(actor, { title: `${c.name} (companion)`, base: c.pool || 3, baseLabel: `Companion pool ${c.pool || 3}` }); + // Companion — attack / dodge + html.find(".cmp-roll").click(ev => { + const c = actor.system.companion ?? {}; + const name = c.name || "The companion"; + if (ev.currentTarget.dataset.roll === "dodge") { + return promptAndRoll(actor, { title: `${name} — dodges`, base: c.dodge || 3, + baseLabel: `Companion dodge ${c.dodge || 3}` }); + } + return promptAndRoll(actor, { title: `${name} — attacks`, base: c.pool || 3, + baseLabel: `Companion pool ${c.pool || 3}`, options: { context: "attack" } }); + }); + + // Companion — Help · Harry · Guard (one action a round) + html.find(".cmp-act").click(async ev => { + const c = actor.system.companion ?? {}; + const name = c.name || "The companion"; + const kind = c.kind ? ` the ${c.kind}` : ""; + const ACTS = { + help: ["Help", "+1 die", + `${name}${kind} flanks, flushes or calls the shot — ${actor.name} gains +1 die on their next roll this round.`], + harry: ["Harry", "−1 die", + `${name}${kind} worries the foe — that foe takes −1 die, and ${actor.name} may treat it as flanked for Ambush-style shots.`], + guard: ["Guard", "reaction", + `${name}${kind} throws itself in the way — it intercepts one hit meant for ${actor.name}. That is the companion's reaction this round.`], + }; + const [label, tag, text] = ACTS[ev.currentTarget.dataset.act] ?? []; + if (!label) return; + await ChatMessage.create({ + speaker: ChatMessage.getSpeaker({ actor }), + content: `
+
🐾 ${label} — ${tag} + ${name}${kind} · the companion's action this round
+

${text}

+ ${c.trick ? `

Trick: ${c.trick}

` : ""} +
` + }); + }); + + // Companion — roll the Bond (d10) and bind the beast to the sheet + html.find(".cmp-bond").click(async () => { + const table = await getVanityTable(BOND_TABLE_NAME); + if (!table) return ui.notifications.error(`"${BOND_TABLE_NAME}" not found in world or compendium.`); + const roll = new Roll("1d10"); + await roll.evaluate(); + lockVanityDice(roll); + if (game.dice3d) await game.dice3d.showForRoll(roll, game.user, true).catch(() => {}); + const results = table.getResultsForRoll(roll.total); + await table.toMessage(results, { roll }); + + // Bind it: pull the matching beast from the companions compendium. + const kind = (results?.[0]?.name ?? "").split("—")[0].trim(); + const beast = (await packDocs("companions")).find(d => d.name === `${kind} (companion)`); + if (!beast) return; + await actor.update({ + "system.companion.kind": kind.toLowerCase(), + "system.companion.img": beast.img, + "system.companion.pool": beast.system.attack1?.pool ?? 3, + "system.companion.dodge": beast.system.defence?.pool ?? 3, + "system.companion.trick": beast.system.trick ?? "", + "system.companion.grit.value": beast.system.grit?.max ?? 3, + "system.companion.grit.max": beast.system.grit?.max ?? 3, + }); + ui.notifications.info(`The Bond: a ${kind.toLowerCase()}. Name it — the table will be shouting that name soon enough.`); }); } } @@ -1019,6 +1079,7 @@ Hooks.on("diceSoNiceRollStart", (messageId, context) => { const TWIST_TABLE_NAME = "Twist the Knife — spending Banes (d66)"; const RECKONING_TABLE_NAME = "THE RECKONING — the tab reads six (2d6)"; +const BOND_TABLE_NAME = "The Bond — Animal Companions (d10)"; async function getVanityTable(name) { let table = game.tables.getName(name);