From f1a61296e861b164e885abec3fa02889509a97cc Mon Sep 17 00:00:00 2001 From: MedievalSteve Date: Mon, 28 Oct 2024 10:25:58 +1000 Subject: [PATCH] Update to sheet version 2.0 Added new image files for dice buttons. Completely reworked HTML, CSS. Updated sheet.json --- Dragon Warriors/Dragon Warriors Revised.css | 4811 +++--- Dragon Warriors/Dragon Warriors Revised.html | 14247 ++++++++++++++--- Dragon Warriors/d12.jpg | Bin 0 -> 2247 bytes Dragon Warriors/d4.jpg | Bin 0 -> 1523 bytes Dragon Warriors/d6.jpg | Bin 0 -> 1479 bytes Dragon Warriors/d8.jpg | Bin 0 -> 1584 bytes Dragon Warriors/sheet.json | 2 +- Dragon Warriors/twod10.jpg | Bin 0 -> 6635 bytes 8 files changed, 15045 insertions(+), 4015 deletions(-) create mode 100644 Dragon Warriors/d12.jpg create mode 100644 Dragon Warriors/d4.jpg create mode 100644 Dragon Warriors/d6.jpg create mode 100644 Dragon Warriors/d8.jpg create mode 100644 Dragon Warriors/twod10.jpg diff --git a/Dragon Warriors/Dragon Warriors Revised.css b/Dragon Warriors/Dragon Warriors Revised.css index cf8b9002a441..c216cbaa0545 100644 --- a/Dragon Warriors/Dragon Warriors Revised.css +++ b/Dragon Warriors/Dragon Warriors Revised.css @@ -1,186 +1,297 @@ -@import url("https://fonts.googleapis.com/css?family=Almendra|Almendra+SC&display=swap"); +/* Import Google Fonts for Almendra and Almendra SC */ +@import url('https://fonts.googleapis.com/css?family=Almendra+SC|Macondo|Cormorant+Unicase&display=swap'); -* { - box-sizing: border-box; - font-family: 'Almendra SC', serif; - font-size: medium; - padding: 1px; +/* Option 1: CSS Variables for consistency and easier future adjustments */ +:root { + --bg-color: #F5F5F5; /* Background color for inputs, textareas, etc. */ + --primary-bg-color: #DCDCDC; /* Primary background color for divs */ + --padding: 2px; + --border-radius: 3px; + --border-color: #a8a8a8; + --hover-bg-color: #e0e0e0; + --hover-border-color: #888; } -select { - width: auto; - background-color: #F5F5F5; + +/* Global styling */ +* { + box-sizing: border-box; + font-family: 'Almendra SC', serif; + font-size: 18px; + padding: var(--padding); } -textarea { - display: block; - width: 98%; - resize: vertical; - height: fit-content 100%; - background-color: #F5F5F5; - margin-left: auto; - margin-right: auto; - overflow: auto; + +/* Specifying Macondo for specific elements */ +.ui-dialog .charsheet p { + font-family: 'Cormorant Unicase', serif; } -textarea.sheet-shorttextarea { - display: block; - width: 98%; - resize: vertical; - height: auto; - background-color: #F5F5F5; - margin-left: auto; - margin-right: auto; - overflow: auto; + +/* Default styling for labels */ +.ui-dialog .charsheet label { + font-size: 16px; + color: #333; /* Dark gray for better readability */ + margin-bottom: 2px; /* Space between label and input */ } -input.sheet-number { - background-color: #F5F5F5; + +/* Ensuring inputs inherit font size */ +.ui-dialog .charsheet input[type="text"], +.ui-dialog .charsheet input[type="number"], +.ui-dialog .charsheet select { + background-color: var(--bg-color); /* Use the background color variable */ + border: 1px solid var(--border-color); /* Ensure inputs have border */ + border-radius: var(--border-radius); /* Matching border radius */ + padding: var(--padding); /* Consistent padding */ + font-size: inherit; /* Inherit font size from the root */ + box-sizing: border-box; } -input.sheet-text { - background-color: #F5F5F5; + +.sheet-auto-expand { + position: relative; + cursor: text; + word-wrap: break-word; + border: 1px solid var(--border-color); /* Ensure inputs have border */ + border-radius: var(--border-radius); /* Matching border radius */ + padding: var(--padding); /* Consistent padding */ + font-size: inherit; /* Inherit font size from the root */ + font-family: 'Cormorant Unicase', serif; + min-height:3em; } -span { - font-size: medium; + +.sheet-auto-expand span { + visibility: hidden; + white-space: pre-wrap; + display: block; } -label { - font-size: medium; + +.sheet-auto-expand textarea { + position: absolute; + z-index: 1; + top: 0; + left: 0; + margin: 0; + overflow: hidden; + resize: none; + height: 100%; + width: 100%; + display: block; + box-sizing: border-box; + background: transparent; + background-color: var(--bg-color); /* Use the background color variable */ + border: none; + border-radius: 0; + box-shadow: none; + color: inherit; + font: inherit; + letter-spacing: inherit; + padding: inherit; + text-align: inherit; + text-transform: inherit; } -label.sheet-subtext { - font-size: small; + +/* Styling for classes */ +.ui-dialog .charsheet .subtext { + font-size: 16px; align-self: flex-end; } -label.sheet-boxheading { - font-size: large; + +.ui-dialog .charsheet .larger { + font-size: 19px; font-weight: bold; - text-align: center; } -label.sheet-larger { - font-size: larger; - font-weight: bold; + +/* Input width based on size */ +.ui-dialog .charsheet .flexitextinput { + width: 98%; } -span.sheet-boxheading { - font-size: large; - font-weight: bold; - text-align: center; + +.ui-dialog .charsheet .fourshorttextinput { + width: 4em; } -input.sheet-flexitextinput { - width: 98%; - background-color: #F5F5F5; + +.ui-dialog .charsheet .sixshorttextinput { + width: 6em; } -input.sheet-fourshorttextinput { - width: 4em; - background-color: #F5F5F5; + +.ui-dialog .charsheet .eightmidtextinput { + width: 8em; } -input.sheet-eightmidtextinput { - width: 8em; - background-color: #F5F5F5; + +.ui-dialog .charsheet .twelvemidlongtextinput { + width: 12em; } -input.sheet-twelvemidlongtextinput { - width: 16em; - background-color: #F5F5F5; + +.ui-dialog .charsheet .fourteenlongtextinput { + width: 14em; } -input.sheet-sixteenlongtextinput { - width: 16em; - background-color: #F5F5F5; + +.ui-dialog .charsheet .sixteenlongtextinput { + width: 16em; } -label.sheet-centerlabel { - text-align:center; + +/* Label text alignment */ +.ui-dialog .charsheet .centerlabel { + text-align: center; } -label.sheet-justifylabel { - text-align:justify; + +.ui-dialog .charsheet .justifylabel { + text-align: justify; } -button[type="roll"].sheet-d20:before{ - content: ' '; +/* Option 2: Focus styling for accessibility */ +.ui-dialog .charsheet input:focus, +.ui-dialog .charsheet textarea:focus, +.ui-dialog .charsheet button:focus, +.ui-dialog .charsheet select:focus { + /* outline: 2px solid var(--hover-border-color);*/ + background-color: var(--hover-bg-color); } -button[type="roll"].sheet-d20:hover{ - background-position: 0; + +/* General styling for details and summary elements */ +.ui-dialog .charsheet details summary { + font-family: 'Almendra SC', serif; + padding: 10px 15px; + background-color: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + cursor: pointer; + margin: 0; + outline: none; + text-align: center; + width: 98%; + transition: background-color 0.3s, border-color 0.3s; + font-weight: normal; } -button[type="roll"].sheet-d20{ - background-image: url(https://i.imgur.com/JQC7jDf.jpg); + +.ui-dialog .charsheet details summary.bigbolddetails { + font-weight: bold; + font-size: larger; + background-color: var(--hover-bg-color); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + cursor: pointer; +} + +/* Hover effects for details/summary */ +.ui-dialog .charsheet details summary:hover, +.ui-dialog .charsheet details summary:focus, +.ui-dialog .charsheet details summary.bigbolddetails:hover { + background-color: var(--hover-bg-color); + border-color: var(--hover-border-color); +} + +/* Button styling */ +.ui-dialog .charsheet button[type=roll]::before { + content: "" !important; +} + +.ui-dialog .charsheet button.d20, +.ui-dialog .charsheet button.twod10, +.ui-dialog .charsheet button.d4, +.ui-dialog .charsheet button.d8, +.ui-dialog .charsheet button.d12, +.ui-dialog .charsheet button.d6 { background-size: 26px 26px; background-repeat: no-repeat; + background-position: center; width: 26px; height: 26px; - border-style: none; + border: none; background-color: transparent; - margin-left: 5px; -} -button.sheet-d20 { - background-image: url(https://i.imgur.com/JQC7jDf.jpg); - background-size: 30px 30px; - background-repeat: no-repeat; - width: 30px; - height: 30px; + margin: 5px; + cursor: pointer; + transition: none !important; + transform: none !important; } -button.sheet-update { - padding: 2px; - margin-top: 3px; + +/* Hover reset for button images */ +.ui-dialog .charsheet button.d20:hover, +.ui-dialog .charsheet button.twod10:hover, +.ui-dialog .charsheet button.d12:hover, +.ui-dialog .charsheet button.d8:hover, +.ui-dialog .charsheet button.d4:hover, +.ui-dialog .charsheet button.d6:hover { + background-color: transparent; + background-position: center; + cursor: pointer; + transition: none !important; + transform: none !important; } -img.sheet-headerimage { - width: 100%; + +.ui-dialog .charsheet button.d12 { + background-image: url(https://i.imgur.com/1JXzzm7.jpeg); /* Sets the background image for the button */; } -img.sheet-imgbackpack { - display: block; - margin-left: auto; - margin-right: auto; - width: 45%; + +.ui-dialog .charsheet button.d8 { + background-image: url(https://i.imgur.com/YcP84zl.jpeg); /* Sets the background image for the button */; } -img.sheet-imgchest { - display: block; - margin-left: auto; - margin-right: auto; - width: 50%; + +.ui-dialog .charsheet button.twod10 { + background-image: url(https://i.imgur.com/pqfUDrV.jpg); /* Sets the background image for the button */; } -img.sheet-imghand { - display: inline-block; - width: 40px px; - height: 25px; + +.ui-dialog .charsheet button.d20 { + background-image: url(https://i.imgur.com/JQC7jDf.jpg); /* Sets the background image for the button */; } -img.sheet-imghanda { - display: inline-block; - width: 40px px; - height: 25px; - transform: scaleX(-1); +.ui-dialog .charsheet button.d6 { + background-image: url(https://i.imgur.com/f9a64YX.jpeg); /* Sets the background image for the button */; } -img.sheet-skullimg { - display: block; - margin-left: auto; - margin-right: auto; - width: 90%; + +.ui-dialog .charsheet button.d4 { + background-image: url(https://i.imgur.com/0DpGQH7.jpeg); /* Sets the background image for the button */; } -img.sheet-elementimage { - display: block; + +/* Option 5: Refactor Image Class Names */ +.ui-dialog .charsheet img.icon { margin-left: auto; margin-right: auto; - width: 50%; } -img.sheet-imgsword { - display: block; - margin-left: auto; - margin-right: auto; - width: 60%; + +/* Specific image class styles */ +.ui-dialog .charsheet img.icon.backpack { + width: 45%; } -img.sheet-imgbow { - display: block; - transform: rotate(120deg); - margin-left: auto; - margin-right: auto; - width: 30%; + +.ui-dialog .charsheet img.icon.chest { + width: 98%; + height: auto; } -img.sheet-imgshield { - width: 98%; + +.ui-dialog .charsheet img.icon.shield { + width: 98%; } -img.sheet-riderimg { - display: block; - margin-left: auto; - margin-right: auto; + +.ui-dialog .charsheet img.icon.hand, +.ui-dialog .charsheet img.icon.handa { + width: 40px; + height: 25px; +} + +.ui-dialog .charsheet img.icon.handa { + transform: scaleX(-1); /* Flip horizontally */ +} + +.ui-dialog .charsheet img.icon.skull, +.ui-dialog .charsheet img.icon.rider { width: 90%; } -img.sheet-liftclaw { - display: block; - margin-left: auto; - margin-right: auto; + +.ui-dialog .charsheet img.icon.liftclaw { width: 45%; } + +/* Styling for header images */ +.ui-dialog .charsheet img.headerimage { + width: 100%; +} + +.ui-dialog .charsheet img.icon.sword { + width: 60%; +} +/* Additional image styling */ +.ui-dialog .charsheet img.icon.bow { + transform: rotate(180deg); +} + /* Configure the 'radio' button styling for health and magic point trackers. */ -button.sheet-sdot { +.ui-dialog .charsheet button.sdot { padding: 0; border: solid 1px #a8a8a8; margin-left: 6px; @@ -193,7 +304,8 @@ button.sheet-sdot { justify-content: center; align-items: center; } -button.sheet-sdot > span { + +.ui-dialog .charsheet button.sdot > span { width: 20px; height: 20px; border-radius: 50%; @@ -202,7 +314,8 @@ button.sheet-sdot > span { background-size: 80%; background-position: center center; } -button.sheet-wtdot { + +.ui-dialog .charsheet button.wtdot { padding: 0; border: solid 1px #a8a8a8; margin-left: 6px; @@ -215,7 +328,8 @@ button.sheet-wtdot { justify-content: center; align-items: center; } -button.sheet-wtdot > span { + +.ui-dialog .charsheet button.wtdot > span { width: 20px; height: 20px; border-radius: 50%; @@ -224,7 +338,8 @@ button.sheet-wtdot > span { background-size: 80%; background-position: center center; } -button.sheet-mdot { + +.ui-dialog .charsheet button.mdot { padding: 0; border: solid 1px #a8a8a8; margin-left: 6px; @@ -237,7 +352,8 @@ button.sheet-mdot { justify-content: center; align-items: center; } -button.sheet-mdot > span { + +.ui-dialog .charsheet button.mdot > span { width: 20px; height: 20px; border-radius: 50%; @@ -246,7 +362,8 @@ button.sheet-mdot > span { background-size: 90%; background-position: center; } -button.sheet-m2dot { + +.ui-dialog .charsheet button.m2dot { padding: 0; border: solid 1px #a8a8a8; margin-left: 6px; @@ -259,7 +376,8 @@ button.sheet-m2dot { justify-content: center; align-items: center; } -button.sheet-m2dot > span { + +.ui-dialog .charsheet button.m2dot > span { width: 20px; height: 20px; border-radius: 50%; @@ -268,7 +386,8 @@ button.sheet-m2dot > span { background-size: 90%; background-position: center; } -button.sheet-m3dot { + +.ui-dialog .charsheet button.m3dot { padding: 0; border: solid 1px #a8a8a8; margin-left: 6px; @@ -281,7 +400,8 @@ button.sheet-m3dot { justify-content: center; align-items: center; } -button.sheet-m3dot > span { + +.ui-dialog .charsheet button.m3dot > span { width: 20px; height: 20px; border-radius: 50%; @@ -290,2225 +410,3158 @@ button.sheet-m3dot > span { background-size: 90%; background-position: center; } + /* Configure the radio button arrays for health points and magic points */ - input.sheet-sdot[value="0"] ~ button.sheet-gt-0 > span.sheet-checked { + input.sdot[value="0"] ~ button.gt-0 > span.checked { display: none; } - input.sheet-sdot[value="1"] ~ button.sheet-gt-1 > span.sheet-checked { + input.sdot[value="1"] ~ button.gt-1 > span.checked { display: none; } - input.sheet-sdot[value="2"] ~ button.sheet-gt-2 > span.sheet-checked { + input.sdot[value="2"] ~ button.gt-2 > span.checked { display: none; } - input.sheet-sdot[value="3"] ~ button.sheet-gt-3 > span.sheet-checked { + input.sdot[value="3"] ~ button.gt-3 > span.checked { display: none; } - input.sheet-sdot[value="4"] ~ button.sheet-gt-4 > span.sheet-checked { + input.sdot[value="4"] ~ button.gt-4 > span.checked { display: none; } - input.sheet-sdot[value="5"] ~ button.sheet-gt-5 > span.sheet-checked { + input.sdot[value="5"] ~ button.gt-5 > span.checked { display: none; } - input.sheet-sdot[value="6"] ~ button.sheet-gt-6 > span.sheet-checked { + input.sdot[value="6"] ~ button.gt-6 > span.checked { display: none; } - input.sheet-sdot[value="7"] ~ button.sheet-gt-7 > span.sheet-checked { + input.sdot[value="7"] ~ button.gt-7 > span.checked { display: none; } - input.sheet-sdot[value="8"] ~ button.sheet-gt-8 > span.sheet-checked { + input.sdot[value="8"] ~ button.gt-8 > span.checked { display: none; } - input.sheet-sdot[value="9"] ~ button.sheet-gt-9 > span.sheet-checked { + input.sdot[value="9"] ~ button.gt-9 > span.checked { display: none; } - input.sheet-sdot[value="10"] ~ button.sheet-gt-10 > span.sheet-checked { + input.sdot[value="10"] ~ button.gt-10 > span.checked { display: none; } - input.sheet-sdot[value="11"] ~ button.sheet-gt-11 > span.sheet-checked { + input.sdot[value="11"] ~ button.gt-11 > span.checked { display: none; } - input.sheet-sdot[value="12"] ~ button.sheet-gt-12 > span.sheet-checked { + input.sdot[value="12"] ~ button.gt-12 > span.checked { display: none; } - input.sheet-sdot[value="13"] ~ button.sheet-gt-13 > span.sheet-checked { + input.sdot[value="13"] ~ button.gt-13 > span.checked { display: none; } - input.sheet-sdot[value="14"] ~ button.sheet-gt-14 > span.sheet-checked { + input.sdot[value="14"] ~ button.gt-14 > span.checked { display: none; } - input.sheet-sdot[value="15"] ~ button.sheet-gt-15 > span.sheet-checked { + input.sdot[value="15"] ~ button.gt-15 > span.checked { display: none; } - input.sheet-sdot[value="16"] ~ button.sheet-gt-16 > span.sheet-checked { + input.sdot[value="16"] ~ button.gt-16 > span.checked { display: none; } - input.sheet-sdot[value="17"] ~ button.sheet-gt-17 > span.sheet-checked { + input.sdot[value="17"] ~ button.gt-17 > span.checked { display: none; } - input.sheet-sdot[value="18"] ~ button.sheet-gt-18 > span.sheet-checked { + input.sdot[value="18"] ~ button.gt-18 > span.checked { display: none; } - input.sheet-sdot[value="19"] ~ button.sheet-gt-19 > span.sheet-checked { + input.sdot[value="19"] ~ button.gt-19 > span.checked { display: none; } - input.sheet-sdot[value="20"] ~ button.sheet-gt-20 > span.sheet-checked { + input.sdot[value="20"] ~ button.gt-20 > span.checked { display: none; } - input.sheet-sdot[value="21"] ~ button.sheet-gt-21 > span.sheet-checked { + input.sdot[value="21"] ~ button.gt-21 > span.checked { display: none; } - input.sheet-sdot[value="22"] ~ button.sheet-gt-22 > span.sheet-checked { + input.sdot[value="22"] ~ button.gt-22 > span.checked { display: none; } - input.sheet-sdot[value="23"] ~ button.sheet-gt-23 > span.sheet-checked { + input.sdot[value="23"] ~ button.gt-23 > span.checked { display: none; } - input.sheet-sdot[value="24"] ~ button.sheet-gt-24 > span.sheet-checked { + input.sdot[value="24"] ~ button.gt-24 > span.checked { display: none; } - input.sheet-sdot[value="25"] ~ button.sheet-gt-25 > span.sheet-checked { + input.sdot[value="25"] ~ button.gt-25 > span.checked { display: none; } - input.sheet-sdot[value="26"] ~ button.sheet-gt-26 > span.sheet-checked { + input.sdot[value="26"] ~ button.gt-26 > span.checked { display: none; } - input.sheet-sdot[value="27"] ~ button.sheet-gt-27 > span.sheet-checked { + input.sdot[value="27"] ~ button.gt-27 > span.checked { display: none; } - input.sheet-sdot[value="28"] ~ button.sheet-gt-28 > span.sheet-checked { + input.sdot[value="28"] ~ button.gt-28 > span.checked { display: none; } - input.sheet-sdot[value="29"] ~ button.sheet-gt-29 > span.sheet-checked { + input.sdot[value="29"] ~ button.gt-29 > span.checked { display: none; } - input.sheet-sdot[value="30"] ~ button.sheet-gt-30 > span.sheet-checked { + input.sdot[value="30"] ~ button.gt-30 > span.checked { display: none; } - input.sheet-sdot[value="31"] ~ button.sheet-gt-31 > span.sheet-checked { + input.sdot[value="31"] ~ button.gt-31 > span.checked { display: none; } - input.sheet-sdot[value="32"] ~ button.sheet-gt-32 > span.sheet-checked { + input.sdot[value="32"] ~ button.gt-32 > span.checked { display: none; } - input.sheet-sdot[value="33"] ~ button.sheet-gt-33 > span.sheet-checked { + input.sdot[value="33"] ~ button.gt-33 > span.checked { display: none; } - input.sheet-sdot[value="34"] ~ button.sheet-gt-34 > span.sheet-checked { + input.sdot[value="34"] ~ button.gt-34 > span.checked { display: none; } - input.sheet-sdot[value="35"] ~ button.sheet-gt-35 > span.sheet-checked { + input.sdot[value="35"] ~ button.gt-35 > span.checked { display: none; } - input.sheet-sdot[value="36"] ~ button.sheet-gt-36 > span.sheet-checked { + input.sdot[value="36"] ~ button.gt-36 > span.checked { display: none; } - input.sheet-sdot[value="37"] ~ button.sheet-gt-37 > span.sheet-checked { + input.sdot[value="37"] ~ button.gt-37 > span.checked { display: none; } - input.sheet-sdot[value="38"] ~ button.sheet-gt-38 > span.sheet-checked { + input.sdot[value="38"] ~ button.gt-38 > span.checked { display: none; } - input.sheet-sdot[value="39"] ~ button.sheet-gt-39 > span.sheet-checked { + input.sdot[value="39"] ~ button.gt-39 > span.checked { display: none; } - input.sheet-sdot[value="40"] ~ button.sheet-gt-40 > span.sheet-checked { + input.sdot[value="40"] ~ button.gt-40 > span.checked { display: none; } - input.sheet-sdot[value="41"] ~ button.sheet-gt-41 > span.sheet-checked { + input.sdot[value="41"] ~ button.gt-41 > span.checked { display: none; } - input.sheet-sdot[value="42"] ~ button.sheet-gt-42 > span.sheet-checked { + input.sdot[value="42"] ~ button.gt-42 > span.checked { display: none; } - input.sheet-sdot[value="43"] ~ button.sheet-gt-43 > span.sheet-checked { + input.sdot[value="43"] ~ button.gt-43 > span.checked { display: none; } - input.sheet-sdot[value="44"] ~ button.sheet-gt-44 > span.sheet-checked { + input.sdot[value="44"] ~ button.gt-44 > span.checked { display: none; } - input.sheet-sdot[value="45"] ~ button.sheet-gt-45 > span.sheet-checked { + input.sdot[value="45"] ~ button.gt-45 > span.checked { display: none; } - input.sheet-sdot[value="46"] ~ button.sheet-gt-46 > span.sheet-checked { + input.sdot[value="46"] ~ button.gt-46 > span.checked { display: none; } - input.sheet-sdot[value="47"] ~ button.sheet-gt-47 > span.sheet-checked { + input.sdot[value="47"] ~ button.gt-47 > span.checked { display: none; } - input.sheet-sdot[value="48"] ~ button.sheet-gt-48 > span.sheet-checked { + input.sdot[value="48"] ~ button.gt-48 > span.checked { display: none; } - input.sheet-sdot[value="49"] ~ button.sheet-gt-49 > span.sheet-checked { + input.sdot[value="49"] ~ button.gt-49 > span.checked { display: none; } - input.sheet-sdot[value="50"] ~ button.sheet-gt-50 > span.sheet-checked { + input.sdot[value="50"] ~ button.gt-50 > span.checked { display: none; } - input.sheet-wtdot[value="0"] ~ button.sheet-wt-0 > span.sheet-checked { + input.wtdot[value="0"] ~ button.wt-0 > span.checked { display: none; } - input.sheet-wtdot[value="1"] ~ button.sheet-wt-1 > span.sheet-checked { - display: none; - } - input.sheet-wtdot[value="2"] ~ button.sheet-wt-2 > span.sheet-checked { - display: none; - } - input.sheet-wtdot[value="3"] ~ button.sheet-wt-3 > span.sheet-checked { - display: none; - } - input.sheet-sbody[value="0"] ~ button.sheet-gt-0, - input.sheet-sbody[value="1"] ~ button.sheet-gt-1, - input.sheet-sbody[value="2"] ~ button.sheet-gt-2, - input.sheet-sbody[value="3"] ~ button.sheet-gt-3, - input.sheet-sbody[value="4"] ~ button.sheet-gt-4, - input.sheet-sbody[value="5"] ~ button.sheet-gt-5, - input.sheet-sbody[value="6"] ~ button.sheet-gt-6, - input.sheet-sbody[value="7"] ~ button.sheet-gt-7, - input.sheet-sbody[value="8"] ~ button.sheet-gt-8, - input.sheet-sbody[value="9"] ~ button.sheet-gt-9, - input.sheet-sbody[value="10"] ~ button.sheet-gt-10, - input.sheet-sbody[value="11"] ~ button.sheet-gt-11, - input.sheet-sbody[value="12"] ~ button.sheet-gt-12, - input.sheet-sbody[value="13"] ~ button.sheet-gt-13, - input.sheet-sbody[value="14"] ~ button.sheet-gt-14, - input.sheet-sbody[value="15"] ~ button.sheet-gt-15, - input.sheet-sbody[value="16"] ~ button.sheet-gt-16, - input.sheet-sbody[value="17"] ~ button.sheet-gt-17, - input.sheet-sbody[value="18"] ~ button.sheet-gt-18, - input.sheet-sbody[value="19"] ~ button.sheet-gt-19, - input.sheet-sbody[value="20"] ~ button.sheet-gt-20, - input.sheet-sbody[value="21"] ~ button.sheet-gt-21, - input.sheet-sbody[value="22"] ~ button.sheet-gt-22, - input.sheet-sbody[value="23"] ~ button.sheet-gt-23, - input.sheet-sbody[value="24"] ~ button.sheet-gt-24, - input.sheet-sbody[value="25"] ~ button.sheet-gt-25, - input.sheet-sbody[value="26"] ~ button.sheet-gt-26, - input.sheet-sbody[value="27"] ~ button.sheet-gt-27, - input.sheet-sbody[value="28"] ~ button.sheet-gt-28, - input.sheet-sbody[value="29"] ~ button.sheet-gt-29, - input.sheet-sbody[value="30"] ~ button.sheet-gt-30, - input.sheet-sbody[value="31"] ~ button.sheet-gt-31, - input.sheet-sbody[value="32"] ~ button.sheet-gt-32, - input.sheet-sbody[value="33"] ~ button.sheet-gt-33, - input.sheet-sbody[value="34"] ~ button.sheet-gt-34, - input.sheet-sbody[value="35"] ~ button.sheet-gt-35, - input.sheet-sbody[value="36"] ~ button.sheet-gt-36, - input.sheet-sbody[value="37"] ~ button.sheet-gt-37, - input.sheet-sbody[value="38"] ~ button.sheet-gt-38, - input.sheet-sbody[value="39"] ~ button.sheet-gt-39, - input.sheet-sbody[value="40"] ~ button.sheet-gt-40, - input.sheet-sbody[value="41"] ~ button.sheet-gt-41, - input.sheet-sbody[value="42"] ~ button.sheet-gt-42, - input.sheet-sbody[value="43"] ~ button.sheet-gt-43, - input.sheet-sbody[value="44"] ~ button.sheet-gt-44, - input.sheet-sbody[value="45"] ~ button.sheet-gt-45, - input.sheet-sbody[value="46"] ~ button.sheet-gt-46, - input.sheet-sbody[value="47"] ~ button.sheet-gt-47, - input.sheet-sbody[value="48"] ~ button.sheet-gt-48, - input.sheet-sbody[value="49"] ~ button.sheet-gt-49, - input.sheet-sbody[value="50"] ~ button.sheet-gt-50{ - display: none; - } - input.sheet-wtbody[value="0"] ~ button.sheet-wt-0, - input.sheet-wtbody[value="1"] ~ button.sheet-wt-1, - input.sheet-wtbody[value="2"] ~ button.sheet-wt-2, - input.sheet-wtbody[value="3"] ~ button.sheet-wt-3{ + input.wtdot[value="1"] ~ button.wt-1 > span.checked { + display: none; + } + input.wtdot[value="2"] ~ button.wt-2 > span.checked { + display: none; + } + input.wtdot[value="3"] ~ button.wt-3 > span.checked { + display: none; + } + input.sbody[value="0"] ~ button.gt-0, + input.sbody[value="1"] ~ button.gt-1, + input.sbody[value="2"] ~ button.gt-2, + input.sbody[value="3"] ~ button.gt-3, + input.sbody[value="4"] ~ button.gt-4, + input.sbody[value="5"] ~ button.gt-5, + input.sbody[value="6"] ~ button.gt-6, + input.sbody[value="7"] ~ button.gt-7, + input.sbody[value="8"] ~ button.gt-8, + input.sbody[value="9"] ~ button.gt-9, + input.sbody[value="10"] ~ button.gt-10, + input.sbody[value="11"] ~ button.gt-11, + input.sbody[value="12"] ~ button.gt-12, + input.sbody[value="13"] ~ button.gt-13, + input.sbody[value="14"] ~ button.gt-14, + input.sbody[value="15"] ~ button.gt-15, + input.sbody[value="16"] ~ button.gt-16, + input.sbody[value="17"] ~ button.gt-17, + input.sbody[value="18"] ~ button.gt-18, + input.sbody[value="19"] ~ button.gt-19, + input.sbody[value="20"] ~ button.gt-20, + input.sbody[value="21"] ~ button.gt-21, + input.sbody[value="22"] ~ button.gt-22, + input.sbody[value="23"] ~ button.gt-23, + input.sbody[value="24"] ~ button.gt-24, + input.sbody[value="25"] ~ button.gt-25, + input.sbody[value="26"] ~ button.gt-26, + input.sbody[value="27"] ~ button.gt-27, + input.sbody[value="28"] ~ button.gt-28, + input.sbody[value="29"] ~ button.gt-29, + input.sbody[value="30"] ~ button.gt-30, + input.sbody[value="31"] ~ button.gt-31, + input.sbody[value="32"] ~ button.gt-32, + input.sbody[value="33"] ~ button.gt-33, + input.sbody[value="34"] ~ button.gt-34, + input.sbody[value="35"] ~ button.gt-35, + input.sbody[value="36"] ~ button.gt-36, + input.sbody[value="37"] ~ button.gt-37, + input.sbody[value="38"] ~ button.gt-38, + input.sbody[value="39"] ~ button.gt-39, + input.sbody[value="40"] ~ button.gt-40, + input.sbody[value="41"] ~ button.gt-41, + input.sbody[value="42"] ~ button.gt-42, + input.sbody[value="43"] ~ button.gt-43, + input.sbody[value="44"] ~ button.gt-44, + input.sbody[value="45"] ~ button.gt-45, + input.sbody[value="46"] ~ button.gt-46, + input.sbody[value="47"] ~ button.gt-47, + input.sbody[value="48"] ~ button.gt-48, + input.sbody[value="49"] ~ button.gt-49, + input.sbody[value="50"] ~ button.gt-50{ + display: none; + } + + input.wtbody[value="0"] ~ button.wt-0, + input.wtbody[value="1"] ~ button.wt-1, + input.wtbody[value="2"] ~ button.wt-2, + input.wtbody[value="3"] ~ button.wt-3{ display: none; -} - input.sheet-mdot[value="0"] ~ button.sheet-mt-0 > span.sheet-checked { + } + + input.mdot[value="0"] ~ button.mt-0 > span.checked { display: none; } - input.sheet-mdot[value="1"] ~ button.sheet-mt-1 > span.sheet-checked { + input.mdot[value="1"] ~ button.mt-1 > span.checked { display: none; } - input.sheet-mdot[value="2"] ~ button.sheet-mt-2 > span.sheet-checked { + input.mdot[value="2"] ~ button.mt-2 > span.checked { display: none; } - input.sheet-mdot[value="3"] ~ button.sheet-mt-3 > span.sheet-checked { + input.mdot[value="3"] ~ button.mt-3 > span.checked { display: none; } - input.sheet-mdot[value="4"] ~ button.sheet-mt-4 > span.sheet-checked { + input.mdot[value="4"] ~ button.mt-4 > span.checked { display: none; } - input.sheet-mdot[value="5"] ~ button.sheet-mt-5 > span.sheet-checked { + input.mdot[value="5"] ~ button.mt-5 > span.checked { display: none; } - input.sheet-mdot[value="6"] ~ button.sheet-mt-6 > span.sheet-checked { + input.mdot[value="6"] ~ button.mt-6 > span.checked { display: none; } - input.sheet-mdot[value="7"] ~ button.sheet-mt-7 > span.sheet-checked { + input.mdot[value="7"] ~ button.mt-7 > span.checked { display: none; } - input.sheet-mdot[value="8"] ~ button.sheet-mt-8 > span.sheet-checked { + input.mdot[value="8"] ~ button.mt-8 > span.checked { display: none; } - input.sheet-mdot[value="9"] ~ button.sheet-mt-9 > span.sheet-checked { + input.mdot[value="9"] ~ button.mt-9 > span.checked { display: none; } - input.sheet-mdot[value="10"] ~ button.sheet-mt-10 > span.sheet-checked { + input.mdot[value="10"] ~ button.mt-10 > span.checked { display: none; } - input.sheet-mdot[value="11"] ~ button.sheet-mt-11 > span.sheet-checked { + input.mdot[value="11"] ~ button.mt-11 > span.checked { display: none; } - input.sheet-mdot[value="12"] ~ button.sheet-mt-12 > span.sheet-checked { + input.mdot[value="12"] ~ button.mt-12 > span.checked { display: none; } - input.sheet-mdot[value="13"] ~ button.sheet-mt-13 > span.sheet-checked { + input.mdot[value="13"] ~ button.mt-13 > span.checked { display: none; } - input.sheet-mdot[value="14"] ~ button.sheet-mt-14 > span.sheet-checked { + input.mdot[value="14"] ~ button.mt-14 > span.checked { display: none; } - input.sheet-mdot[value="15"] ~ button.sheet-mt-15 > span.sheet-checked { + input.mdot[value="15"] ~ button.mt-15 > span.checked { display: none; } - input.sheet-mdot[value="16"] ~ button.sheet-mt-16 > span.sheet-checked { + input.mdot[value="16"] ~ button.mt-16 > span.checked { display: none; } - input.sheet-mdot[value="17"] ~ button.sheet-mt-17 > span.sheet-checked { + input.mdot[value="17"] ~ button.mt-17 > span.checked { display: none; } - input.sheet-mdot[value="18"] ~ button.sheet-mt-18 > span.sheet-checked { + input.mdot[value="18"] ~ button.mt-18 > span.checked { display: none; } - input.sheet-mdot[value="19"] ~ button.sheet-mt-19 > span.sheet-checked { + input.mdot[value="19"] ~ button.mt-19 > span.checked { display: none; } - input.sheet-mdot[value="20"] ~ button.sheet-mt-20 > span.sheet-checked { + input.mdot[value="20"] ~ button.mt-20 > span.checked { display: none; } - input.sheet-mdot[value="21"] ~ button.sheet-mt-21 > span.sheet-checked { + input.mdot[value="21"] ~ button.mt-21 > span.checked { display: none; } - input.sheet-mdot[value="22"] ~ button.sheet-mt-22 > span.sheet-checked { + input.mdot[value="22"] ~ button.mt-22 > span.checked { display: none; } - input.sheet-mdot[value="23"] ~ button.sheet-mt-23 > span.sheet-checked { + input.mdot[value="23"] ~ button.mt-23 > span.checked { display: none; } - input.sheet-mdot[value="24"] ~ button.sheet-mt-24 > span.sheet-checked { + input.mdot[value="24"] ~ button.mt-24 > span.checked { display: none; } - input.sheet-mdot[value="25"] ~ button.sheet-mt-25 > span.sheet-checked { + input.mdot[value="25"] ~ button.mt-25 > span.checked { display: none; } - input.sheet-mdot[value="26"] ~ button.sheet-mt-26 > span.sheet-checked { + input.mdot[value="26"] ~ button.mt-26 > span.checked { display: none; } - input.sheet-mdot[value="27"] ~ button.sheet-mt-27 > span.sheet-checked { + input.mdot[value="27"] ~ button.mt-27 > span.checked { display: none; } - input.sheet-mdot[value="28"] ~ button.sheet-mt-28 > span.sheet-checked { + input.mdot[value="28"] ~ button.mt-28 > span.checked { display: none; } - input.sheet-mdot[value="29"] ~ button.sheet-mt-29 > span.sheet-checked { + input.mdot[value="29"] ~ button.mt-29 > span.checked { display: none; } - input.sheet-mdot[value="30"] ~ button.sheet-mt-30 > span.sheet-checked { + input.mdot[value="30"] ~ button.mt-30 > span.checked { display: none; } - input.sheet-mdot[value="31"] ~ button.sheet-mt-31 > span.sheet-checked { + input.mdot[value="31"] ~ button.mt-31 > span.checked { display: none; } - input.sheet-mdot[value="32"] ~ button.sheet-mt-32 > span.sheet-checked { + input.mdot[value="32"] ~ button.mt-32 > span.checked { display: none; } - input.sheet-mdot[value="33"] ~ button.sheet-mt-33 > span.sheet-checked { + input.mdot[value="33"] ~ button.mt-33 > span.checked { display: none; } - input.sheet-mdot[value="34"] ~ button.sheet-mt-34 > span.sheet-checked { + input.mdot[value="34"] ~ button.mt-34 > span.checked { display: none; } - input.sheet-mdot[value="35"] ~ button.sheet-mt-35 > span.sheet-checked { + input.mdot[value="35"] ~ button.mt-35 > span.checked { display: none; } - input.sheet-mdot[value="36"] ~ button.sheet-mt-36 > span.sheet-checked { + input.mdot[value="36"] ~ button.mt-36 > span.checked { display: none; } - input.sheet-mdot[value="37"] ~ button.sheet-mt-37 > span.sheet-checked { + input.mdot[value="37"] ~ button.mt-37 > span.checked { display: none; } - input.sheet-mdot[value="38"] ~ button.sheet-mt-38 > span.sheet-checked { + input.mdot[value="38"] ~ button.mt-38 > span.checked { display: none; } - input.sheet-mdot[value="39"] ~ button.sheet-mt-39 > span.sheet-checked { + input.mdot[value="39"] ~ button.mt-39 > span.checked { display: none; } - input.sheet-mdot[value="40"] ~ button.sheet-mt-40 > span.sheet-checked { + input.mdot[value="40"] ~ button.mt-40 > span.checked { display: none; } - input.sheet-mdot[value="41"] ~ button.sheet-mt-41 > span.sheet-checked { + input.mdot[value="41"] ~ button.mt-41 > span.checked { display: none; } - input.sheet-mdot[value="42"] ~ button.sheet-mt-42 > span.sheet-checked { + input.mdot[value="42"] ~ button.mt-42 > span.checked { display: none; } - input.sheet-mdot[value="43"] ~ button.sheet-mt-43 > span.sheet-checked { + input.mdot[value="43"] ~ button.mt-43 > span.checked { display: none; } - input.sheet-mdot[value="44"] ~ button.sheet-mt-44 > span.sheet-checked { + input.mdot[value="44"] ~ button.mt-44 > span.checked { display: none; } - input.sheet-mdot[value="45"] ~ button.sheet-mt-45 > span.sheet-checked { + input.mdot[value="45"] ~ button.mt-45 > span.checked { display: none; } - input.sheet-mdot[value="46"] ~ button.sheet-mt-46 > span.sheet-checked { + input.mdot[value="46"] ~ button.mt-46 > span.checked { display: none; } - input.sheet-mdot[value="47"] ~ button.sheet-mt-47 > span.sheet-checked { + input.mdot[value="47"] ~ button.mt-47 > span.checked { display: none; } - input.sheet-mdot[value="48"] ~ button.sheet-mt-48 > span.sheet-checked { + input.mdot[value="48"] ~ button.mt-48 > span.checked { display: none; } - input.sheet-mdot[value="49"] ~ button.sheet-mt-49 > span.sheet-checked { + input.mdot[value="49"] ~ button.mt-49 > span.checked { display: none; } - input.sheet-mdot[value="50"] ~ button.sheet-mt-50 > span.sheet-checked { + input.mdot[value="50"] ~ button.mt-50 > span.checked { display: none; } - input.sheet-mbody[value="0"] ~ button.sheet-mt-0, - input.sheet-mbody[value="1"] ~ button.sheet-mt-1, - input.sheet-mbody[value="2"] ~ button.sheet-mt-2, - input.sheet-mbody[value="3"] ~ button.sheet-mt-3, - input.sheet-mbody[value="4"] ~ button.sheet-mt-4, - input.sheet-mbody[value="5"] ~ button.sheet-mt-5, - input.sheet-mbody[value="6"] ~ button.sheet-mt-6, - input.sheet-mbody[value="7"] ~ button.sheet-mt-7, - input.sheet-mbody[value="8"] ~ button.sheet-mt-8, - input.sheet-mbody[value="9"] ~ button.sheet-mt-9, - input.sheet-mbody[value="10"] ~ button.sheet-mt-10, - input.sheet-mbody[value="11"] ~ button.sheet-mt-11, - input.sheet-mbody[value="12"] ~ button.sheet-mt-12, - input.sheet-mbody[value="13"] ~ button.sheet-mt-13, - input.sheet-mbody[value="14"] ~ button.sheet-mt-14, - input.sheet-mbody[value="15"] ~ button.sheet-mt-15, - input.sheet-mbody[value="16"] ~ button.sheet-mt-16, - input.sheet-mbody[value="17"] ~ button.sheet-mt-17, - input.sheet-mbody[value="18"] ~ button.sheet-mt-18, - input.sheet-mbody[value="19"] ~ button.sheet-mt-19, - input.sheet-mbody[value="20"] ~ button.sheet-mt-20, - input.sheet-mbody[value="21"] ~ button.sheet-mt-21, - input.sheet-mbody[value="22"] ~ button.sheet-mt-22, - input.sheet-mbody[value="23"] ~ button.sheet-mt-23, - input.sheet-mbody[value="24"] ~ button.sheet-mt-24, - input.sheet-mbody[value="25"] ~ button.sheet-mt-25, - input.sheet-mbody[value="26"] ~ button.sheet-mt-26, - input.sheet-mbody[value="27"] ~ button.sheet-mt-27, - input.sheet-mbody[value="28"] ~ button.sheet-mt-28, - input.sheet-mbody[value="29"] ~ button.sheet-mt-29, - input.sheet-mbody[value="30"] ~ button.sheet-mt-30, - input.sheet-mbody[value="31"] ~ button.sheet-mt-31, - input.sheet-mbody[value="32"] ~ button.sheet-mt-32, - input.sheet-mbody[value="33"] ~ button.sheet-mt-33, - input.sheet-mbody[value="34"] ~ button.sheet-mt-34, - input.sheet-mbody[value="35"] ~ button.sheet-mt-35, - input.sheet-mbody[value="36"] ~ button.sheet-mt-36, - input.sheet-mbody[value="37"] ~ button.sheet-mt-37, - input.sheet-mbody[value="38"] ~ button.sheet-mt-38, - input.sheet-mbody[value="39"] ~ button.sheet-mt-39, - input.sheet-mbody[value="40"] ~ button.sheet-mt-40, - input.sheet-mbody[value="41"] ~ button.sheet-mt-41, - input.sheet-mbody[value="42"] ~ button.sheet-mt-42, - input.sheet-mbody[value="43"] ~ button.sheet-mt-43, - input.sheet-mbody[value="44"] ~ button.sheet-mt-44, - input.sheet-mbody[value="45"] ~ button.sheet-mt-45, - input.sheet-mbody[value="46"] ~ button.sheet-mt-46, - input.sheet-mbody[value="47"] ~ button.sheet-mt-47, - input.sheet-mbody[value="48"] ~ button.sheet-mt-48, - input.sheet-mbody[value="49"] ~ button.sheet-mt-49, - input.sheet-mbody[value="50"] ~ button.sheet-mt-50{ + + input.mbody[value="0"] ~ button.mt-0, + input.mbody[value="1"] ~ button.mt-1, + input.mbody[value="2"] ~ button.mt-2, + input.mbody[value="3"] ~ button.mt-3, + input.mbody[value="4"] ~ button.mt-4, + input.mbody[value="5"] ~ button.mt-5, + input.mbody[value="6"] ~ button.mt-6, + input.mbody[value="7"] ~ button.mt-7, + input.mbody[value="8"] ~ button.mt-8, + input.mbody[value="9"] ~ button.mt-9, + input.mbody[value="10"] ~ button.mt-10, + input.mbody[value="11"] ~ button.mt-11, + input.mbody[value="12"] ~ button.mt-12, + input.mbody[value="13"] ~ button.mt-13, + input.mbody[value="14"] ~ button.mt-14, + input.mbody[value="15"] ~ button.mt-15, + input.mbody[value="16"] ~ button.mt-16, + input.mbody[value="17"] ~ button.mt-17, + input.mbody[value="18"] ~ button.mt-18, + input.mbody[value="19"] ~ button.mt-19, + input.mbody[value="20"] ~ button.mt-20, + input.mbody[value="21"] ~ button.mt-21, + input.mbody[value="22"] ~ button.mt-22, + input.mbody[value="23"] ~ button.mt-23, + input.mbody[value="24"] ~ button.mt-24, + input.mbody[value="25"] ~ button.mt-25, + input.mbody[value="26"] ~ button.mt-26, + input.mbody[value="27"] ~ button.mt-27, + input.mbody[value="28"] ~ button.mt-28, + input.mbody[value="29"] ~ button.mt-29, + input.mbody[value="30"] ~ button.mt-30, + input.mbody[value="31"] ~ button.mt-31, + input.mbody[value="32"] ~ button.mt-32, + input.mbody[value="33"] ~ button.mt-33, + input.mbody[value="34"] ~ button.mt-34, + input.mbody[value="35"] ~ button.mt-35, + input.mbody[value="36"] ~ button.mt-36, + input.mbody[value="37"] ~ button.mt-37, + input.mbody[value="38"] ~ button.mt-38, + input.mbody[value="39"] ~ button.mt-39, + input.mbody[value="40"] ~ button.mt-40, + input.mbody[value="41"] ~ button.mt-41, + input.mbody[value="42"] ~ button.mt-42, + input.mbody[value="43"] ~ button.mt-43, + input.mbody[value="44"] ~ button.mt-44, + input.mbody[value="45"] ~ button.mt-45, + input.mbody[value="46"] ~ button.mt-46, + input.mbody[value="47"] ~ button.mt-47, + input.mbody[value="48"] ~ button.mt-48, + input.mbody[value="49"] ~ button.mt-49, + input.mbody[value="50"] ~ button.mt-50{ display: none; } - input.sheet-m2dot[value="0"] ~ button.sheet-mt2-0 > span.sheet-checked { + + input.m2dot[value="0"] ~ button.mt2-0 > span.checked { display: none; } - input.sheet-m2dot[value="1"] ~ button.sheet-mt2-1 > span.sheet-checked { + input.m2dot[value="1"] ~ button.mt2-1 > span.checked { display: none; } - input.sheet-m2dot[value="2"] ~ button.sheet-mt2-2 > span.sheet-checked { + input.m2dot[value="2"] ~ button.mt2-2 > span.checked { display: none; } - input.sheet-m2dot[value="3"] ~ button.sheet-mt2-3 > span.sheet-checked { + input.m2dot[value="3"] ~ button.mt2-3 > span.checked { display: none; } - input.sheet-m2dot[value="4"] ~ button.sheet-mt2-4 > span.sheet-checked { + input.m2dot[value="4"] ~ button.mt2-4 > span.checked { display: none; } - input.sheet-m2dot[value="5"] ~ button.sheet-mt2-5 > span.sheet-checked { + input.m2dot[value="5"] ~ button.mt2-5 > span.checked { display: none; } - input.sheet-m2dot[value="6"] ~ button.sheet-mt2-6 > span.sheet-checked { + input.m2dot[value="6"] ~ button.mt2-6 > span.checked { display: none; } - input.sheet-m2dot[value="7"] ~ button.sheet-mt2-7 > span.sheet-checked { + input.m2dot[value="7"] ~ button.mt2-7 > span.checked { display: none; } - input.sheet-m2dot[value="8"] ~ button.sheet-mt2-8 > span.sheet-checked { + input.m2dot[value="8"] ~ button.mt2-8 > span.checked { display: none; } - input.sheet-m2dot[value="9"] ~ button.sheet-mt2-9 > span.sheet-checked { + input.m2dot[value="9"] ~ button.mt2-9 > span.checked { display: none; } - input.sheet-m2dot[value="10"] ~ button.sheet-mt2-10 > span.sheet-checked { + input.m2dot[value="10"] ~ button.mt2-10 > span.checked { display: none; } - input.sheet-m2dot[value="11"] ~ button.sheet-mt2-11 > span.sheet-checked { + input.m2dot[value="11"] ~ button.mt2-11 > span.checked { display: none; } - input.sheet-m2dot[value="12"] ~ button.sheet-mt2-12 > span.sheet-checked { + input.m2dot[value="12"] ~ button.mt2-12 > span.checked { display: none; } - input.sheet-m2dot[value="13"] ~ button.sheet-mt2-13 > span.sheet-checked { + input.m2dot[value="13"] ~ button.mt2-13 > span.checked { display: none; } - input.sheet-m2dot[value="14"] ~ button.sheet-mt2-14 > span.sheet-checked { + input.m2dot[value="14"] ~ button.mt2-14 > span.checked { display: none; } - input.sheet-m2dot[value="15"] ~ button.sheet-mt2-15 > span.sheet-checked { + input.m2dot[value="15"] ~ button.mt2-15 > span.checked { display: none; } - input.sheet-m2dot[value="16"] ~ button.sheet-mt2-16 > span.sheet-checked { + input.m2dot[value="16"] ~ button.mt2-16 > span.checked { display: none; } - input.sheet-m2dot[value="17"] ~ button.sheet-mt2-17 > span.sheet-checked { + input.m2dot[value="17"] ~ button.mt2-17 > span.checked { display: none; } - input.sheet-m2dot[value="18"] ~ button.sheet-mt2-18 > span.sheet-checked { + input.m2dot[value="18"] ~ button.mt2-18 > span.checked { display: none; } - input.sheet-m2dot[value="19"] ~ button.sheet-mt2-19 > span.sheet-checked { + input.m2dot[value="19"] ~ button.mt2-19 > span.checked { display: none; } - input.sheet-m2dot[value="20"] ~ button.sheet-mt2-20 > span.sheet-checked { + input.m2dot[value="20"] ~ button.mt2-20 > span.checked { display: none; } - input.sheet-m2dot[value="21"] ~ button.sheet-mt2-21 > span.sheet-checked { + input.m2dot[value="21"] ~ button.mt2-21 > span.checked { display: none; } - input.sheet-m2dot[value="22"] ~ button.sheet-mt2-22 > span.sheet-checked { + input.m2dot[value="22"] ~ button.mt2-22 > span.checked { display: none; } - input.sheet-m2dot[value="23"] ~ button.sheet-mt2-23 > span.sheet-checked { + input.m2dot[value="23"] ~ button.mt2-23 > span.checked { display: none; } - input.sheet-m2dot[value="24"] ~ button.sheet-mt2-24 > span.sheet-checked { + input.m2dot[value="24"] ~ button.mt2-24 > span.checked { display: none; } - input.sheet-m2dot[value="25"] ~ button.sheet-mt2-25 > span.sheet-checked { + input.m2dot[value="25"] ~ button.mt2-25 > span.checked { display: none; } - input.sheet-m2dot[value="26"] ~ button.sheet-mt2-26 > span.sheet-checked { + input.m2dot[value="26"] ~ button.mt2-26 > span.checked { display: none; } - input.sheet-m2dot[value="27"] ~ button.sheet-mt2-27 > span.sheet-checked { + input.m2dot[value="27"] ~ button.mt2-27 > span.checked { display: none; } - input.sheet-m2dot[value="28"] ~ button.sheet-mt2-28 > span.sheet-checked { + input.m2dot[value="28"] ~ button.mt2-28 > span.checked { display: none; } - input.sheet-m2dot[value="29"] ~ button.sheet-mt2-29 > span.sheet-checked { + input.m2dot[value="29"] ~ button.mt2-29 > span.checked { display: none; } - input.sheet-m2dot[value="30"] ~ button.sheet-mt2-30 > span.sheet-checked { + input.m2dot[value="30"] ~ button.mt2-30 > span.checked { display: none; } - input.sheet-m2dot[value="31"] ~ button.sheet-mt22-31 > span.sheet-checked { + input.m2dot[value="31"] ~ button.mt22-31 > span.checked { display: none; } - input.sheet-m2dot[value="32"] ~ button.sheet-mt2-32 > span.sheet-checked { + input.m2dot[value="32"] ~ button.mt2-32 > span.checked { display: none; } - input.sheet-m2dot[value="33"] ~ button.sheet-mt2-33 > span.sheet-checked { + input.m2dot[value="33"] ~ button.mt2-33 > span.checked { display: none; } - input.sheet-m2dot[value="34"] ~ button.sheet-mt2-34 > span.sheet-checked { + input.m2dot[value="34"] ~ button.mt2-34 > span.checked { display: none; } - input.sheet-m2dot[value="35"] ~ button.sheet-mt2-35 > span.sheet-checked { + input.m2dot[value="35"] ~ button.mt2-35 > span.checked { display: none; } - input.sheet-m2dot[value="36"] ~ button.sheet-mt2-36 > span.sheet-checked { + input.m2dot[value="36"] ~ button.mt2-36 > span.checked { display: none; } - input.sheet-m2dot[value="37"] ~ button.sheet-mt2-37 > span.sheet-checked { + input.m2dot[value="37"] ~ button.mt2-37 > span.checked { display: none; } - input.sheet-m2dot[value="38"] ~ button.sheet-mt2-38 > span.sheet-checked { + input.m2dot[value="38"] ~ button.mt2-38 > span.checked { display: none; } - input.sheet-m2dot[value="39"] ~ button.sheet-mt2-39 > span.sheet-checked { + input.m2dot[value="39"] ~ button.mt2-39 > span.checked { display: none; } - input.sheet-m2dot[value="40"] ~ button.sheet-mt2-40 > span.sheet-checked { + input.m2dot[value="40"] ~ button.mt2-40 > span.checked { display: none; } - input.sheet-m2dot[value="41"] ~ button.sheet-mt2-41 > span.sheet-checked { + input.m2dot[value="41"] ~ button.mt2-41 > span.checked { display: none; } - input.sheet-m2dot[value="42"] ~ button.sheet-mt2-42 > span.sheet-checked { + input.m2dot[value="42"] ~ button.mt2-42 > span.checked { display: none; } - input.sheet-m2dot[value="43"] ~ button.sheet-mt2-43 > span.sheet-checked { + input.m2dot[value="43"] ~ button.mt2-43 > span.checked { display: none; } - input.sheet-m2dot[value="44"] ~ button.sheet-mt2-44 > span.sheet-checked { + input.m2dot[value="44"] ~ button.mt2-44 > span.checked { display: none; } - input.sheet-m2dot[value="45"] ~ button.sheet-mt2-45 > span.sheet-checked { + input.m2dot[value="45"] ~ button.mt2-45 > span.checked { display: none; } - input.sheet-m2dot[value="46"] ~ button.sheet-mt2-46 > span.sheet-checked { + input.m2dot[value="46"] ~ button.mt2-46 > span.checked { display: none; } - input.sheet-m2dot[value="47"] ~ button.sheet-mt2-47 > span.sheet-checked { + input.m2dot[value="47"] ~ button.mt2-47 > span.checked { display: none; } - input.sheet-m2dot[value="48"] ~ button.sheet-mt2-48 > span.sheet-checked { + input.m2dot[value="48"] ~ button.mt2-48 > span.checked { display: none; } - input.sheet-m2dot[value="49"] ~ button.sheet-mt2-49 > span.sheet-checked { + input.m2dot[value="49"] ~ button.mt2-49 > span.checked { display: none; } - input.sheet-m2dot[value="50"] ~ button.sheet-mt2-50 > span.sheet-checked { + input.m2dot[value="50"] ~ button.mt2-50 > span.checked { display: none; } - input.sheet-m2body[value="0"] ~ button.sheet-mt2-0, - input.sheet-m2body[value="1"] ~ button.sheet-mt2-1, - input.sheet-m2body[value="2"] ~ button.sheet-mt2-2, - input.sheet-m2body[value="3"] ~ button.sheet-mt2-3, - input.sheet-m2body[value="4"] ~ button.sheet-mt2-4, - input.sheet-m2body[value="5"] ~ button.sheet-mt2-5, - input.sheet-m2body[value="6"] ~ button.sheet-mt2-6, - input.sheet-m2body[value="7"] ~ button.sheet-mt2-7, - input.sheet-m2body[value="8"] ~ button.sheet-mt2-8, - input.sheet-m2body[value="9"] ~ button.sheet-mt2-9, - input.sheet-m2body[value="10"] ~ button.sheet-mt2-10, - input.sheet-m2body[value="11"] ~ button.sheet-mt2-11, - input.sheet-m2body[value="12"] ~ button.sheet-mt2-12, - input.sheet-m2body[value="13"] ~ button.sheet-mt2-13, - input.sheet-m2body[value="14"] ~ button.sheet-mt2-14, - input.sheet-m2body[value="15"] ~ button.sheet-mt2-15, - input.sheet-m2body[value="16"] ~ button.sheet-mt2-16, - input.sheet-m2body[value="17"] ~ button.sheet-mt2-17, - input.sheet-m2body[value="18"] ~ button.sheet-mt2-18, - input.sheet-m2body[value="19"] ~ button.sheet-mt2-19, - input.sheet-m2body[value="20"] ~ button.sheet-mt2-20, - input.sheet-m2body[value="21"] ~ button.sheet-mt2-21, - input.sheet-m2body[value="22"] ~ button.sheet-mt2-22, - input.sheet-m2body[value="23"] ~ button.sheet-mt2-23, - input.sheet-m2body[value="24"] ~ button.sheet-mt2-24, - input.sheet-m2body[value="25"] ~ button.sheet-mt2-25, - input.sheet-m2body[value="26"] ~ button.sheet-mt2-26, - input.sheet-m2body[value="27"] ~ button.sheet-mt2-27, - input.sheet-m2body[value="28"] ~ button.sheet-mt2-28, - input.sheet-m2body[value="29"] ~ button.sheet-mt2-29, - input.sheet-m2body[value="30"] ~ button.sheet-mt2-30, - input.sheet-m2body[value="31"] ~ button.sheet-mt2-31, - input.sheet-m2body[value="32"] ~ button.sheet-mt2-32, - input.sheet-m2body[value="33"] ~ button.sheet-mt2-33, - input.sheet-m2body[value="34"] ~ button.sheet-mt2-34, - input.sheet-m2body[value="35"] ~ button.sheet-mt2-35, - input.sheet-m2body[value="36"] ~ button.sheet-mt2-36, - input.sheet-m2body[value="37"] ~ button.sheet-mt2-37, - input.sheet-m2body[value="38"] ~ button.sheet-mt2-38, - input.sheet-m2body[value="39"] ~ button.sheet-mt2-39, - input.sheet-m2body[value="40"] ~ button.sheet-mt2-40, - input.sheet-m2body[value="41"] ~ button.sheet-mt2-41, - input.sheet-m2body[value="42"] ~ button.sheet-mt2-42, - input.sheet-m2body[value="43"] ~ button.sheet-mt2-43, - input.sheet-m2body[value="44"] ~ button.sheet-mt2-44, - input.sheet-m2body[value="45"] ~ button.sheet-mt2-45, - input.sheet-m2body[value="46"] ~ button.sheet-mt2-46, - input.sheet-m2body[value="47"] ~ button.sheet-mt2-47, - input.sheet-m2body[value="48"] ~ button.sheet-mt2-48, - input.sheet-m2body[value="49"] ~ button.sheet-mt2-49, - input.sheet-m2body[value="50"] ~ button.sheet-mt2-50{ + + input.m2body[value="0"] ~ button.mt2-0, + input.m2body[value="1"] ~ button.mt2-1, + input.m2body[value="2"] ~ button.mt2-2, + input.m2body[value="3"] ~ button.mt2-3, + input.m2body[value="4"] ~ button.mt2-4, + input.m2body[value="5"] ~ button.mt2-5, + input.m2body[value="6"] ~ button.mt2-6, + input.m2body[value="7"] ~ button.mt2-7, + input.m2body[value="8"] ~ button.mt2-8, + input.m2body[value="9"] ~ button.mt2-9, + input.m2body[value="10"] ~ button.mt2-10, + input.m2body[value="11"] ~ button.mt2-11, + input.m2body[value="12"] ~ button.mt2-12, + input.m2body[value="13"] ~ button.mt2-13, + input.m2body[value="14"] ~ button.mt2-14, + input.m2body[value="15"] ~ button.mt2-15, + input.m2body[value="16"] ~ button.mt2-16, + input.m2body[value="17"] ~ button.mt2-17, + input.m2body[value="18"] ~ button.mt2-18, + input.m2body[value="19"] ~ button.mt2-19, + input.m2body[value="20"] ~ button.mt2-20, + input.m2body[value="21"] ~ button.mt2-21, + input.m2body[value="22"] ~ button.mt2-22, + input.m2body[value="23"] ~ button.mt2-23, + input.m2body[value="24"] ~ button.mt2-24, + input.m2body[value="25"] ~ button.mt2-25, + input.m2body[value="26"] ~ button.mt2-26, + input.m2body[value="27"] ~ button.mt2-27, + input.m2body[value="28"] ~ button.mt2-28, + input.m2body[value="29"] ~ button.mt2-29, + input.m2body[value="30"] ~ button.mt2-30, + input.m2body[value="31"] ~ button.mt2-31, + input.m2body[value="32"] ~ button.mt2-32, + input.m2body[value="33"] ~ button.mt2-33, + input.m2body[value="34"] ~ button.mt2-34, + input.m2body[value="35"] ~ button.mt2-35, + input.m2body[value="36"] ~ button.mt2-36, + input.m2body[value="37"] ~ button.mt2-37, + input.m2body[value="38"] ~ button.mt2-38, + input.m2body[value="39"] ~ button.mt2-39, + input.m2body[value="40"] ~ button.mt2-40, + input.m2body[value="41"] ~ button.mt2-41, + input.m2body[value="42"] ~ button.mt2-42, + input.m2body[value="43"] ~ button.mt2-43, + input.m2body[value="44"] ~ button.mt2-44, + input.m2body[value="45"] ~ button.mt2-45, + input.m2body[value="46"] ~ button.mt2-46, + input.m2body[value="47"] ~ button.mt2-47, + input.m2body[value="48"] ~ button.mt2-48, + input.m2body[value="49"] ~ button.mt2-49, + input.m2body[value="50"] ~ button.mt2-50{ display: none; } - input.sheet-m3dot[value="0"] ~ button.sheet-mt3-0 > span.sheet-checked { + + input.m3dot[value="0"] ~ button.mt3-0 > span.checked { display: none; } - input.sheet-m3dot[value="1"] ~ button.sheet-mt3-1 > span.sheet-checked { + input.m3dot[value="1"] ~ button.mt3-1 > span.checked { display: none; } - input.sheet-m3dot[value="2"] ~ button.sheet-mt3-2 > span.sheet-checked { + input.m3dot[value="2"] ~ button.mt3-2 > span.checked { display: none; } - input.sheet-m3dot[value="3"] ~ button.sheet-mt3-3 > span.sheet-checked { + input.m3dot[value="3"] ~ button.mt3-3 > span.checked { display: none; } - input.sheet-m3dot[value="4"] ~ button.sheet-mt3-4 > span.sheet-checked { + input.m3dot[value="4"] ~ button.mt3-4 > span.checked { display: none; } - input.sheet-m3dot[value="5"] ~ button.sheet-mt3-5 > span.sheet-checked { + input.m3dot[value="5"] ~ button.mt3-5 > span.checked { display: none; } - input.sheet-m3dot[value="6"] ~ button.sheet-mt3-6 > span.sheet-checked { + input.m3dot[value="6"] ~ button.mt3-6 > span.checked { display: none; } - input.sheet-m3dot[value="7"] ~ button.sheet-mt3-7 > span.sheet-checked { + input.m3dot[value="7"] ~ button.mt3-7 > span.checked { display: none; } - input.sheet-m3dot[value="8"] ~ button.sheet-mt3-8 > span.sheet-checked { + input.m3dot[value="8"] ~ button.mt3-8 > span.checked { display: none; } - input.sheet-m3dot[value="9"] ~ button.sheet-mt3-9 > span.sheet-checked { + input.m3dot[value="9"] ~ button.mt3-9 > span.checked { display: none; } - input.sheet-m3dot[value="10"] ~ button.sheet-mt3-10 > span.sheet-checked { + input.m3dot[value="10"] ~ button.mt3-10 > span.checked { display: none; } - input.sheet-m3dot[value="11"] ~ button.sheet-mt3-11 > span.sheet-checked { + input.m3dot[value="11"] ~ button.mt3-11 > span.checked { display: none; } - input.sheet-m3dot[value="12"] ~ button.sheet-mt3-12 > span.sheet-checked { + input.m3dot[value="12"] ~ button.mt3-12 > span.checked { display: none; } - input.sheet-m3dot[value="13"] ~ button.sheet-mt3-13 > span.sheet-checked { + input.m3dot[value="13"] ~ button.mt3-13 > span.checked { display: none; } - input.sheet-m3dot[value="14"] ~ button.sheet-mt3-14 > span.sheet-checked { + input.m3dot[value="14"] ~ button.mt3-14 > span.checked { display: none; } - input.sheet-m3dot[value="15"] ~ button.sheet-mt3-15 > span.sheet-checked { + input.m3dot[value="15"] ~ button.mt3-15 > span.checked { display: none; } - input.sheet-m3dot[value="16"] ~ button.sheet-mt3-16 > span.sheet-checked { + input.m3dot[value="16"] ~ button.mt3-16 > span.checked { display: none; } - input.sheet-m3dot[value="17"] ~ button.sheet-mt3-17 > span.sheet-checked { + input.m3dot[value="17"] ~ button.mt3-17 > span.checked { display: none; } - input.sheet-m3dot[value="18"] ~ button.sheet-mt3-18 > span.sheet-checked { + input.m3dot[value="18"] ~ button.mt3-18 > span.checked { display: none; } - input.sheet-m3dot[value="19"] ~ button.sheet-mt3-19 > span.sheet-checked { + input.m3dot[value="19"] ~ button.mt3-19 > span.checked { display: none; } - input.sheet-m3dot[value="20"] ~ button.sheet-mt3-20 > span.sheet-checked { + input.m3dot[value="20"] ~ button.mt3-20 > span.checked { display: none; } - input.sheet-m3dot[value="21"] ~ button.sheet-mt3-21 > span.sheet-checked { + input.m3dot[value="21"] ~ button.mt3-21 > span.checked { display: none; } - input.sheet-m3dot[value="22"] ~ button.sheet-mt3-22 > span.sheet-checked { + input.m3dot[value="22"] ~ button.mt3-22 > span.checked { display: none; } - input.sheet-m3dot[value="23"] ~ button.sheet-mt3-23 > span.sheet-checked { + input.m3dot[value="23"] ~ button.mt3-23 > span.checked { display: none; } - input.sheet-m3dot[value="24"] ~ button.sheet-mt3-24 > span.sheet-checked { + input.m3dot[value="24"] ~ button.mt3-24 > span.checked { display: none; } - input.sheet-m3dot[value="25"] ~ button.sheet-mt3-25 > span.sheet-checked { + input.m3dot[value="25"] ~ button.mt3-25 > span.checked { display: none; } - input.sheet-m3dot[value="26"] ~ button.sheet-mt3-26 > span.sheet-checked { + input.m3dot[value="26"] ~ button.mt3-26 > span.checked { display: none; } - input.sheet-m3dot[value="27"] ~ button.sheet-mt3-27 > span.sheet-checked { + input.m3dot[value="27"] ~ button.mt3-27 > span.checked { display: none; } - input.sheet-m3dot[value="28"] ~ button.sheet-mt3-28 > span.sheet-checked { + input.m3dot[value="28"] ~ button.mt3-28 > span.checked { display: none; } - input.sheet-m3dot[value="29"] ~ button.sheet-mt3-29 > span.sheet-checked { + input.m3dot[value="29"] ~ button.mt3-29 > span.checked { display: none; } - input.sheet-m3dot[value="30"] ~ button.sheet-mt3-30 > span.sheet-checked { + input.m3dot[value="30"] ~ button.mt3-30 > span.checked { display: none; } - input.sheet-m3dot[value="31"] ~ button.sheet-mt32-31 > span.sheet-checked { + input.m3dot[value="31"] ~ button.mt32-31 > span.checked { display: none; } - input.sheet-m3dot[value="32"] ~ button.sheet-mt3-32 > span.sheet-checked { + input.m3dot[value="32"] ~ button.mt3-32 > span.checked { display: none; } - input.sheet-m3dot[value="33"] ~ button.sheet-mt3-33 > span.sheet-checked { + input.m3dot[value="33"] ~ button.mt3-33 > span.checked { display: none; } - input.sheet-m3dot[value="34"] ~ button.sheet-mt3-34 > span.sheet-checked { + input.m3dot[value="34"] ~ button.mt3-34 > span.checked { display: none; } - input.sheet-m3dot[value="35"] ~ button.sheet-mt3-35 > span.sheet-checked { + input.m3dot[value="35"] ~ button.mt3-35 > span.checked { display: none; } - input.sheet-m3dot[value="36"] ~ button.sheet-mt3-36 > span.sheet-checked { + input.m3dot[value="36"] ~ button.mt3-36 > span.checked { display: none; } - input.sheet-m3dot[value="37"] ~ button.sheet-mt3-37 > span.sheet-checked { + input.m3dot[value="37"] ~ button.mt3-37 > span.checked { display: none; } - input.sheet-m3dot[value="38"] ~ button.sheet-mt3-38 > span.sheet-checked { + input.m3dot[value="38"] ~ button.mt3-38 > span.checked { display: none; } - input.sheet-m3dot[value="39"] ~ button.sheet-mt3-39 > span.sheet-checked { + input.m3dot[value="39"] ~ button.mt3-39 > span.checked { display: none; } - input.sheet-m3dot[value="40"] ~ button.sheet-mt3-40 > span.sheet-checked { + input.m3dot[value="40"] ~ button.mt3-40 > span.checked { display: none; } - input.sheet-m3dot[value="41"] ~ button.sheet-mt3-41 > span.sheet-checked { + input.m3dot[value="41"] ~ button.mt3-41 > span.checked { display: none; } - input.sheet-m3dot[value="42"] ~ button.sheet-mt3-42 > span.sheet-checked { + input.m3dot[value="42"] ~ button.mt3-42 > span.checked { display: none; } - input.sheet-m3dot[value="43"] ~ button.sheet-mt3-43 > span.sheet-checked { + input.m3dot[value="43"] ~ button.mt3-43 > span.checked { display: none; } - input.sheet-m3dot[value="44"] ~ button.sheet-mt3-44 > span.sheet-checked { + input.m3dot[value="44"] ~ button.mt3-44 > span.checked { display: none; } - input.sheet-m3dot[value="45"] ~ button.sheet-mt3-45 > span.sheet-checked { + input.m3dot[value="45"] ~ button.mt3-45 > span.checked { display: none; } - input.sheet-m3dot[value="46"] ~ button.sheet-mt3-46 > span.sheet-checked { + input.m3dot[value="46"] ~ button.mt3-46 > span.checked { display: none; } - input.sheet-m3dot[value="47"] ~ button.sheet-mt3-47 > span.sheet-checked { + input.m3dot[value="47"] ~ button.mt3-47 > span.checked { display: none; } - input.sheet-m3dot[value="48"] ~ button.sheet-mt3-48 > span.sheet-checked { + input.m3dot[value="48"] ~ button.mt3-48 > span.checked { display: none; } - input.sheet-m3dot[value="49"] ~ button.sheet-mt3-49 > span.sheet-checked { + input.m3dot[value="49"] ~ button.mt3-49 > span.checked { display: none; } - input.sheet-m3dot[value="50"] ~ button.sheet-mt3-50 > span.sheet-checked { + input.m3dot[value="50"] ~ button.mt3-50 > span.checked { display: none; } - input.sheet-m3body[value="0"] ~ button.sheet-mt3-0, - input.sheet-m3body[value="1"] ~ button.sheet-mt3-1, - input.sheet-m3body[value="2"] ~ button.sheet-mt3-2, - input.sheet-m3body[value="3"] ~ button.sheet-mt3-3, - input.sheet-m3body[value="4"] ~ button.sheet-mt3-4, - input.sheet-m3body[value="5"] ~ button.sheet-mt3-5, - input.sheet-m3body[value="6"] ~ button.sheet-mt3-6, - input.sheet-m3body[value="7"] ~ button.sheet-mt3-7, - input.sheet-m3body[value="8"] ~ button.sheet-mt3-8, - input.sheet-m3body[value="9"] ~ button.sheet-mt3-9, - input.sheet-m3body[value="10"] ~ button.sheet-mt3-10, - input.sheet-m3body[value="11"] ~ button.sheet-mt3-11, - input.sheet-m3body[value="12"] ~ button.sheet-mt3-12, - input.sheet-m3body[value="13"] ~ button.sheet-mt3-13, - input.sheet-m3body[value="14"] ~ button.sheet-mt3-14, - input.sheet-m3body[value="15"] ~ button.sheet-mt3-15, - input.sheet-m3body[value="16"] ~ button.sheet-mt3-16, - input.sheet-m3body[value="17"] ~ button.sheet-mt3-17, - input.sheet-m3body[value="18"] ~ button.sheet-mt3-18, - input.sheet-m3body[value="19"] ~ button.sheet-mt3-19, - input.sheet-m3body[value="20"] ~ button.sheet-mt3-20, - input.sheet-m3body[value="21"] ~ button.sheet-mt3-21, - input.sheet-m3body[value="22"] ~ button.sheet-mt3-22, - input.sheet-m3body[value="23"] ~ button.sheet-mt3-23, - input.sheet-m3body[value="24"] ~ button.sheet-mt3-24, - input.sheet-m3body[value="25"] ~ button.sheet-mt3-25, - input.sheet-m3body[value="26"] ~ button.sheet-mt3-26, - input.sheet-m3body[value="27"] ~ button.sheet-mt3-27, - input.sheet-m3body[value="28"] ~ button.sheet-mt3-28, - input.sheet-m3body[value="29"] ~ button.sheet-mt3-29, - input.sheet-m3body[value="30"] ~ button.sheet-mt3-30, - input.sheet-m3body[value="31"] ~ button.sheet-mt3-31, - input.sheet-m3body[value="32"] ~ button.sheet-mt3-32, - input.sheet-m3body[value="33"] ~ button.sheet-mt3-33, - input.sheet-m3body[value="34"] ~ button.sheet-mt3-34, - input.sheet-m3body[value="35"] ~ button.sheet-mt3-35, - input.sheet-m3body[value="36"] ~ button.sheet-mt3-36, - input.sheet-m3body[value="37"] ~ button.sheet-mt3-37, - input.sheet-m3body[value="38"] ~ button.sheet-mt3-38, - input.sheet-m3body[value="39"] ~ button.sheet-mt3-39, - input.sheet-m3body[value="40"] ~ button.sheet-mt3-40, - input.sheet-m3body[value="41"] ~ button.sheet-mt3-41, - input.sheet-m3body[value="42"] ~ button.sheet-mt3-42, - input.sheet-m3body[value="43"] ~ button.sheet-mt3-43, - input.sheet-m3body[value="44"] ~ button.sheet-mt3-44, - input.sheet-m3body[value="45"] ~ button.sheet-mt3-45, - input.sheet-m3body[value="46"] ~ button.sheet-mt3-46, - input.sheet-m3body[value="47"] ~ button.sheet-mt3-47, - input.sheet-m3body[value="48"] ~ button.sheet-mt3-48, - input.sheet-m3body[value="49"] ~ button.sheet-mt3-49, - input.sheet-m3body[value="50"] ~ button.sheet-mt3-50{ + + input.m3body[value="0"] ~ button.mt3-0, + input.m3body[value="1"] ~ button.mt3-1, + input.m3body[value="2"] ~ button.mt3-2, + input.m3body[value="3"] ~ button.mt3-3, + input.m3body[value="4"] ~ button.mt3-4, + input.m3body[value="5"] ~ button.mt3-5, + input.m3body[value="6"] ~ button.mt3-6, + input.m3body[value="7"] ~ button.mt3-7, + input.m3body[value="8"] ~ button.mt3-8, + input.m3body[value="9"] ~ button.mt3-9, + input.m3body[value="10"] ~ button.mt3-10, + input.m3body[value="11"] ~ button.mt3-11, + input.m3body[value="12"] ~ button.mt3-12, + input.m3body[value="13"] ~ button.mt3-13, + input.m3body[value="14"] ~ button.mt3-14, + input.m3body[value="15"] ~ button.mt3-15, + input.m3body[value="16"] ~ button.mt3-16, + input.m3body[value="17"] ~ button.mt3-17, + input.m3body[value="18"] ~ button.mt3-18, + input.m3body[value="19"] ~ button.mt3-19, + input.m3body[value="20"] ~ button.mt3-20, + input.m3body[value="21"] ~ button.mt3-21, + input.m3body[value="22"] ~ button.mt3-22, + input.m3body[value="23"] ~ button.mt3-23, + input.m3body[value="24"] ~ button.mt3-24, + input.m3body[value="25"] ~ button.mt3-25, + input.m3body[value="26"] ~ button.mt3-26, + input.m3body[value="27"] ~ button.mt3-27, + input.m3body[value="28"] ~ button.mt3-28, + input.m3body[value="29"] ~ button.mt3-29, + input.m3body[value="30"] ~ button.mt3-30, + input.m3body[value="31"] ~ button.mt3-31, + input.m3body[value="32"] ~ button.mt3-32, + input.m3body[value="33"] ~ button.mt3-33, + input.m3body[value="34"] ~ button.mt3-34, + input.m3body[value="35"] ~ button.mt3-35, + input.m3body[value="36"] ~ button.mt3-36, + input.m3body[value="37"] ~ button.mt3-37, + input.m3body[value="38"] ~ button.mt3-38, + input.m3body[value="39"] ~ button.mt3-39, + input.m3body[value="40"] ~ button.mt3-40, + input.m3body[value="41"] ~ button.mt3-41, + input.m3body[value="42"] ~ button.mt3-42, + input.m3body[value="43"] ~ button.mt3-43, + input.m3body[value="44"] ~ button.mt3-44, + input.m3body[value="45"] ~ button.mt3-45, + input.m3body[value="46"] ~ button.mt3-46, + input.m3body[value="47"] ~ button.mt3-47, + input.m3body[value="48"] ~ button.mt3-48, + input.m3body[value="49"] ~ button.mt3-49, + input.m3body[value="50"] ~ button.mt3-50{ display: none; } -.sheet-dots { + +/* Container for dot buttons, using flexbox for alignment */ +.dots { display: flex; flex-wrap: wrap; justify-content: flex-start; -} -/*configure the main frame of the sheet, including the header image*/ -.sheet-main { +} + +/* Main container with border image and background color */ +.main { min-width: 850px; border: 20px solid transparent; padding: 1px; border-image: url(https://i.imgur.com/XxBv5A2.png) 30 round; border-image-outset: 1px; - background-color: #DCDCDC; -} -/*Configure the tabbed sections of the sheet*/ -/*Configure the tab buttons*/ -.sheet-character, -.sheet-skills, -.sheet-inventory, -.sheet-combat, -.sheet-magic, -.sheet-languages, -.sheet-biographical, -.sheet-documentation { - display: none; -} -/* show the selected tab */ -.sheet-tabstoggle[value="character"] ~ div.sheet-character, -.sheet-tabstoggle[value="inventory"] ~ div.sheet-inventory, -.sheet-tabstoggle[value="combat"] ~ div.sheet-combat, -.sheet-tabstoggle[value="magic"] ~ div.sheet-magic, -.sheet-tabstoggle[value="skills"] ~ div.sheet-skills, -.sheet-tabstoggle[value="languages"] ~ div.sheet-languages, -.sheet-tabstoggle[value="biographical"] ~ div.sheet-biographical, -.sheet-tabstoggle[value="documentation"] ~ div.sheet-documentation { - display: grid; - grid-gap: 5px; -} -.sheet-buttonbar { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-around; - align-items: flex-start; - width: auto; - border-style: double; - border-width: 6px; - padding: 0.75%; - margin-bottom: 5px; -} -/*define main tab pages*/ -.sheet-character { - width: auto; - height: auto; - grid-template-columns: 29% 34% 36%; - grid-template-rows: auto; - grid-template-areas: "common common common" "attributes afattributes finalcombatattributes" "atkdefattributes hpattributes finalcombatattributes" "evaattribute hpattributes finalcombatattributes" "mamdattributes mpattributes classcombatabilities" "steperattributes mpattributes classcombatabilities" "gapfillimg mpattributes classcombatabilities"; -} -.sheet-inventory { - width: auto; - height: auto; - grid-template-columns: 50% 50%; - grid-template-rows: auto; - grid-template-areas: "weapons weapons" "money armour" "encumbrance armour" "possessions possessions"; -} -.sheet-combat { - width: auto; - height: auto; - grid-template-rows: auto; - grid-template-areas: "basecharacteristics baseotherattributes" "basemeleeattributes baserangedattributes" "finalcombatattributes finalcombatattributes"; -} -.sheet-magic { - width: auto; - height: auto; - grid-template-columns: 34% 64%; - grid-template-rows: auto; - grid-template-areas: "allprofessionattribs spellbox" "allcastermana spellbox" "manabox spellbox"; -} -.sheet-skills { - width: auto; - height: auto; - grid-template-columns: auto; - grid-template-rows: auto; - grid-template-areas: "paths" "professionskills" "secondaryskills"; -} -.sheet-languages { - width: auto; - height: auto; - grid-template-columns: auto; - grid-template-rows: auto; - grid-template-areas: "modlang" "anclang"; -} -.sheet-biographical { - width: auto; - height: auto; - grid-template-columns: auto; - grid-template-rows: auto; - grid-template-areas: "basicbio"; -} -.sheet-documentation { - width: auto; - height: auto; - font-family: 'arial', sans-serif !important; - text-align: left; - border-style: double; - border-width: 6px; -} -/*define child elements*/ -/* columns */ -.sheet-col1 { - width: calc(66% - 12px); - display: inline-block; - margin-left: 15px; - vertical-align: top; -} -.sheet-col2 { - width: calc(33% - 12px); - display: inline-block; -} -.sheet-colequip { - width: calc(66% - 12px); - display: inline-block; -} -.sheet-colbackpack { - width: calc(33% - 12px); - display: inline-block; - vertical-align: top; -} -.sheet-inputscol { - width: calc(25% - 12px); - display: inline-block; -} -.sheet-skullcol { - width: calc(35% - 12px); - display: inline-block; - vertical-align: top; -} -.sheet-encumbrance { - grid-area: encumbrance; - display: grid; - grid-template-areas: "encumbranceheader encumbranceheader encumbranceheader" "liftclawcol encumbrancecol1 encumbrancecol2 "; -} -.sheet-encumbranceheader { - grid-area: encumbranceheader; -} -.sheet-encumbrancecol1 { - grid-area: encumbrancecol1; -} -.sheet-encumbrancecol2 { - grid-area: encumbrancecol2; -} -.sheet-liftclawcol { - grid-area: liftclawcol; -} -/* Child Elements on the Character Tab */ -.sheet-common { - grid-area: common; - border-style: double; - border-width: 6px; -} -.sheet-gapfillimg { - display: grid; - grid-area: gapfillimg; -} -.sheet-attributes { - grid-area: attributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "charhead charhead charhead" "char1 charscore1 button1" "char2 charscore2 button2" "char3 charscore3 button3" "char4 charscore4 button4" "char5 charscore5 button5"; -} -button.sheet-button1 { - grid-area: button1; -} -button.sheet-button2 { - grid-area: button2; -} -button.sheet-button3 { - grid-area: button3; -} -button.sheet-button4 { - grid-area: button4; -} -button.sheet-button5 { - grid-area: button5; -} -.sheet-char1 { - grid-area: char1; -} -.sheet-char2 { - grid-area: char2; -} -.sheet-char3 { - grid-area: char3; -} -.sheet-char4 { - grid-area: char4; -} -.sheet-char5 { - grid-area: char5; -} -.sheet-charscore1 { - grid-area: charscore1; -} -.sheet-charscore2 { - grid-area: charscore2; -} -.sheet-charscore3 { - grid-area: charscore3; -} -.sheet-charscore4 { - grid-area: charscore4; -} -.sheet-charscore5 { - grid-area: charscore5; -} -label.sheet-charheading { - grid-area: charhead; -} -.sheet-atkdefattributes { - grid-area: atkdefattributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "cfheading cfheading" "finalmeleelabel1 finalmeleebox1" "finalrangedlabel1 finalrangedbox1" "finalmeleelabel2 finalmeleebox2" "finalrangedlabel2 finalrangedbox2"; -} -.sheet-finalmeleelabel1 { - grid-area: finalmeleelabel1; - text-align: center; -} -.sheet-finalmeleelabel2 { - grid-area: finalmeleelabel2; - text-align: center; -} -.sheet-finalmeleebox1 { - grid-area: finalmeleebox1; -} -.sheet-finalmeleebox2 { - grid-area: finalmeleebox2; -} -.sheet-finalrangedlabel1 { - grid-area: finalrangedlabel1; - text-align: center; -} -.sheet-finalrangedlabel2 { - grid-area: finalrangedlabel2; - text-align: center; -} -.sheet-finalrangedbox1 { - grid-area: finalrangedbox1; -} -.sheet-finalrangedbox2 { - grid-area: finalrangedbox2; -} -.sheet-cf1 { - grid-area: cf1; -} -.sheet-cf2 { - grid-area: cf2; -} -.sheet-cfa { - grid-area: cfa; -} -.sheet-cfd { - grid-area: cfd; -} -label.sheet-cfheading { - grid-area: cfheading; -} -.sheet-mabrlabel1 { - grid-area: mabrlabel1; -} -.sheet-mdamlabel1 { - grid-area: mdamlabel1; -} -.sheet-rabrlabel1 { - grid-area: rabrlabel1; -} -.sheet-rdamlabel1 { - grid-area: rdamlabel1; -} -.sheet-mabrbox1 { - grid-area: mabrbox1; -} -.sheet-mdambox1 { - grid-area: mdambox1; -} -.sheet-rabrbox1 { - grid-area: rabrbox1; -} -.sheet-rdambox1 { - grid-area: rdambox1; -} -.sheet-evaattribute { - grid-area: evaattribute; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "dodgehead dodgehead" "dodge evade" "finaldodge finalevade"; -} -.sheet-dodge { - grid-area: dodge; + background-color: var(--primary-bg-color); } -.sheet-evade { - grid-area: evade; -} -.sheet-finaldodge { - grid-area: finaldodge; - text-align: center; -} -.sheet-finalevade { - grid-area: finalevade; -} -label.sheet-dodgeheading { - grid-area: dodgehead; -} -.sheet-mamdattributes { - grid-area: mamdattributes; - border-style: double; - border-width: 6px; - text-align: justify; - text-justify: inter-word; - justify-content: space-around; - display: grid; - grid-template-areas: "mcfheading mcfheading" "mcf1 mcfma" "finalmagicalattacklabel finalmagicalattackbox" "mcf2 mcfmd" "finalmagicaldefencelabel finalmagicaldefencebox"; -} -.sheet-finalmagicalattacklabel { - grid-area: finalmagicalattacklabel; - text-align: center; -} -.sheet-finalmagicalattackbox { - grid-area: finalmagicalattackbox; -} -.sheet-finalmagicaldefencelabel { - grid-area: finalmagicaldefencelabel; - text-align: center; -} -.sheet-finalmagicaldefencebox { - grid-area: finalmagicaldefencebox; -} -label.sheet-mcfheading { - grid-area: mcfheading; + + /* Button bar with flexbox layout and double border */ + .buttonbar { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-around; + align-items: flex-start; + width: auto; + border-style: double; + border-width: 6px; + padding: 0.75%; + margin-bottom: 5px; + } + + .character { + grid-area: character; + display: grid; + grid-template-areas: + "common common common" + "primaryattributes afattributes finalcombatattributes" + "finalattackdefenceattributes afattributes finalcombatattributes" + "evasionattribute hpattributes finalcombatattributes" + "stealthperceptionattributes hpattributes finalcombatattributes" + "mamdattributes hpattributes finalcombatattributes" + "gapfillimg mpattributes classcombatabilities"; + + /* Set all columns to equal width (1fr) */ + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: auto; /* Automatically adjust row height */ + gap: 10px; /* Space between grid items */ + } + + .common { + grid-area: common; + display: grid; + grid-template-columns: 2fr 2fr 1fr 1fr; /* Adjusts column widths */ + grid-template-areas: + "name profession rank experience"; + gap: 5px; /* Space between the elements */ + background-color: var(--primary-bg-color); /* Match the background color of .main */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 3px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically center the labels and inputs */ + } + + /* Ensure the labels and inputs are aligned correctly */ + .common .label-input-pair { + display: flex; + flex-direction: column; /* Arrange label and input vertically */ + align-items: start; /* Align items to the start of the container */ + } + + .common label { + margin-bottom: 5px; /* Space between label and input */ + font-size: 19px; + } + + .common input { + width: 100%; /* Ensure inputs fill their grid area */ + box-sizing: border-box; + } + + /* Assign areas to each pair */ + .name { + grid-area: name; + } + + .profession { + grid-area: profession; + } + + .rank { + grid-area: rank; + } + + .experience { + grid-area: experience; + } + + .primaryattributes { + display: grid; + grid-area: primaryattributes; + grid-template-columns: 1fr 1fr auto; /* Columns: name, input, button */ + grid-template-areas: + "primaryattribheader primaryattribheader primaryattribheader" + "name1 input1 button1" + "name2 input2 button2" + "name3 input3 button3" + "name4 input4 button4" + "name5 input5 button5"; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .primaryattributes h2 { + grid-column: 1 / -1; /* Header spans all columns */ + text-align: center; + font-size: 19px; + margin-bottom: 10px; + grid-area: primaryattribheader; + } + + .primaryattributes > div:nth-of-type(1) { + grid-area: name1; + } + + .primaryattributes > div:nth-of-type(2) { + grid-area: input1; + } + + .primaryattributes > div:nth-of-type(3) { + grid-area: button1; + } + + .primaryattributes > div:nth-of-type(4) { + grid-area: name2; + } + + .primaryattributes > div:nth-of-type(5) { + grid-area: input2; + } + + .primaryattributes > div:nth-of-type(6) { + grid-area: button2; + } + + .primaryattributes > div:nth-of-type(7) { + grid-area: name3; + } + + .primaryattributes > div:nth-of-type(8) { + grid-area: input3; + } + + .primaryattributes > div:nth-of-type(9) { + grid-area: button3; + } + + .primaryattributes > div:nth-of-type(10) { + grid-area: name4; + } + + .primaryattributes > div:nth-of-type(11) { + grid-area: input4; + } + + .primaryattributes > div:nth-of-type(12) { + grid-area: button4; + } + + .primaryattributes > div:nth-of-type(13) { + grid-area: name5; + } + + .primaryattributes > div:nth-of-type(14) { + grid-area: input5; + } + + .primaryattributes > div:nth-of-type(15) { + grid-area: button5; + } + + /* Combat Factors section styling */ + .finalattackdefenceattributes { + display: grid; + grid-area: finalattackdefenceattributes; + grid-template-columns: 1fr 1fr; /* Two columns: one for labels and one for inputs */ + grid-template-areas: + "finalattackdefenceheader finalattackdefenceheader" + "meleeattacklabel meleeattackinput" + "meleedefencelabel meleedefenceinput" + "rangedattacklabel rangedattackinput" + "rangeddefencelabel rangeddefenceinput"; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .finalattackdefenceattributes h2 { + grid-column: 1 / -1; /* Span the header across all columns */ + text-align: center; + font-size: 19px; + margin-bottom: 10px; + grid-area: finalattackdefenceheader; + } + + .finalattackdefenceattributes .finalmeleelabel1 { + grid-area: meleeattacklabel; + } + + .finalattackdefenceattributes .finalrangedlabel1 { + grid-area: rangedattacklabel; + } + + .finalattackdefenceattributes .finalmeleebox1 { + grid-area: meleeattackinput; + } + + .finalattackdefenceattributes .finalrangedbox1 { + grid-area: rangedattackinput; + } + + .finalattackdefenceattributes .finalmeleelabel2 { + grid-area: meleedefencelabel; + } + + .finalattackdefenceattributes .finalrangedlabel2 { + grid-area: rangeddefencelabel; + } + + .finalattackdefenceattributes .finalmeleebox2 { + grid-area: meleedefenceinput; + } + + .finalattackdefenceattributes .finalrangedbox2 { + grid-area: rangeddefenceinput; + } + + /* Ensure inputs and labels are styled consistently */ + .finalattackdefenceattributes div { + background-color: var(--primary-bg-color); /* Primary background color for divs */ + } + + .finalattackdefenceattributes input { + background-color: var(--bg-color); /* Background color for inputs */ + border: 1px solid var(--border-color); /* Border styling for inputs */ + border-radius: var(--border-radius); /* Border radius for inputs */ + padding: var(--padding); /* Padding for inputs */ + } + + .evasionattribute { + display: grid; + grid-area: evasionattribute; + grid-template-columns: 1fr 1fr; /* Two columns: one for labels and one for inputs */ + grid-template-areas: + "evadeheader evadeheader" + "finaldodge finalevade"; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .evasionattribute h2 { + grid-column: 1 / -1; /* Span the header across all columns */ + text-align: center; + font-size: 19px; + margin-bottom: 10px; + grid-area: evadeheader; + } + + .evasionattribute .finaldodge { + grid-area: finaldodge; + } + + .evasionattribute .finalevade { + grid-area: finalevade; + } + + .mamdattributes { + display: grid; + grid-area: mamdattributes; + grid-template-columns: 1fr 1fr; /* Two columns: one for labels and one for inputs */ + grid-template-areas: + "mamdheader mamdheader" + "magicalattacklabel magicalattackinput" + "magicaldefencelabel magicaldefenceinput"; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .mamdattributes h2 { + grid-area: mamdheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + .mamdattributes .magicalattacklabel { + grid-area: magicalattacklabel; + } + + .mamdattributes .magicalattackinput { + grid-area: magicalattackinput; + } + + .mamdattributes .magicaldefencelabel { + grid-area: magicaldefencelabel; + } + + .mamdattributes .magicaldefenceinput { + grid-area: magicaldefenceinput; + } + + .stealthperceptionattributes { + display: grid; + grid-area: stealthperceptionattributes; + grid-template-columns: 1fr 1fr 1fr; /* Three columns: name, input, buttons */ + grid-template-areas: + "stealthperceptheader stealthperceptheader stealthperceptheader" + "stealthlabel stealthinput stealthbuttons" + "perceptionlabel perceptioninput perceptionbuttons"; + gap: 5px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .stealthperceptionattributes h2 { + grid-area: stealthperceptheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + /* Stealth section */ + .stealthperceptionattributes > div:nth-of-type(1) { + grid-area: stealthlabel; + } + .stealthperceptionattributes > div:nth-of-type(2) { + grid-area: stealthinput; + } + .stealthperceptionattributes > div:nth-of-type(3) { + grid-area: stealthbuttons; + display: flex; + gap: 5px; /* Space between buttons */ + } + + /* Perception section */ + .stealthperceptionattributes > div:nth-of-type(4) { + grid-area: perceptionlabel; + } + .stealthperceptionattributes > div:nth-of-type(5) { + grid-area: perceptioninput; + } + .stealthperceptionattributes > div:nth-of-type(6) { + grid-area: perceptionbuttons; + display: flex; + gap: 5px; /* Space between buttons */ + } + + .stealthperceptionattributes button { + margin: 0 5px; + } + + .gapfillimg { + grid-area: gapfillimg; + } + + .hpattributes { + grid-area: hpattributes; + display: grid; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .hpattributes h2 { + grid-column: 1 / -1; /* Span the header across all columns */ + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + + .afattributes { + display: grid; + grid-area: afattributes; + grid-template-columns: 1fr 1fr; /* Adjust column widths */ + grid-template-areas: + "afattribheader afattribheader" + "imgshieldcol aftype" + "imgshieldcol aftypeinput" + "imgshieldcol afname" + "imgshieldcol afinput" + "shieldbox shieldbox" + "shieldtogglebox shieldtogglebox"; + gap: 5px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .afattributes h2 { + grid-area: afattribheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + /* Assign grid areas based on class names */ + .afattributes .imgshieldcol { + grid-area: imgshieldcol; + display: flex; + justify-content: center; + align-items: center; + } + + .afattributes .aftype { + grid-area: aftype; + display: flex; + align-items: center; + } + + .afattributes .aftypeinput { + grid-area: aftypeinput; + } + + .afattributes .afname { + grid-area: afname; + display: flex; + align-items: center; + } + + .afattributes .afinput { + grid-area: afinput; + } + + .afattributes .shieldbox { + grid-area: shieldbox; + display: flex; + align-items: center; + } + + .shieldtogglebox { + grid-area: shieldtogglebox; + } + + .afattributes .shieldhidden { + grid-area: shieldhidden; + grid-template-areas: + "shielddie shieldbutton"; + } + .shielddie { + grid-area: shielddie; + } + + .shieldbutton { + grid-area: shieldbutton; + } + + .finalcombatattributes { + grid-area: finalcombatattributes; + display: grid; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-columns: 1fr 1fr; /* Ensures all elements stack in a single column */ + grid-template-areas: + "finalcombatheader finalcombatheader" + "meleeattack1 meleeattack1" + "equippedweaponbox equippedweaponbox" + "abrbox abrbox" + "damagebox damagebox" + "swordimage swordimage" + "rangedattack1 rangedattack1" + "equippedrangedweaponbox equippedrangedweaponbox" + "equippedammobox equippedammobox" + "rangedabrbox rangedabrbox" + "rangeddamagebox rangeddamagebox" + "bowimage rangedweaponranges" + + } + .finalcombatattributes h2 { + grid-area: finalcombatheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + + .meleeattack1 { + grid-area: meleeattack1; + } + + .equippedweaponbox { + grid-area: equippedweaponbox; + } + + .abrbox { + grid-area: abrbox; + } + + .damagebox { + grid-area: damagebox; + } + + .rangedattack1 { + grid-area: rangedattack1; + } + + .equippedrangedweaponbox { + grid-area: equippedrangedweaponbox; + } + + .equippedammobox { + grid-area: equippedammobox; + } + + .rangedabrbox { + grid-area: rangedabrbox; + } + + .rangeddamagebox { + grid-area: rangeddamagebox; + } + + .rangedweaponranges { + grid-area: rangedweaponranges; + } + + .swordimage { + grid-area: swordimage; + } + + .bowimage { + grid-area: bowimage; + } + + .classcombatabilities { + grid-area: classcombatabilities; + display: grid; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-columns: 1fr; /* Ensures all elements stack in a single column */ + grid-template-areas: + "classcombatabilitiesheader" + "skills_known" + "melee"; /* Updated to ensure these appear in one column */ + } + + .classcombatabilities h2 { + grid-area: classcombatabilitiesheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + .skills_known { + grid-area: skills_known; + } + + .melee { + grid-area: melee; + } + + .melee h2 { + grid-row: 1; + grid-column: 1 / -1; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + .mpattributes { + grid-area: mpattributes; + display: grid; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-columns: 1fr; /* Ensures all elements stack in a single column */ + grid-template-areas: + "mpattribheader" + "mpattributeshidden" + "nonmartialhidden" + "martialhidden"; + } + + .mpattributes h2 { + grid-area: mpattribheader; + text-align: center; + font-size: 19px; + margin-bottom: 10px; + } + + .mpattributeshidden { + grid-area: mpattributeshidden; + } + + .nonmartialhidden { + grid-area: nonmartialhidden; + } + + .martialhidden { + grid-area: martialhidden; + } + + /* Grid layout for combat section */ + .basescores { + grid-area: basescores; + display: grid; + grid-template-columns: repeat(2, 1fr); /* Three equal columns */ + grid-template-rows: auto; /* Automatically adjust row height */ + gap: 10px; /* Space between grid items */ + grid-template-areas: + "basecharacteristics baseattributes" + "basemeleeattributes baserangedattributes" + "finalbasecombatattributes finalbasecombatattributes"; + } + + .basecharacteristics { + grid-area: basecharacteristics; + display: grid; + grid-template-columns: 1fr 1fr 1fr; /* Adjust column widths as needed */ + grid-template-areas: + "basecharheader basecharheader basecharheader" + "characteristic base modifier" + "strength base-strength modifier-strength" + "reflexes base-reflexes modifier-reflexes" + "intelligence base-intelligence modifier-intelligence" + "psychic-talent base-psychic-talent modifier-psychic-talent" + "looks base-looks modifier-looks" + "stats-controls stats-controls stats-controls"; /* Added for roll stats container */ + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically aligns the content */ + justify-items: center; /* Aligns items horizontally */ + } + + .basecharacteristics h2 { + grid-area: basecharheader; + text-align: center; + margin-bottom: 10px; + } + + .basecharacteristics h3.characteristic { + grid-area: characteristic; + text-align: center; + font-weight: bold; + } + + .basecharacteristics h3.base { + grid-area: base; + text-align: center; + font-weight: bold; + } + + .basecharacteristics h3.modifier { + grid-area: modifier; + text-align: center; + font-weight: bold; + } + + .basecharacteristics > div:nth-of-type(1) { + grid-area: strength; /* 4th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(2) { + grid-area: base-strength; /* 5th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(3) { + grid-area: modifier-strength; /* 6th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(4) { + grid-area: reflexes; /* 7th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(5) { + grid-area: base-reflexes; /* 8th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(6) { + grid-area: modifier-reflexes; /* 9th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(7) { + grid-area: intelligence; /* 10th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(8) { + grid-area: base-intelligence; /* 11th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(9) { + grid-area: modifier-intelligence; /* 12th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(10) { + grid-area: psychic-talent; /* 13th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(11) { + grid-area: base-psychic-talent; /* 14th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(12) { + grid-area: modifier-psychic-talent; /* 15th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(13) { + grid-area: looks; /* 16th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(14) { + grid-area: base-looks; /* 17th overall child */ + align-items: center; + } + + .basecharacteristics > div:nth-of-type(15) { + grid-area: modifier-looks; /* 18th overall child */ + align-items: center; + } + + .rollbasestatssetcontainer { + grid-area: stats-controls; + justify-content: center; + align-items: center; + border: none; + gap: 10px; + display: flex; + } + + .rollbasestatsbuttoncontainer { + grid-area: rollbasestatsbuttoncontainer; + } + + .baseattributes { + grid-area: baseattributes; + display: grid; + grid-template-columns: 1fr 1fr 1fr; /* Adjust column widths as needed */ + grid-template-areas: + "baseattrheader baseattrheader baseattrheader" + "attribute base modifier" + "attack base-attack modifier-attack" + "defence base-defence modifier-defence" + "stealth base-stealth modifier-stealth" + "perception base-perception modifier-perception" + "evasion base-evasion modifier-evasion" + "maxhp base-maxhp modifier-maxhp" + "hp-controls hp-controls hp-controls"; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically aligns the content */ + justify-items: center; /* Aligns items horizontally */ + } + + .baseattributes h2 { + grid-area: baseattrheader; + text-align: center; + margin-bottom: 10px; + } + + .baseattributes h3.attribute { + grid-area: attribute; + text-align: center; + font-weight: bold; + } + + .baseattributes h3.base { + grid-area: base; + text-align: center; + font-weight: bold; + } + + .baseattributes h3.modifier { + grid-area: modifier; + text-align: center; + font-weight: bold; + } + + .baseattributes > div:nth-of-type(1) { + grid-area: attack; + align-items: center; + } + + .baseattributes > div:nth-of-type(2) { + grid-area: base-attack; + align-items: center; + } + + .baseattributes > div:nth-of-type(3) { + grid-area: modifier-attack; + align-items: center; + } + + .baseattributes > div:nth-of-type(4) { + grid-area: defence; + align-items: center; + } + + .baseattributes > div:nth-of-type(5) { + grid-area: base-defence; + align-items: center; + } + + .baseattributes > div:nth-of-type(6) { + grid-area: modifier-defence; + align-items: center; + } + + .baseattributes > div:nth-of-type(7) { + grid-area: stealth; + align-items: center; + } + + .baseattributes > div:nth-of-type(8) { + grid-area: base-stealth; + align-items: center; + } + + .baseattributes > div:nth-of-type(9) { + grid-area: modifier-stealth; + align-items: center; + } + + .baseattributes > div:nth-of-type(10) { + grid-area: perception; + align-items: center; + } + + .baseattributes > div:nth-of-type(11) { + grid-area: base-perception; + align-items: center; + } + + .baseattributes > div:nth-of-type(12) { + grid-area: modifier-perception; + align-items: center; + } + + .baseattributes > div:nth-of-type(13) { + grid-area: evasion; + align-items: center; + } + + .baseattributes > div:nth-of-type(14) { + grid-area: base-evasion; + align-items: center; + } + + .baseattributes > div:nth-of-type(15) { + grid-area: modifier-evasion; + align-items: center; + } + + .baseattributes > div:nth-of-type(16) { + grid-area: maxhp; + align-items: center; + } + + .baseattributes > div:nth-of-type(17) { + grid-area: base-maxhp; + align-items: center; + } + + .baseattributes > div:nth-of-type(18) { + grid-area: modifier-maxhp; + align-items: center; + } + + .rollbasehpsetcontainer { + grid-area: hp-controls; + justify-content: center; + align-items: left; + gap: 10px; + display: flex; + border: none; + } + + .rollbasehpbuttoncontainer { + grid-area: rollbasehpbuttoncontainer; + } + + .basemeleeattributes { + display: grid; + grid-area: basemeleeattributes; + grid-template-columns: 1fr 1fr; /* Two columns for Attribute and Modifier */ + grid-template-areas: + "basemeleeheader basemeleeheader" + "attribute modifier" + "attack modifier-attack" + "defence modifier-defence" + "armour-bypass modifier-armour-bypass" + "damage modifier-damage"; + gap: 5px; + background-color: var(--primary-bg-color); /* Ensure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically aligns the content */ + justify-items: center; /* Aligns items horizontally */ + } + + .basemeleeattributes h2 { + grid-area: basemeleeheader; + text-align: center; + margin-bottom: 10px; + } + + .basemeleeattributes h3.attribute { + grid-area: attribute; + text-align: center; + font-weight: bold; + } + + .basemeleeattributes h3.modifier { + grid-area: modifier; + text-align: center; + font-weight: bold; + } + + .basemeleeattributes > div:nth-of-type(1) { + grid-area: attack; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(2) { + grid-area: modifier-attack; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(3) { + grid-area: defence; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(4) { + grid-area: modifier-defence; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(5) { + grid-area: armour-bypass; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(6) { + grid-area: modifier-armour-bypass; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(7) { + grid-area: damage; + align-items: center; + } + + .basemeleeattributes > div:nth-of-type(8) { + grid-area: modifier-damage; + align-items: center; + } + + .baserangedattributes { + display: grid; + grid-area: baserangedattributes; + grid-template-columns: 1fr 1fr; /* Two columns for Attribute and Modifier */ + grid-template-areas: + "baserangedheader baserangedheader" + "attribute modifier" + "attack modifier-attack" + "defence modifier-defence" + "armour-bypass modifier-armour-bypass" + "damage modifier-damage"; + gap: 5px; + background-color: var(--primary-bg-color); /* Ensure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically aligns the content */ + justify-items: center; /* Aligns items horizontally */ + } + + .baserangedattributes h2 { + grid-area: baserangedheader; + text-align: center; + margin-bottom: 10px; + } + + .baserangedattributes h3.attribute { + grid-area: attribute; + text-align: center; + font-weight: bold; + } + + .baserangedattributes h3.modifier { + grid-area: modifier; + text-align: center; + font-weight: bold; + } + + .baserangedattributes > div:nth-of-type(1) { + grid-area: attack; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(2) { + grid-area: modifier-attack; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(3) { + grid-area: defence; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(4) { + grid-area: modifier-defence; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(5) { + grid-area: armour-bypass; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(6) { + grid-area: modifier-armour-bypass; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(7) { + grid-area: damage; + align-items: center; + } + + .baserangedattributes > div:nth-of-type(8) { + grid-area: modifier-damage; + align-items: center; + } + + .finalbasecombatattributes { + display: grid; + grid-area: finalbasecombatattributes; + grid-template-columns: 1fr 1fr 1fr 1fr; /* Four columns: melee h3, melee input, ranged h3, ranged input */ + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + .finalbasecombatattributes h2 { + grid-column: 1 / span 4; /* Span across all four columns */ + text-align: center; + margin-bottom: 10px; + } + + .finalbasecombatattributes h3 { + margin: 0; /* Remove default margin for tighter layout */ + } + + .finalbasecombatattributes input { + width: 100%; + box-sizing: border-box; /* Ensure inputs don't overflow their containers */ + padding: 5px; + + } + + /* Grid layout for magic section */ + .magic { + grid-area: magic; + grid-template-columns: 1fr 1fr 1fr; + display: grid; + grid-template-areas: + "manabox allprofessionattribs allcastermana" + "spellbox spellbox spellbox"; + } + .allprofessionattribs { + display: grid; + grid-area: allprofessionattribs; + grid-template-columns: 1fr 1fr; /* Two equal columns */ + grid-template-rows: auto auto auto; /* Adjust rows automatically */ + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + .allprofessionattribs h2 { + grid-column: span 2; /* Make the header span across both columns */ + text-align: center; + margin-bottom: 10px; + } + + .allprofessionattribs h3 { + text-align: left; + font-weight: bold; + } + + .allprofessionattribs input { + width: 100%; + padding: 5px; + text-align: center; + } + + .allcastermana { + display: grid; + grid-area: allcastermana; + grid-template-columns: 1fr 1fr; /* Two equal columns */ + grid-template-rows: auto auto auto; /* Adjust rows automatically */ + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + .allcastermana h2 { + grid-column: span 2; /* Make the header span across both columns */ + text-align: center; + margin-bottom: 10px; + } + + .allcastermana h3 { + text-align: left; + font-weight: bold; + } + + .allcastermana input { + width: 100%; + padding: 5px; + text-align: center; + } + + .manabox { + display: grid; + grid-area: manabox; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + .mana h3 { + margin-bottom: 5px; + font-weight: bold; + } + + .mana button, .mana input, .mana select { + width: 100%; + padding: 5px; + text-align: center; + margin-bottom: 10px; + } + + .spellbox { + grid-area: spellbox; + display: grid; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-columns: 1fr; + grid-template-areas: + "spells"; + } + + .spells { + grid-area: spells; + } + + .spell-entry { + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + padding: 10px; + margin-bottom: 10px; + background-color: var(--primary-bg-color); + } + + .spell-entry > div { /* Targets the direct children divs within .spell-entry */ + margin-bottom: 5px; + } + + .spell_name, + .spell_range, + .spell_duration, + .spell_replaces, + .spell_rarity, + .spell_origin { + font-weight: bold; + } + + .spell_name { /* Style the spell name */ + font-size: 22px; /* Increased font size */ + font-weight: 700; /* Bolder font weight */ + } + + .spell_desc p { + font-size: 18px; /* Reduced font size for descriptions */ + font-family: 'Macondo', serif; + } + + .spell_darkness p { + font-size: 18px; /* Reduced font size for darkness descriptions */ + font-family: 'Macondo', serif; + } + + /* Grid layout for inventory section */ + .inventory { + grid-area: inventory; + grid-template-rows: max-content; /* Automatically adjust row height */ + gap: 10px; /* Space between grid items */ + grid-template-areas: + "weapons weapons" + "possessions armour" + "money encumbrance"; + } + + /* Grid Layout for Weapons Section */ + .weapons { + display: grid; + grid-area: weapons; + grid-template-columns: 1fr; + grid-template-areas: + "meleeweapons" + "rangedweapons" + "ammunition"; + } + + .meleeweapons { + grid-area: meleeweapons; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .rangedweapons { + grid-area: rangedweapons; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + .ammunition { + grid-area: ammunition; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + } + + input.equip-toggle[value="1"] + div.hidden-row { + border: 5px double var(--hover-border-color); + background-color: var(--hover-bg-color); /* Make sure this matches your design */ + } + + /* Armour Section Layout */ + .armour { + display: grid; + grid-area: armour; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-areas: + "armheader armheader" + "armourtypelist armourtypelist" + "basearmourdetails basearmourdetails" + "subheader subheader" + "armourproficiencypenalties armourproficiencypenalties" + "skullimage shieldtogglebox"; + + } + + /* Full-width headings */ + .armour h2 { + text-align: center; + font-size: 19px; + grid-area: armheader; + } + + .armour h3 { + text-align: center; + font-size: 19px; + grid-area: subheader; + } + + .armour .armourtypelist { + grid-area: armourtypelist; + } + + .armour .basearmourdetails { + grid-area: basearmourdetails; + } + + .armour .armourproficiencypenalties { + grid-area: armourproficiencypenalties; + } + + .armour .shieldtogglebox { + grid-area: shieldtogglebox; + } + + .armour .skullimage { + grid-area: skullimage; + } + + .armour .shieldhidden { + grid-area: shieldhidden; + grid-template-areas: + "shielddie" + "shieldbutton"; + } + .shielddie { + grid-area: shielddie; + } + .shieldbutton { + grid-area: shieldbutton; + } + + + /* General Section Styling */ + .money { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-areas: + "moneyheader moneyheader" + "image goldcrowns" + "image silverflorins" + "image copperpennies" + "otherwealth otherwealth"; + } + + /* Title Styling */ + .money h2 { + grid-row: 1; + grid-column: 1 / span 2; + text-align: center; + font-size: 19px; + grid-area: moneyheader; + } + + .money .goldcrowns { + grid-area: goldcrowns; + } + + .money .silverflorins { + grid-area: silverflorins; + + } + + .money .copperpennies { + grid-area: copperpennies; + } + /* Icon Images */ + .money .chestimage { + grid-area: image; + align-items: center; + justify-content: center; + } + + .money .otherwealth { + grid-area: otherwealth; + align-items: left; + justify-content: center; + + } + + .possessions { + display: grid; + grid-area: possessions; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-rows: max-content; + grid-template-areas: + "posheader" + "inventoryitems" + "repcontrols"; + } + + /* Full-width headings */ + .possessions h2 { + grid-row: 1; + text-align: center; + font-size: 19px; + grid-area: posheader; + } + + .charsheet .repcontainer[data-groupname="repeating_inventoryitems"] { + grid-area: inventoryitems; + display: grid; + align-self: start; + } + + .charsheet .repcontainer[data-groupname="repeating_inventoryitems"] > .repitem { + border: 1px solid var(--hover-border-color); + background-color: var(--hover-bg-color); /* Make sure this matches your design */ + margin: 1px; + } + + .charsheet .repcontrol[data-groupname="repeating_inventoryitems"] { + grid-area: repcontrols; + align-self: start; + } + + .encumbrance { + display: grid; + grid-area: encumbrance; + grid-template-columns: repeat(2fr 1fr); + gap: 5px; + background-color: var(--primary-bg-color); /* Make sure this matches your design */ + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + grid-template-areas: + "encheader encheader" + "encumbrancecontainer clawimage" + } + + /* Full-width headings */ + .encumbrance h2 { + grid-column: span 4; + text-align: center; + font-size: 19px; + grid-area: encheader; + } + + .encumbrance .encumbrancecontainer { + grid-area: encumbrancecontainer; + } + + .encumbrance .clawimage { + grid-area: clawimage; + } + + /* General Grid Layout for Skills Section */ + .skills { + grid-area: skills; + display: grid; + grid-template-rows: auto; /* Automatically adjust row height */ + gap: 10px; /* Space between grid items */ + grid-template-areas: + "professionskillscontainer" + "pathscontainer" + "secondaryskillscontainer"; + } + + .professionskillscontainer { + grid-area: professionskillscontainer; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + /* Arrange counter-boxes horizontally */ + .counter-container { + display: flex; + justify-content: space-between; + flex-wrap: wrap; /* Allows boxes to wrap on smaller screens */ + gap: 20px; + } + + .counterbox { + display: flex; + flex-direction: column; + border: 1px solid var(--border-color); + padding: 10px; + flex: 1 1 200px; /* Flex-grow and flex-shrink for dynamic width */ + min-width: 200px; /* Ensure counterboxes don't shrink too small */ + } + + .counterfields { + display: flex; + flex-direction: column; + } + + .skillrow details { + width: 100%; + padding: 10px 0; + } + + /* Layout for checkboxes and the dice roll */ + .skillrow > details > div { + align-items: center; + justify-content: flex-start; + } + + .pathscontainer { + grid-area: pathscontainer; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + + .secondaryskillscontainer { + grid-area: secondaryskillscontainer; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } + +/* Grid layout for languages section */ +.languages { + grid-area: languages; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } -.sheet-mcf1 { - grid-area: mcf1; + +/* Grid layout for biographical section */ +.biographical { + grid-area: biographical; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } -.sheet-mcf2 { - grid-area: mcf2; + +/* Documentation section with custom font and border style */ +.documentation { + grid-area: documentation; + gap: 10px; + background-color: var(--primary-bg-color); + padding: var(--padding); + border-radius: var(--border-radius); + border: 5px double var(--border-color); /* Double-line border */ + align-items: center; /* Vertically align content */ + } -.sheet-mcfma { - grid-area: mcfma; + +.customskills { + grid-area: customskills; } -.sheet-mcfmd { - grid-area: mcfmd; + +.knightskills { + grid-area: knightskills; } -.sheet-steperattributes { - grid-area: steperattributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "steperheading steperheading steperheading " "steper3 finalstealth button1" "steper4 finalperception button2"; + +.barbarianskills { + grid-area: barbarianskills; } -label.sheet-steperheading { - grid-area: steperheading; + +.assassinskills { + grid-area: assassinskills; } -.sheet-steper1 { - grid-area: steper1; + +.hunterskills { + grid-area: hunterskills; } -.sheet-steper2 { - grid-area: steper2; + +.warlockskills { + grid-area: warlockskills; } -.sheet-steper3 { - grid-area: steper3; - text-align: center; + +.sorcererskills { + grid-area: sorcererskills; } -.sheet-steper4 { - grid-area: steper4; - text-align: center; + +.mysticskills { + grid-area: mysticskills; } -.sheet-stealth { - grid-area: stealth; + +.elementalistskills { + grid-area: elementalistskills; } -.sheet-finalperception { - grid-area: finalperception; + +.knaveskills { + grid-area: knaveskills; } -.sheet-finalstealth { - grid-area: finalstealth; + +.priestskills { + grid-area: priestskills; } -.sheet-percep { - grid-area: percep; + +.demonologistskills { + grid-area: demonologistskills; } -.sheet-hpattributes { - grid-area: hpattributes; - border-style: double; - border-width: 6px; + +.shock_attack { + grid-area: shock_attack; } -.sheet-afattributes { - grid-area: afattributes; - grid-template-columns: 25% 50% 25%; - grid-template-rows: auto; + +/* Show the specific section based on the value of the tabstoggle input */ +.tabstoggle[value="character"] ~ div.character, +.tabstoggle[value="inventory"] ~ div.inventory, +.tabstoggle[value="basescores"] ~ div.basescores, +.tabstoggle[value="magic"] ~ div.magic, +.tabstoggle[value="skills"] ~ div.skills, +.tabstoggle[value="languages"] ~ div.languages, +.tabstoggle[value="biographical"] ~ div.biographical, +.tabstoggle[value="documentation"] ~ div.documentation { display: grid; - border-style: double; - border-width: 6px; - grid-template-areas: "afheader afheader afheader" "aftype aftypeinput aftypeinput" "imgshieldcol afname afinput" "imgshieldcol shieldbox shieldbox" "shieldhidden shieldhidden shieldhidden"; } -.sheet-afheader { - grid-area: afheader; -} -.sheet-aftype{ - grid-area: aftype; -} -.sheet-aftypeinput{ - grid-area: aftypeinput; -} -.sheet-imgshieldcol{ - grid-area: imgshieldcol; -} -.sheet-afname{ - grid-area: afname; -} -.sheet-afinput{ - grid-area: afinput; -} -.sheet-shieldbox{ - grid-area: shieldbox; -} -/*hide shield values if the shield is not equipped*/ -.sheet-shieldhidden{ - display: none; - grid-area: shieldhidden; - grid-template-areas: "shielddie shieldsuccess shieldbutton"; -} -.sheet-shielddie{ - grid-area: shielddie; -} -.sheet-shieldsuccess { - grid-area: shieldsuccess; -} -.sheet-shieldbutton { - grid-area: shieldbutton; + +/* Display grid layout for specific profession abilities based on toggle value */ +input.profession-toggle[value="Knight"] ~ div.knightmelee, +input.profession-toggle[value="Barbarian"] ~ div.barbarianmelee, +input.profession-toggle[value="Assassin"] ~ div.assassinmelee, +input.profession-toggle[value="Hunter"] ~ div.huntermelee, +input.profession-toggle[value="Knave"] ~ div.knavemelee, +input.profession-toggle[value="Priest"] ~ div.priestmelee, +input.profession-toggle[value="Sorcerer"] ~ div.nomelee, +input.profession-toggle[value="Mystic"] ~ div.mysticmelee, +input.profession-toggle[value="Elementalist"] ~ div.elementalistmelee, +input.profession-toggle[value="Demonologist"] ~ div.demonologistmelee, +input.profession-toggle[value="Warlock"] ~ div.warlockmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.knightmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.barbarianmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.assassinmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.huntermelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.warlockmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.knavemelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.mysticmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.priestmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.demonologistmelee, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.elementalistmelee { + display: grid; /* Displays the element as a grid layout */ } -input.sheet-shield-toggle[value="1"] ~ div.sheet-shieldhidden { + +/* Show relevant sections for predefined professions */ +input.profession-toggle[value="Knight"] ~ div.martialhidden, +input.profession-toggle[value="Knight"] ~ div.nomagic, +input.profession-toggle[value="Barbarian"] ~ div.martialhidden, +input.profession-toggle[value="Barbarian"] ~ div.nomagic, +input.profession-toggle[value="Hunter"] ~ div.martialhidden, +input.profession-toggle[value="Hunter"] ~ div.nomagic, +input.profession-toggle[value="Assassin"] ~ div.nonmartialhidden, +input.profession-toggle[value="Assassin"] ~ div.nomagic, +input.profession-toggle[value="Knave"] ~ div.nonmartialhidden, +input.profession-toggle[value="Knave"] ~ div.nomagic, +input.profession-toggle[value="Priest"] ~ div.nonmartialhidden, +input.profession-toggle[value="Priest"] ~ div.nomagic, +input.profession-toggle[value="Sorcerer"] ~ div.mpattributeshidden, +input.profession-toggle[value="Sorcerer"] ~ div.nonmartialhidden, +input.profession-toggle[value="Mystic"] ~ div.mpattributeshidden, +input.profession-toggle[value="Mystic"] ~ div.nonmartialhidden, +input.profession-toggle[value="Elementalist"] ~ div.mpattributeshidden, +input.profession-toggle[value="Elementalist"] ~ div.nonmartialhidden, +input.profession-toggle[value="Warlock"] ~ div.mpattributeshidden, +input.profession-toggle[value="Warlock"] ~ div.nonmartialhidden, +input.profession-toggle[value="Demonologist"] ~ div.mpattributeshidden, +input.profession-toggle[value="Demonologist"] ~ div.nonmartialhidden, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.mpattributeshidden, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.martialhidden, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.nonmartialhidden { display: grid; } -/*define which magic point elements should be shown, based on profession*/ -.sheet-mpattributes { - grid-area: mpattributes; - border-style: double; - border-width: 6px; -} -.sheet-mp { + +input.combat_guards_able[value="disabled"] ~ div.martialhidden, +input.combat_guards_able[value="disabled"] ~ div.nonmartialhidden { display: none; } -input.sheet-profession-toggle[value="Knight"] ~ div.sheet-martialhidden, -input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-martialhidden, -input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-nonmartialhidden, -input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-martialhidden, -input.sheet-profession-toggle[value="Knave"] ~ div.sheet-nonmartialhidden, -input.sheet-profession-toggle[value="Priest"] ~ div.sheet-nonmartialhidden, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-mpattributeshidden, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-mpattributeshidden, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-mpattributeshidden, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-mpattributeshidden, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-mpattributeshidden { + +/* Toggle visibility of magical attributes based on profession */ +input.profession-toggle[value="Sorcerer"] ~ div.castermp, +input.profession-toggle[value="Mystic"] ~ div.castermp, +input.profession-toggle[value="Elementalist"] ~ div.castermp, +input.profession-toggle[value="Demonologist"] ~ div.castermp, +input.profession-toggle[value="Warlock"] ~ div.warlockmp, +input.profession-toggle[value="Elementalist"] ~ div.standardmp, +input.profession-toggle[value="Elementalist"] ~ div.elementalistmp, +input.profession-toggle[value="Sorcerer"] ~ div.standardmp, +input.profession-toggle[value="Mystic"] ~ div.mysticmp, +input.profession-toggle[value="Warlock"] ~ div.standardmp, +input.profession-toggle[value="Demonologist"] ~ div.standardmp, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.castermp, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.warlockmp, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.elementalistmp, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.standardmp, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.mysticmp { display: grid; } -.sheet-nonmartialhidden { - grid-template-areas: "guardheader2 guardheader2" "guardselect2 guardselect2" "malabel2 mabox2" "mdlabel2 mdbox2" "ralabel2 rabox2" "rdlabel2 rdbox2" "dodgelabel2 dodgebox2" "guardother2 guardother2"; -} -.sheet-guardheader2 { - grid-area: guardheader2; -} -.sheet-guardselect2 { - grid-area: guardselect2; -} -.sheet-malabel2 { - grid-area: malabel2; - justify-content: space-around; -} -.sheet-mabox2 { - grid-area: mabox2; - justify-content: space-around; -} -.sheet-mdlabel2 { - grid-area: mdlabel2; - justify-content: space-around; -} -.sheet-mdbox2 { - grid-area: mdbox2; - justify-content: space-around; -} -.sheet-ralabel2 { - grid-area: ralabel2; - justify-content: space-around; -} -.sheet-rabox2 { - grid-area: rabox2; - justify-content: space-around; -} -.sheet-rdlabel2 { - grid-area: rdlabel2; - justify-content: space-around; -} -.sheet-rdbox2 { - grid-area: rdbox2; - justify-content: space-around; -} -.sheet-dodgelabel2 { - grid-area: dodgelabel2; - justify-content: space-around; -} -.sheet-dodgebox2 { - grid-area: dodgebox2; - justify-content: space-around; -} -.sheet-guardother2 { - grid-area: guardother2; -} -.sheet-martialhidden { - grid-template-areas: "guardheader1 guardheader1" "guardselect1 guardselect1" "guardcounteredcol guardcounteredcol" "malabel1 mabox1" "mdlabel1 mdbox1" "ralabel1 rabox1" "rdlabel1 rdbox1" "dodgelabel1 dodgebox1" "guardother1 guardother1"; -} -.sheet-guardheader1 { - grid-area: guardheader1; -} -.sheet-guardcounteredcol { - grid-area: guardcounteredcol; -} -.sheet-guardselect1 { - grid-area: guardselect1; -} -.sheet-malabel1 { - grid-area: malabel1; - justify-content: space-around; -} -.sheet-mabox1 { - grid-area: mabox1; - justify-content: space-around; -} -.sheet-mdlabel1 { - grid-area: mdlabel1; - justify-content: space-around; -} -.sheet-mdbox1 { - grid-area: mdbox1; - justify-content: space-around; -} -.sheet-ralabel1 { - grid-area: ralabel1; - justify-content: space-around; -} -.sheet-rabox1 { - grid-area: rabox1; - justify-content: space-around; -} -.sheet-rdlabel1 { - grid-area: rdlabel1; - justify-content: space-around; -} -.sheet-rdbox1 { - grid-area: rdbox1; - justify-content: space-around; -} -.sheet-dodgelabel1 { - grid-area: dodgelabel1; - justify-content: space-around; -} -.sheet-dodgebox1 { - grid-area: dodgebox1; - justify-content: space-around; -} -.sheet-guardother1 { - grid-area: guardother1; -} -.sheet-castermp { - justify-content: space-between; - grid-template-areas: "dma1 dmabutton1" "ima1 imabutton1" "ser1 serbutton1"; -} -.sheet-warlockmp { - justify-content: space-between; - grid-template-areas: "dma2 dmabutton2" "ima2 imabutton2" "ser2 serbutton2"; -} -.sheet-dma1 { - justify-content: space-between; - grid-area: dma1; -} -.sheet-ima1 { - justify-content: space-between; - grid-area: ima1; -} -.sheet-ser1 { - justify-content: space-between; - grid-area: ser1; -} -button.sheet-dmabutton1 { - justify-content: space-around; - grid-area: dmabutton1; -} -button.sheet-imabutton1 { - justify-content: space-around; - grid-area: imabutton1; -} -button.sheet-serbutton1 { - grid-area: serbutton1; - justify-content: space-around; -} -.sheet-dma2 { - justify-content: space-between; - grid-area: dma2; -} -.sheet-ima2 { - justify-content: space-between; - grid-area: ima2; -} -.sheet-ser2 { - justify-content: space-between; - grid-area: ser2; -} -button.sheet-dmabutton2 { - justify-content: space-around; - grid-area: dmabutton2; -} -button.sheet-imabutton2 { - justify-content: space-around; - grid-area: imabutton2; -} -button.sheet-serbutton2 { - grid-area: serbutton2; - justify-content: space-around; -} -.sheet-finmagatk { - grid-area: finmagatk; - justify-content: space-between; -} -.sheet-finmagdef { - grid-area: finmagdef; - justify-content: space-between; -} -.sheet-finmagatkbox { - grid-area: finmagatkbox; - justify-content: space-between; -} -.sheet-finmagdefbox { - grid-area: finmagdefbox; - justify-content: space-between; -} -.sheet-mysticmp { - grid-template-areas: "psyfatlabel1 psyfatlabel1 psyfatlabel1" "psyfatbox1 psyfatbox1 psyfatbutton1" "esplabel1 espbox1 espbutton1" "premonitionlabel1 premonitionbox1 premonitionbutton1"; -} -.sheet-psyfatlabel1 { - grid-area: psyfatlabel1; - justify-content: space-around; -} -.sheet-psyfatbox1 { - grid-area: psyfatbox1; - justify-content: space-around; -} -.sheet-psyfatbutton1 { - grid-area: psyfatbutton1; - justify-content: space-around; -} -.sheet-esplabel1 { - grid-area: esplabel1; - justify-content: space-around; -} -.sheet-espbox1 { - grid-area: espbox1; - justify-content: space-around; -} -.sheet-espbutton1 { - grid-area: espbutton1; - justify-content: space-around; -} -.sheet-premonitionlabel1 { - grid-area: premonitionlabel1; - justify-content: space-around; -} -.sheet-premonitionbox1 { - grid-area: premonitionbox1; - justify-content: space-around; -} -.sheet-premonitionbutton1 { - grid-area: premonitionbutton1; - justify-content: space-around; -} -.sheet-frontmp { - display: none; -} -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-castermp, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-castermp, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-castermp, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-castermp, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-warlockmp, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-standardmp, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-elementalistmp, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-standardmp, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-mysticmp, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-standardmp, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-standardmp { + +input.profession-toggle[value="Knight"] ~ div.notacaster, +input.profession-toggle[value="Barbarian"] ~ div.notacaster, +input.profession-toggle[value="Assassin"] ~ div.notacaster, +input.profession-toggle[value="Hunter"] ~ div.notacaster, +input.profession-toggle[value="Knave"] ~ div.notacaster, +input.profession-toggle[value="Priest"] ~ div.notacaster, +input.profession-toggle[value="Sorcerer"] ~ div.castermana, +input.profession-toggle[value="Mystic"] ~ div.castermana, +input.profession-toggle[value="Elementalist"] ~ div.castermana, +input.profession-toggle[value="Demonologist"] ~ div.castermana, +input.profession-toggle[value="Warlock"] ~ div.warlockmana, +input.profession-toggle[value="Sorcerer"] ~ div.standardmana, +input.profession-toggle[value="Mystic"] ~ div.mysticmana, +input.profession-toggle[value="Elementalist"] ~ div.elementalistattributes, +input.profession-toggle[value="Elementalist"] ~ div.standardmana, +input.profession-toggle[value="Elementalist"] ~ div.elementalistmana, +input.profession-toggle[value="Warlock"] ~ div.standardmana, +input.profession-toggle[value="Demonologist"] ~ div.standardmana, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.castermana, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.warlockmana, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.elementalistattributes, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.standardmana, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.elementalistmana, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.mysticmana { display: grid; } -.sheet-paths { - grid-area: paths; - border-style: double; - border-width: 6px; -} -.sheet-professionskills { - grid-area: professionskills; - border-style: double; - border-width: 6px; -} -.sheet-secondaryskillssec { - grid-area: secondaryskills; - border-style: double; - border-width: 6px; -} -/*define equiment tab children*/ -.sheet-possessions { - grid-area: possessions; - border-style: double; - border-width: 6px; -} -.sheet-money { - grid-area: money; - border-style: double; - border-width: 6px; -} -.sheet-armour { - grid-area: armour; + +/* Toggle visibility of caster list based on profession */ +input.profession-toggle[value="Knight"] ~ div.noncaster, +input.profession-toggle[value="Barbarian"] ~ div.noncaster, +input.profession-toggle[value="Assassin"] ~ div.noncaster, +input.profession-toggle[value="Knave"] ~ div.noncaster, +input.profession-toggle[value="Hunter"] ~ div.noncaster, +input.profession-toggle[value="Priest"] ~ div.noncaster, +input.profession-toggle[value="Sorcerer"] ~ div.sorcerer_spell_list, +input.profession-toggle[value="Mystic"] ~ div.mystic_spell_list, +input.profession-toggle[value="Warlock"] ~ div.warlock_spell_list, +input.profession-toggle[value="Elementalist"] ~ div.elementalist_spell_list, +input.element-toggle1[value="Air"] ~ div.air_spell_list, +input.element-toggle1[value="Earth"] ~ div.earth_spell_list, +input.element-toggle1[value="Water"] ~ div.water_spell_list, +input.element-toggle1[value="Fire"] ~ div.fire_spell_list, +input.element-toggle1[value="Darkness"] ~ div.darkness_spell_list, +input.element-toggle1[value="Darkness"] ~ div.spell_darkness, +input.element-toggle2[value="Air"] ~ div.air_spell_list, +input.element-toggle2[value="Earth"] ~ div.earth_spell_list, +input.element-toggle2[value="Water"] ~ div.water_spell_list, +input.element-toggle2[value="Fire"] ~ div.fire_spell_list, +input.element-toggle2[value="Darkness"] ~ div.darkness_spell_list, +input.element-toggle3[value="Air"] ~ div.air_spell_list, +input.element-toggle3[value="Earth"] ~ div.earth_spell_list, +input.element-toggle3[value="Water"] ~ div.water_spell_list, +input.element-toggle3[value="Fire"] ~ div.fire_spell_list, +input.element-toggle3[value="Darkness"] ~ div.darkness_spell_list, +input.profession-toggle[value="Elementalist"] ~ div.spelllist, +input.profession-toggle[value="Warlock"] ~ div.spelllist, +input.profession-toggle[value="Demonologist"] ~ div.spelllist, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.spelllist { display: grid; - border-style: double; - border-width: 6px; - justify-content: space-around; - grid-template-areas: " aflabel1 aflabel1" "armourtypelabel1 armourtypebox1" "armourfactorlabel1 armourfactorbox1" "armourmagiclabel1 armourmagicbox1" "colstatlabel9 colstatmodbox9" "nonprofarmourheader1 nonprofarmourheader1" "nonprofarmourpenaltylabel1 nonprofarmourpenaltybox1" "nonprofarmourpenaltylabel2 nonprofarmourpenaltybox2" " nonprofarmourpenaltylabel3 nonprofarmourpenaltybox3" "shieldcol1 shieldcol1"; } -.sheet-aflabel1 { - grid-area: aflabel1; + +/* Display grid layout for specific profession skills based on toggle value */ +input.profession-toggle[value="Knight"] ~ div.knightskills, +input.profession-toggle[value="Barbarian"] ~ div.barbarianskills, +input.profession-toggle[value="Assassin"] ~ div.assassinskills, +input.profession-toggle[value="Hunter"] ~ div.hunterskills, +input.profession-toggle[value="Warlock"] ~ div.warlockskills, +input.profession-toggle[value="Sorcerer"] ~ div.sorcererskills, +input.profession-toggle[value="Mystic"] ~ div.mysticskills, +input.profession-toggle[value="Elementalist"] ~ div.elementalistskills, +input.profession-toggle[value="Knave"] ~ div.knaveskills, +input.profession-toggle[value="Priest"] ~ div.priestskills, +input.profession-toggle[value="Demonologist"] ~ div.demonologistskills, +input.profession-toggle[value="Knight"] ~ div.customskills, +input.profession-toggle[value="Barbarian"] ~ div.customskills, +input.profession-toggle[value="Assassin"] ~ div.customskills, +input.profession-toggle[value="Hunter"] ~ div.customskills, +input.profession-toggle[value="Warlock"] ~ div.customskills, +input.profession-toggle[value="Sorcerer"] ~ div.customskills, +input.profession-toggle[value="Mystic"] ~ div.customskills, +input.profession-toggle[value="Elementalist"] ~ div.customskills, +input.profession-toggle[value="Knave"] ~ div.customskills, +input.profession-toggle[value="Priest"] ~ div.customskills, +input.profession-toggle[value="Demonologist"] ~ div.customskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ divs, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.barbarianskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.assassinskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.hunterskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.warlockskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.sorcererskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.mysticskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.elementalistskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.knaveskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.priestskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.demonologistskills, +input.profession-toggle:not([value="Knight"]):not([value="Barbarian"]):not([value="Warlock"]):not([value="Assassin"]):not([value="Knave"]):not([value="Hunter"]):not([value="Priest"]):not([value="Mystic"]):not([value="Elementalist"]):not([value="Demonologist"]):not([value="Sorcerer"]):not([value=""]) ~ div.customskills { + display: grid; /* Displays the element as a grid layout */ } -.sheet-armourtypelabel1 { - grid-area: armourtypelabel1; + +.charsheet input.rollhp-toggle:checked ~ div.rollbasehpbuttoncontainer, +.charsheet input.rollstats-toggle:checked ~ div.rollbasestatsbuttoncontainer { + display: block; } -.sheet-armourtypebox1 { - grid-area: armourtypebox1; + +.charsheet input.weaponskill1:checked ~ div.weaponskillrow1, +.charsheet input.weaponskill2:checked ~ div.weaponskillrow2, +.charsheet input.weaponskill3:checked ~ div.weaponskillrow3, +.charsheet input.shield-toggle:checked ~ div.shieldhidden { + display: block; } -.sheet-armourfactorlabel1 { - grid-area: armourfactorlabel1; + +.charsheet input.track:not([value="0"]) ~ div.track, +.charsheet input.disarm_technique:not([value="0"]) ~ div.disarm_technique, +.charsheet input.main_gauche:not([value="0"]) ~ div.main_gauche, +.charsheet input.intimidating:not([value="0"]) ~ div.intimidating, +.charsheet input.shock_attack:not([value="0"]) ~ div.shock_attack, +.charsheet input.memorize:not([value="0"]) ~ div.memorize, +.charsheet input.pilfer:not([value="0"]) ~ div.pilfer, +.charsheet input.disguise:not([value="0"]) ~ div.disguise, +.charsheet input.inner_sense:not([value="0"]) ~ div.inner_sense, +.charsheet input.pick_lock:not([value="0"]) ~ div.pick_lock, +.charsheet input.esp:not([value="0"]) ~ div.esp, +.charsheet input.premonition:not([value="0"]) ~ div.premonition, +.charsheet input.raw_power:not([value="0"]) ~ div.raw_power, +.charsheet input.raw_poweralternate:not([value="0"]) ~ div.raw_poweralternate, +.charsheet input.appraiseenemy:not([value="0"]) ~ div.appraiseenemy, +.charsheet input.distract:not([value="0"]) ~ div.distract, +.charsheet input.bodyguard:not([value="0"]) ~ div.bodyguard, +.charsheet input.presence:not([value="0"]) ~ div.presence, +.charsheet input.sense_falsehood:not([value="0"]) ~ div.sense_falsehood, +.charsheet input.hypnotic_suggestion:not([value="0"]) ~ div.hypnotic_suggestion, +.charsheet input.network:not([value="0"]) ~ div.network, +.charsheet input.gossip:not([value="0"]) ~ div.gossip, +.charsheet input.forage:not([value="0"]) ~ div.forage, +.charsheet input.favoured_terrain:not([value="0"]) ~ div.favoured_terrain, +.charsheet input.favoured_weapon:not([value="0"]) ~ div.favoured_weapon, +.charsheet input.linguist:not([value="0"]) ~ div.linguist, +.charsheet input.exorcism:not([value="0"]) ~ div.exorcism, +.charsheet input.sermon:not([value="0"]) ~ div.sermon, +.charsheet input.remove_curse:not([value="0"]) ~ div.remove_curse, +.charsheet input.remove_madness:not([value="0"]) ~ div.remove_madness, +.charsheet input.demonology:not([value="0"]) ~ div.demonology, +.charsheet input.ritual:not([value="0"]) ~ div.ritual, +.charsheet input.banish:not([value="0"]) ~ div.banish, +.charsheet input.words_are_power:not([value="0"]) ~ div.words_are_power, +.charsheet input.pact:not([value="0"]) ~ div.pact { + display: block; } -.sheet-armourfactorbox1 { - grid-area: armourfactorbox1; + +.charsheet input.track_front:not([value="0"]) ~ div.track_button_front, +.charsheet input.disarm_front:not([value="0"]) ~ div.disarm_button_front, +.charsheet input.intimidating_front:not([value="0"]) ~ div.intimidating_button_front, +.charsheet input.shock_attack_front:not([value="0"]) ~ div.shock_attack_button_front, +.charsheet input.memorize_front:not([value="0"]) ~ div.memorize_button_front, +.charsheet input.pilfer_front:not([value="0"]) ~ div.pilfer_button_front, +.charsheet input.disguise_front:not([value="0"]) ~ div.disguise_button_front, +.charsheet input.inner_sense_front:not([value="0"]) ~ div.inner_sense_button_front, +.charsheet input.pick_lock_front:not([value="0"]) ~ div.pick_lock_button_front, +.charsheet input.esp_front:not([value="0"]) ~ div.esp_button_front, +.charsheet input.premonition_front:not([value="0"]) ~ div.premonition_button_front, +.charsheet input.raw_power_front:not([value="0"]) ~ div.raw_power_button_front, +.charsheet input.raw_poweralternate_front:not([value="0"]) ~ div.raw_power_button_front, +.charsheet input.appraiseenemy_front:not([value="0"]) ~ div.appraiseenemy_button_front, +.charsheet input.distract_front:not([value="0"]) ~ div.distract_button_front, +.charsheet input.bodyguard_front:not([value="0"]) ~ div.bodyguard_button_front, +.charsheet input.presence_front:not([value="0"]) ~ div.presence_button_front, +.charsheet input.sense_falsehood_front:not([value="0"]) ~ div.sense_falsehood_button_front, +.charsheet input.hypnotic_suggestion_front:not([value="0"]) ~ div.hypnotic_suggestion_button_front, +.charsheet input.network_front:not([value="0"]) ~ div.network_button_front, +.charsheet input.gossip_front:not([value="0"]) ~ div.gossip_button_front, +.charsheet input.forage_front:not([value="0"]) ~ div.forage_button_front, +.charsheet input.favoured_terrain_front:not([value="0"]) ~ div.favoured_terrain_button_front, +.charsheet input.favoured_weapon_front:not([value="0"]) ~ div.favoured_weapon_button_front, +.charsheet input.linguist_front:not([value="0"]) ~ div.linguist_button_front, +.charsheet input.exorcism_front:not([value="0"]) ~ div.exorcism_button_front, +.charsheet input.sermon_front:not([value="0"]) ~ div.sermon_button_front, +.charsheet input.remove_curse_front:not([value="0"]) ~ div.remove_curse_button_front, +.charsheet input.remove_madness_front:not([value="0"]) ~ div.remove_madness_button_front, +.charsheet input.demonology_front:not([value="0"]) ~ div.demonology_button_front, +.charsheet input.ritual_front:not([value="0"]) ~ div.ritual_button_front, +.charsheet input.banish_front:not([value="0"]) ~ div.banish_button_front, +.charsheet input.words_are_power_front:not([value="0"]) ~ div.words_are_power_button_front, +.charsheet input.pact_front:not([value="0"]) ~ div.pact_button_front, +.charsheet input.deathvow_front:not([value="0"]) ~ div.deathvow_button_front, +.charsheet input.iron_will_front:not([value="0"]) ~ div.iron_will_button_front, +.charsheet input.precise_shot_front:not([value="0"]) ~ div.precise_shot_button_front, +.charsheet input.stillness_front:not([value="0"]) ~ div.stillness_button_front, +.charsheet input.penetrating_shot_front:not([value="0"]) ~ div.penetrating_shot_button_front, +.charsheet input.hunters_mind_front:not([value="0"]) ~ div.hunters_mind_button_front, +.charsheet input.human_intuition_front:not([value="0"]) ~ div.human_intuition_button_front, +.charsheet input.elemental_resistance_front:not([value="0"]) ~ div.elemental_resistance_button_front, +.charsheet input.berserk_front:not([value="0"]) ~ div.berserk_button_front, +.charsheet input.bloodrage_front:not([value="0"]) ~ div.bloodrage_button_front, +.charsheet input.main_gauche_front:not([value="0"]) ~ div.main_gauche_button_front { + display: block; } -.sheet-armourmagiclabel1 { - grid-area: armourmagiclabel1; + +/* When "Core" is selected, show ONLY the core powers div within the elementalistskills div */ +.charsheet input.elementalist_raw_power_type[value="Core"] ~ .elementalist_core_powers { + display: block; } -.sheet-armourmagicbox1 { - grid-area: armourmagicbox1; + +/* When "PG" is selected, show ONLY the alternate powers div within the elementalistskills div */ +.charsheet input.elementalist_raw_power_type[value="PG"] ~ .elementalist_alternate_powers { + display: block; } -.sheet-nonprofarmourheader1 { - grid-area: nonprofarmourheader1; + +/* When "Both" is selected, show BOTH divs within the elementalistskills div */ +.charsheet input.elementalist_raw_power_type[value="Both"] ~ .elementalist_alternate_powers, +.charsheet input.elementalist_raw_power_type[value="Both"] ~ .elementalist_core_powers { + display: block; } -.sheet-nonprofarmourpenaltylabel1 { - grid-area: nonprofarmourpenaltylabel1; - text-align: center; + +/* Hide both divs by default */ +.charsheet div.elementalist_alternate_powers, +.charsheet div.attr_elementalist_core_powers { /* Use .attr_elementalist_core_powers here as well */ + display: none; } -.sheet-nonprofarmourpenaltylabel2 { - grid-area: nonprofarmourpenaltylabel2; - text-align: center; + +.charsheet input.supremacy_able[value="disabled"] ~ div.supremacy, +.charsheet input.paths_toggle[value="disabled"] ~ div.pathscontainer, +.charsheet input.secondaryskills_toggle[value="disabled"] ~ div.secondaryskillscontainer, +.charsheet input.playerspells_toggle[value="disabled"] ~ div.playerspell { + display: none; } -.sheet-nonprofarmourpenaltylabel3 { - grid-area: nonprofarmourpenaltylabel3; + +/* Hide all sections by default */ +.charsheet div.knightskills, +.charsheet div.barbarianskills, +.charsheet div.assassinskills, +.charsheet div.hunterskills, +.charsheet div.warlockskills, +.charsheet div.sorcererskills, +.charsheet div.mysticskills, +.charsheet div.elementalistskills, +.charsheet div.knaveskills, +.charsheet div.priestskills, +.charsheet div.demonologistskills, +.charsheet div.customskills, +.charsheet div.character, +.charsheet div.skills, +.charsheet div.inventory, +.charsheet div.basescores, +.charsheet div.magic, +.charsheet div.languages, +.charsheet div.biographical, +.charsheet div.documentation, +.charsheet div.barbarianmelee, +.charsheet div.knightmelee, +.charsheet div.warlockmelee, +.charsheet div.assassinmelee, +.charsheet div.huntermelee, +.charsheet div.knavemelee, +.charsheet div.elementalistmelee, +.charsheet div.mysticmelee, +.charsheet div.priestmelee, +.charsheet div.demonologistmelee, +.charsheet div.nomelee, +.charsheet div.castermana, +.charsheet div.warlockmana, +.charsheet div.elementalistattributes, +.charsheet div.standardmana, +.charsheet div.elementalistmana, +.charsheet div.notacaster, +.charsheet div.mysticmana, +.charsheet div.noncaster, +.charsheet div.spelllist, +.charsheet div.sorcerer_spell_list, +.charsheet div.mystic_spell_list, +.charsheet div.warlock_spell_list, +.charsheet div.elementalist_spell_list, +.charsheet div.air_spell_list, +.charsheet div.earth_spell_list, +.charsheet div.water_spell_list, +.charsheet div.fire_spell_list, +.charsheet div.darkness_spell_list, +.charsheet div.spell_darkness, +.charsheet div.weaponskillrow1, +.charsheet div.weaponskillrow2, +.charsheet div.weaponskillrow3, +.charsheet div.rollbasestatsbuttoncontainer, +.charsheet div.rollbasehpbuttoncontainer, +.charsheet div.castermp, +.charsheet div.warlockmp, +.charsheet div.standardmp, +.charsheet div.elementalistmp, +.charsheet div.mysticmp, +.charsheet div.nomagic, +.charsheet div.nonmartialhidden, +.charsheet div.martialhidden, +.charsheet div.shieldhidden, +.charsheet div.disarm_technique, +.charsheet div.intimidating, +.charsheet div.main_gauche, +.charsheet div.track, +.charsheet div.shock_attack, +.charsheet div.memorize, +.charsheet div.disguise, +.charsheet div.pilfer, +.charsheet div.inner_sense, +.charsheet div.pick_lock, +.charsheet div.esp, +.charsheet div.premonition, +.charsheet div.raw_power, +.charsheet div.raw_poweralternate, +.charsheet div.appraiseenemy, +.charsheet div.distract, +.charsheet div.bodyguard, +.charsheet div.presence, +.charsheet div.sense_falsehood, +.charsheet div.hypnotic_suggestion, +.charsheet div.network, +.charsheet div.gossip, +.charsheet div.forage, +.charsheet div.favoured_terrain, +.charsheet div.favoured_weapon, +.charsheet div.linguist, +.charsheet div.exorcism, +.charsheet div.sermon, +.charsheet div.remove_curse, +.charsheet div.remove_madness, +.charsheet div.demonology, +.charsheet div.ritual, +.charsheet div.banish, +.charsheet div.pact, +.charsheet div.track_button_front, +.charsheet div.disarm_button_front, +.charsheet div.intimidating_button_front, +.charsheet div.shock_attack_button_front, +.charsheet div.memorize_button_front, +.charsheet div.pilfer_button_front, +.charsheet div.disguise_button_front, +.charsheet div.inner_sense_button_front, +.charsheet div.pick_lock_button_front, +.charsheet div.esp_button_front, +.charsheet div.premonition_button_front, +.charsheet div.raw_power_button_front, +.charsheet div.appraiseenemy_button_front, +.charsheet div.distract_button_front, +.charsheet div.bodyguard_button_front, +.charsheet div.presence_button_front, +.charsheet div.sense_falsehood_button_front, +.charsheet div.hypnotic_suggestion_button_front, +.charsheet div.network_button_front, +.charsheet div.gossip_button_front, +.charsheet div.forage_button_front, +.charsheet div.favoured_terrain_button_front, +.charsheet div.favoured_weapon_button_front, +.charsheet div.linguist_button_front, +.charsheet div.exorcism_button_front, +.charsheet div.sermon_button_front, +.charsheet div.remove_curse_button_front, +.charsheet div.remove_madness_button_front, +.charsheet div.demonology_button_front, +.charsheet div.ritual_button_front, +.charsheet div.banish_button_front, +.charsheet div.words_are_power_button_front, +.charsheet div.pact_button_front, +.charsheet div.iron_will_button_front, +.charsheet div.deathvow_button_front, +.charsheet div.precise_shot_button_front, +.charsheet div.stillness_button_front, +.charsheet div.penetrating_shot_button_front, +.charsheet div.hunters_mind_button_front, +.charsheet div.human_intuition_button_front, +.charsheet div.elemental_resistance_button_front, +.charsheet div.berserk_button_front, +.charsheet div.bloodrage_button_front, +.charsheet div.main_gauche_button_front, +.charsheet div.elementalist_alternate_powers, +.charsheet div.elementalist_core_powers { + display: none; + } + +/* Base styles for all custom templates */ +.sheet-rolltemplate-custom, +.sheet-rolltemplate-customd20, +.sheet-rolltemplate-custom2d10 { + margin-left: -30px; + margin-right: 20px; + background-color: var(--primary-bg-color); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + padding: 10px; + vertical-align: middle; text-align: center; } -.sheet-nonprofarmourpenaltybox1 { - grid-area: nonprofarmourpenaltybox1; -} -.sheet-nonprofarmourpenaltybox2 { - grid-area: nonprofarmourpenaltybox2; -} -.sheet-nonprofarmourpenaltybox3 { - grid-area: nonprofarmourpenaltybox3; -} -.sheet-shieldcol1 { - grid-area: shieldcol1; - display: grid; - grid-template-areas: "skullcol1 shieldbox1 shieldbox1" "skullcol1 magicshieldlabel1 magicshieldbox1" "shieldhidden1 shieldhidden1 shieldhidden1"; -} -.sheet-skullcol1 { - grid-area: skullcol1; -} -.sheet-shieldbox1 { - grid-area: shieldbox1; -} -.sheet-magicshieldlabel1 { - grid-area: magicshieldlabel1; -} -.sheet-magicshieldbox1 { - grid-area: magicshieldbox1; -} -.sheet-shieldhidden1{ - display: none; - grid-area: shieldhidden1; - grid-template-areas: "shielddie1 shieldsuccess1 shieldbutton1"; -} -.sheet-shielddie1{ - grid-area: shielddie1; + +.sheet-rolltemplate-custom .sheet-header, +.sheet-rolltemplate-customd20 .sheet-header, +.sheet-rolltemplate-custom2d10 .sheet-header { + background-color: rgba(112, 32, 130, 1); + text-align: left; + color: #FFF; + padding: 5px; } -.sheet-shieldsuccess1 { - grid-area: shieldsuccess1; + +.sheet-rolltemplate-custom .sheet-header .sheet-title, +.sheet-rolltemplate-customd20 .sheet-header .sheet-title, +.sheet-rolltemplate-custom2d10 .sheet-header .sheet-title { + font-family: 'Almendra SC', serif; + font-size: 22px; + line-height: 1.1; } -.sheet-shieldbutton1 { - grid-area: shieldbutton1; + +.sheet-rolltemplate-custom .sheet-header .sheet-subtitle, +.sheet-rolltemplate-customd20 .sheet-header .sheet-subtitle, +.sheet-rolltemplate-custom2d10 .sheet-header .sheet-subtitle { + font-family: 'Macondo', serif; + font-size: 16px; } -input.sheet-shield-toggle[value="1"] ~ div.sheet-shieldhidden1 { - display: grid; + +.sheet-rolltemplate-custom .sheet-content > div, +.sheet-rolltemplate-customd20 .sheet-content > div, +.sheet-rolltemplate-custom2d10 .sheet-content > div { + padding: 8px; } -.sheet-weapons { - grid-area: weapons; - border-style: double; - border-width: 6px; -} -.sheet-encumbrance { - grid-area: encumbrance; - border-style: double; - border-width: 6px; -} -/*define Biography tab children*/ -.sheet-basicbio { - grid-area: basicbio; - border-style: double; - border-width: 6px; -} -/*define Languages tab children*/ -.sheet-modlang { - grid-area: modlang; - border-style: double; - border-width: 6px; -} -.sheet-anclang { - grid-area: anclang; - border-style: double; - border-width: 6px; -} -/*define Magic tab children*/ -.sheet-allprofessionattribs { - grid-area: allprofessionattribs; - border-style: double; - border-width: 6px; - justify-content: space-between; + +.sheet-rolltemplate-custom .sheet-content, +.sheet-rolltemplate-customd20 .sheet-content, +.sheet-rolltemplate-custom2d10 .sheet-content { display: grid; - grid-template-areas: "mdheader mdheader" "mcf2 mcfmd" "magmod2 magbox2" "magfmod2 magfbox2"; -} -.sheet-mdheader { - grid-area: mdheader; + grid-template-columns: auto auto; + line-height: 1.6em; + vertical-align: middle; } -.sheet-manabox { - grid-area: manabox; - border-style: double; - border-width: 6px; -} -.sheet-spellbox { - grid-area: spellbox; - border-style: double; - border-width: 6px; -} -.sheet-allcastermana{ - border-style: double; - border-width: 6px; - justify-content: space-between; - display: grid; - grid-template-areas: "maheader maheader" "mcf1 mcfma" "magmod1 magbox1" "magfmod1 magfbox1"; -} -.sheet-maheader { - grid-area: maheader; -} -/*define which elements should be shown, based on profession*/ -.sheet-mana { - display: none; -} -.sheet-magmod1 { - grid-area: magmod1; -} -.sheet-magmod2 { - grid-area: magmod2; -} -.sheet-magbox1 { - grid-area: magbox1; - justify-content: space-between; + +.sheet-rolltemplate-custom .sheet-content .sheet-key, +.sheet-rolltemplate-customd20 .sheet-content .sheet-key, +.sheet-rolltemplate-custom2d10 .sheet-content .sheet-key { + font-family: 'Almendra SC', serif; + font-size: 20px; + font-weight: normal; + padding-right: 10px; + text-align: right; + vertical-align: middle; + background-color: #C0C0C0; + color: black; } -.sheet-magbox2 { - grid-area: magbox2; - justify-content: space-between; + +.sheet-rolltemplate-custom .sheet-content .sheet-value, +.sheet-rolltemplate-customd20 .sheet-content .sheet-value, +.sheet-rolltemplate-custom2d10 .sheet-content .sheet-value { + font-family: 'Almendra SC', serif; + font-size: 20px; + font-weight: normal; + padding-right: 10px; + text-align: right; + vertical-align: middle; + background-color: #767676; + color: white; } -.sheet-magfmod1 { - grid-area: magfmod1; + +.sheet-rolltemplate-custom .sheet-desc, +.sheet-rolltemplate-customd20 .sheet-desc, +.sheet-rolltemplate-custom2d10 .sheet-desc { + grid-column: span 2; + padding: 5px; + font-family: 'Macondo', serif; + font-size: 16px; + font-weight: normal; + padding-right: 10px; + vertical-align: middle; + background-color: #767676; + color: white; text-align: center; + vertical-align: middle; } -.sheet-magfmod2 { - grid-area: magfmod2; + +.sheet-rolltemplate-customd20 span.sheet-fumble, +.sheet-rolltemplate-custom2d10 span.sheet-fumble { + color: red; + vertical-align: middle; + padding: 5px; text-align: center; } -.sheet-magfbox1 { - grid-area: magfbox1; - justify-content: space-around; -} -.sheet-magfbox2 { - grid-area: magfbox2; - justify-content: space-around; -} -label.sheet-magattribheader { - grid-area: magattribheader; -} -.sheet-castermana { - grid-template-areas: "dma3 dmabutton3" "ima3 imabutton3" "ser3 serbutton3"; -} -.sheet-warlockmana { - grid-template-areas: "dma4 dmabutton4" "ima4 imabutton4" "ser4 serbutton4"; -} -.sheet-dma3 { - justify-content: space-between; - grid-area: dma3; -} -.sheet-ima3 { - justify-content: space-between; - grid-area: ima3; -} -.sheet-ser3 { - justify-content: space-between; - grid-area: ser3; -} -.sheet-dmabutton3 { - justify-content: space-around; - grid-area: dmabutton3; -} -.sheet-imabutton3 { - justify-content: space-around; - grid-area: imabutton3; -} -.sheet-serbutton3 { - grid-area: serbutton3; - justify-content: space-around; -} -.sheet-dma4 { - justify-content: space-between; - grid-area: dma4; -} -.sheet-ima4 { - justify-content: space-between; - grid-area: ima4; -} -.sheet-ser4 { - justify-content: space-between; - grid-area: ser4; -} -.sheet-dmabutton4 { - justify-content: space-around; - grid-area: dmabutton4; -} -.sheet-imabutton4 { - justify-content: space-around; - grid-area: imabutton4; -} -.sheet-serbutton4 { - grid-area: serbutton4; - justify-content: space-around; -} -input.sheet-profession-toggle[value="Knight"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Knave"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Priest"] ~ div.sheet-notacaster, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-castermana, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-castermana, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-castermana, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-castermana, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-warlockmana, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-standardmana, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-mysticmana, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-elementalistattributes, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-standardmana, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-elementalistmana, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-standardmana, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-standardmana { - display: grid; -} -.sheet-spells { - display: none; -} -input.sheet-profession-toggle[value="Knight"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Knave"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Priest"] ~ div.sheet-noncaster, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-list, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-list, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-list, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-list, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-list { - display: grid; -} -/* define combat tab children*/ -.sheet-basemeleeattributes { - grid-area: basemeleeattributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "miscmeleemodsheading miscmeleemodsheading" "colhead1 colhead2" "mmod1 mbox1" "mmod2 mbox2" "mmod3 mbox3" "mmod4 mbox4"; -} -.sheet-miscmeleemodsheading { - grid-area: miscmeleemodsheading; -} -.sheet-mmod1 { - grid-area: mmod1; -} -.sheet-mmod2 { - grid-area: mmod2; -} -.sheet-mmod3 { - grid-area: mmod3; -} -.sheet-mmod4 { - grid-area: mmod4; -} -.sheet-mbox1{ - grid-area: mbox1; -} -.sheet-mbox2{ - grid-area: mbox2; -} -.sheet-mbox3{ - grid-area: mbox3; -} -.sheet-mbox4{ - grid-area: mbox4; -} -.sheet-baserangedattributes { - grid-area: baserangedattributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "miscrangedmodsheading miscrangedmodsheading" "colhead1 colhead2" "rmod1 rbox1" "rmod2 rbox2" "rmod3 rbox3" "rmod4 rbox4"; -} -.sheet-miscrangedmodsheading { - grid-area: miscrangedmodsheading; -} -.sheet-rmod1 { - grid-area: rmod1; -} -.sheet-rmod2 { - grid-area: rmod2; -} -.sheet-rmod3 { - grid-area: rmod3; -} -.sheet-rmod4 { - grid-area: rmod4; -} -.sheet-rbox1{ - grid-area: rbox1; -} -.sheet-rbox2{ - grid-area: rbox2; -} -.sheet-rbox3{ - grid-area: rbox3; -} -.sheet-rbox4{ - grid-area: rbox4; -} -.sheet-basecharacteristics { - grid-area: basecharacteristics; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "misccharacteristicheading misccharacteristicheading misccharacteristicheading" "colhead1 colhead3 colhead2" "colstatlabel4 colstatfinal4 colstatmodbox4" "colstatlabel5 colstatfinal5 colstatmodbox5" "colstatlabel6 colstatfinal6 colstatmodbox6" "colstatlabel7 colstatfinal7 colstatmodbox7" "colstatlabel8 colstatfinal8 colstatmodbox8"; -} -.sheet-misccharacteristicheading { - grid-area: misccharacteristicheading; -} -.sheet-colstatlabel4 { - grid-area: colstatlabel4; -} -.sheet-colstatlabel5 { - grid-area: colstatlabel5; -} -.sheet-colstatlabel6 { - grid-area: colstatlabel6; -} -.sheet-colstatlabel7 { - grid-area: colstatlabel7; -} -.sheet-colstatlabel8 { - grid-area: colstatlabel8; -} -.sheet-colstatmodbox4 { - grid-area: colstatmodbox4; -} -.sheet-colstatmodbox5 { - grid-area: colstatmodbox5; -} -.sheet-colstatmodbox6 { - grid-area: colstatmodbox6; -} -.sheet-colstatmodbox7 { - grid-area: colstatmodbox7; -} -.sheet-colstatmodbox8 { - grid-area: colstatmodbox8; -} -.sheet-baseotherattributes { - grid-area: baseotherattributes; - border-style: double; - border-width: 6px; - justify-content: space-around; - display: grid; - grid-template-areas: "miscotherheading miscotherheading miscotherheading" "colhead1 colhead2 colhead3" "cf1 cfa colstatlabel10" "cf2 cfd colstatlabel20" "colstatlabel1 stealth colstatmodbox1" "colstatlabel2 percep colstatmodbox2" "colstatlabel3 evade colstatmodbox3"; -} -.sheet-miscotherheading { - grid-area: miscotherheading; -} -.sheet-colhead1 { - grid-area: colhead1; -} -.sheet-colhead2 { - grid-area: colhead2; -} -.sheet-colstatlabel1 { - grid-area: colstatlabel1; -} -.sheet-colstatlabel2 { - grid-area: colstatlabel2; -} -.sheet-colstatlabel10 { - grid-area: colstatlabel10; -} -.sheet-colstatlabel20 { - grid-area: colstatlabel20; -} -.sheet-colstatlabel3 { - grid-area: colstatlabel3; -} -.sheet-colstatlabel9 { - grid-area: colstatlabel9; -} -.sheet-colstatmodbox1 { - grid-area: colstatmodbox1; -} -.sheet-colstatmodbox2 { - grid-area: colstatmodbox2; -} -.sheet-colstatmodbox3 { - grid-area: colstatmodbox3; -} -.sheet-colstatmodbox9 { - grid-area: colstatmodbox9; -} -.sheet-classcombatabilities { - grid-area: classcombatabilities; - border-style: double; - border-width: 6px; -} -.sheet-finalcombatattributes2 { - grid-area: finalcombatattributes; - display: grid; - border-style: double; - border-width: 6px; - grid-template-areas: "finalsumheader finalsumheader finalsumheader finalsumheader" "finalsumcol1 finalsumboxes1 finalsumcol2 finalsumboxes2"; -} -.sheet-finalsumboxes1 { - grid-area: finalsumboxes1; -} -.sheet-finalsumboxes2 { - grid-area: finalsumboxes2; -} -.sheet-finalsumcol1 { - grid-area: finalsumcol1; -} -.sheet-finalsumcol2 { - grid-area: finalsumcol2; -} -.sheet-finalsumheader { - grid-area: finalsumheader; -} -.sheet-finalcombatattributes { - grid-area: finalcombatattributes; - display: grid; - border-style: double; - border-width: 6px; - grid-template-columns: 53% 47%; - grid-template-areas: "combatsumheader combatsumheader" "meleeattack1 meleeattack1" "equippedweaponlabel1 equippedweaponbox1" "abrlabel1 abrbox1" "mabrlabel1 mabrbox1" "damagelabel1 damagebox1" "mdamlabel1 mdambox1" "imgsworddiv imgsworddiv" "rangedattack1 rangedattack1" "equippedweaponlabel2 equippedweaponbox2" "equippedammolabel1 equippedammobox1" "abrlabel2 abrbox2" "rabrlabel1 rabrbox1" "damagelabel2 damagebox2" "rdamlabel1 rdambox1" "rangecols rangecols" "buttonfooter buttonfooter"; -} -.sheet-meleeattack1 { - grid-area: meleeattack1 ; -} -.sheet-equippedweaponlabel1 { - grid-area: equippedweaponlabel1; -} -.sheet-equippedweaponbox1 { - grid-area: equippedweaponbox1; -} -.sheet-abrlabel1 { - grid-area: abrlabel1; -} -.sheet-abrbox1 { - grid-area: abrbox1; -} -.sheet-damagelabel1 { - grid-area: damagelabel1 ; -} -.sheet-damagebox1 { - grid-area: damagebox1; -} -.sheet-rangedattack1 { - grid-area: rangedattack1; -} -.sheet-equippedweaponlabel2 { - grid-area: equippedweaponlabel2; -} -.sheet-equippedweaponbox2 { - grid-area: equippedweaponbox2; -} -.sheet-equippedammolabel1 { - grid-area: equippedammolabel1; -} -.sheet-equippedammobox1 { - grid-area: equippedammobox1; -} -.sheet-abrlabel2 { - grid-area: abrlabel2; -} -.sheet-abrbox2 { - grid-area: abrbox2; -} -.sheet-damagelabel2 { - grid-area: damagelabel2; -} -.sheet-damagebox2 { - grid-area: damagebox2; -} -.sheet-rangecols{ - grid-area: rangecols; - display: grid; - grid-template-columns: 40% 30% 30%; - grid-template-areas: "rangecol2 rangeheader rangeheader " "rangecol2 rangecol1 rangebox1 " "rangecol2 rangecol3 rangebox3 " "rangecol2 rangecol4 rangebox4 "; -} -.sheet-rangeheader { - grid-area: rangeheader; -} -.sheet-rangecol1 { - grid-area: rangecol1; -} -.sheet-rangecol2 { - grid-area: rangecol2; -} -.sheet-rangecol3 { - grid-area: rangecol3; -} -.sheet-rangecol4 { - grid-area: rangecol4; -} -.sheet-rangebox1 { - grid-area: rangebox1; -} -.sheet-rangebox3 { - grid-area: rangebox3; -} -.sheet-rangebox4 { - grid-area: rangebox4; -} -.sheet-combatsumheader { - grid-area: combatsumheader; -} -.sheet-imgsworddiv { - grid-area: imgsworddiv; -} -.sheet-barbarianmelee { - justify-content: space-around; - grid-template-areas: "barbarianheader1 barbarianheader1" "barbarianheader2 barbarianheader2" "barbarianlabel1 barbarianbox1" "barbarianlabel2 barbarianbox2" "barbarianlabel4 barbarianlabel4" "barbarianlabel3 barbarianlabel3" ; -} -.sheet-barbarianheader1 { - grid-area: barbarianheader1; -} -.sheet-barbarianheader2 { - grid-area: barbarianheader2; -} -.sheet-barbarianlabel1 { - grid-area: barbarianlabel1; -} -.sheet-barbarianlabel2 { - grid-area: barbarianlabel2; -} -.sheet-barbarianlabel3 { - grid-area: barbarianlabel3; -} -.sheet-barbarianlabel4 { - grid-area: barbarianlabel4; -} -.sheet-barbarianbox1 { - grid-area: barbarianbox1; -} -.sheet-barbarianbox2 { - grid-area: barbarianbox2; -} -.sheet-nonmartialhidden2 { - grid-template-areas: "guardheader3 guardheader3" "guardselect3 guardselect3" "malabel3 mabox3" "mdlabel3 mdbox3" "ralabel3 rabox3" "rdlabel3 rdbox3" "dodgelabel3 dodgebox3" "guardother3 guardother3"; -} -.sheet-guardheader3 { - grid-area: guardheader3; -} -.sheet-guardselect3 { - grid-area: guardselect3; -} -.sheet-malabel3 { - grid-area: malabel3; - justify-content: space-around; -} -.sheet-mabox3 { - grid-area: mabox3; - justify-content: space-around; -} -.sheet-mdlabel3 { - grid-area: mdlabel3; - justify-content: space-around; -} -.sheet-mdbox3 { - grid-area: mdbox3; - justify-content: space-around; -} -.sheet-ralabel3 { - grid-area: ralabel3; - justify-content: space-around; -} -.sheet-rabox3 { - grid-area: rabox3; - justify-content: space-around; -} -.sheet-rdlabel3 { - grid-area: rdlabel3; - justify-content: space-around; -} -.sheet-rdbox3 { - grid-area: rdbox3; - justify-content: space-around; + +.sheet-rolltemplate-customd20 div.sheet-fumble, +.sheet-rolltemplate-custom2d10 div.sheet-fumble { + grid-column: span 2; } -.sheet-dodgelabel3 { - grid-area: dodgelabel3; - justify-content: space-around; + +.sheet-rolltemplate-customd20 span.sheet-crit, +.sheet-rolltemplate-custom2d10 span.sheet-crit { + color: green; + vertical-align: middle; + padding: 5px; + text-align: center; } -.sheet-dodgebox3 { - grid-area: dodgebox3; - justify-content: space-around; + +.sheet-rolltemplate-customd20 div.sheet-crit, +.sheet-rolltemplate-custom2d10 div.sheet-crit { + grid-column: span 2; } -.sheet-guardother3 { - grid-area: guardother3; + +.sheet-rolltemplate-customd20 span.inlinerollresult, +.sheet-rolltemplate-customd20 span.inlinerollresult.fullfail, +.sheet-rolltemplate-customd20 span.inlinerollresult.fullcrit, +.sheet-rolltemplate-customd20 span.inlinerollresult.importantroll, +.sheet-rolltemplate-custom2d10 span.inlinerollresult, +.sheet-rolltemplate-custom2d10 span.inlinerollresult.fullfail, +.sheet-rolltemplate-custom2d10 span.inlinerollresult.fullcrit, +.sheet-rolltemplate-custom2d10 span.inlinerollresult.importantroll, +.sheet-rolltemplate-custom span.inlinerollresult, +.sheet-rolltemplate-custom span.inlinerollresult.fullfail, +.sheet-rolltemplate-custom span.inlinerollresult.fullcrit, +.sheet-rolltemplate-custom span.inlinerollresult.importantroll { + background-color: rgba(112, 32, 130, 1); + border: none; } -/*define which martial elements be show, based on Profession*/ -.sheet-melee { + +.maingauchesummary .repcontrol { display: none; } -input.sheet-profession-toggle[value="Knight"] ~ div.sheet-knightmelee, -input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-barbarianmelee, -input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-assassinmelee, -input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-huntermelee, -input.sheet-profession-toggle[value="Knave"] ~ div.sheet-nomelee, -input.sheet-profession-toggle[value="Priest"] ~ div.sheet-nomelee, -input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-nonmartialhidden2, -input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-nonmartialhidden2, -input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-nonmartialhidden2, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-warlockmelee, -input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-nonmartialhidden2, -input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-nonmartialhidden2 { - display: grid; + +@media print { + /* Set A4 size */ + @page { + size: A4 portrait; + margin: 10mm; /* Adjust margin as needed */ + } + + /* Hide documentation or unwanted sections */ + .documentation { + display: none; + } + + /* General print styles */ + body { + font-size: 12pt; /* Adjust font size */ + line-height: 1.5; + color: black; + } + + /* Format main sections */ + .character, + .base-scores, + .magic, + .inventory, + .paths-skills, + .languages, + .biography { + page-break-inside: avoid; /* Avoid breaking these sections */ + margin-bottom: 15mm; /* Spacing between sections */ + } + + /* Optional: Adjust table styles for print */ + table { + width: 100%; + border-collapse: collapse; + margin-bottom: 10mm; + } + + th, td { + border: 1px solid #000; + padding: 5px; + } } \ No newline at end of file diff --git a/Dragon Warriors/Dragon Warriors Revised.html b/Dragon Warriors/Dragon Warriors Revised.html index 0560b1f064ee..298c68c6db7b 100644 --- a/Dragon Warriors/Dragon Warriors Revised.html +++ b/Dragon Warriors/Dragon Warriors Revised.html @@ -1,2144 +1,12121 @@
-
- Dragon Warriors
- - - - - - - - - -
- -
-
- Name - Profession - Rank - Experience -
-
- -
Strength
-
Reflexes
-
Intelligence
-
Psychic Talent
-
Looks
-
-
- -
Melee Attack
-
Ranged Attack

-
Melee Defence
-
Ranged Defence
- -
-
- -
Evasion
-
-
- -
Magical Attack
-
Magical Defence
-
-
- -
Stealth

-
Perception

-
-
Dice Warriors
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- Poison Save -
-
- -
-
-
Shield
-


-
-
Roll
on
-
-
-
-
-
Equipped Weapon:
-
ABR
-
Damage
-
Sword
-
-
Equipped Weapon:
-
Ammunition Type:
-
ABR
-
Damage
-
-
Ranges:
-
Short
-
Medium
-
Long

-
Bow
-
-
-
- -
- - -
-
Berserk:
-
Defence Penalty:
-
Attack Bonus

-
-

Activate Bloodrage
-
-
- - Activate Expert Parry
- Activate Weaponskill
-
- Activate Main Guache:
Inactive Defensive Offensive -

- Activate Master Bowman -
-
- - Activate Non-Proficient Weapon -
-
-
- - Activate Armour Peircing - Activate Deathvow -
-
- - Precise Shot:
Defence Penalty
Attack Bonus

- Stillness:
Defence Penalty
Stealth Bonus

-
- Penetrating Shot Skill Level:
None Once Twice
-

- Activate Penetrating Shot -
-
- No Magic Attributes -
-
- -
-
-
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
-
-
-
-
- -
- No Magic Attributes -
-
- -
-
-
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
-
-
-
-
- -
Guard Taken
-
-
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
-
-
-
- - -
-
-

-

-
-
-
-

-

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
Psychic Fatigue Check:
- spell level

-
ESP
%

-
Premonition
%
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-
-
-
-
-
- - Magic Bonus - Armour Bypass Roll - Damage - Equipped - -
-
-
- - Magic Bonus - Armour Bypass Roll - Damage - Equipped
- Short - Medium - Long - -
-
-
- Ammunition Type - Quantity - Magic Bonus - Equipped
- Special Ammunition Modifiers: Attack - ABR - Damage
-
-
-
- -
- Item - Location - Quantity - Encumbrance Value -
-
-
-
- -
- - - -
-
- Coin Chest -
-
- - -
-
-
-
-
-
Type
-
Armour Factor
-
Magic Bonus

-
Miscellaneous Bonus
-
Non-Proficiency Penalties:
-
Attack
-
Defence
-
Stealth
-
- -
Helmed Skull
-

Shield Equipped?
-
Magic Bonus
-
-
Roll
on
-
-
-
-
-
-
Total Encumbrance

Maximum Encumbrance
-


-
Encumbrance
-
-
-
-
-
-
Base Score
-
Strength
-
Reflexes
-
Intelligence
-
Psychic Talent
-
Looks
-
-
-
-
-
Attack
-
Defence
-
Armour Bypass
-
Damage
-
-
-
-
-
Attack
-
Defence
-
Armour Bypass
-
Damage
-
-
-
-
Base Attribute
-
Attack
See Below
-
Defence
See Below
-
Stealth
-
Perception
-
Evasion
-
-
-
- -
-
- Final Melee Attack
- Final Melee Defence
- Total Melee ABR Bonus
- Total Melee Damage Bonus
-
-
-
-
-
-
-
-
- Final Ranged Attack
- Final Ranged Defence
- Total Ranged ABR Bonus
- Total Ranged Damage Bonus
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
Base Score
-
Modifier
-
Final
-
-
-
- -
-
Base Score
-
Modifier
-
Final
-
-
- -
Sword
-
-
Direct Magical Attack
-
Indirect Magical Attack
-
Spell Expiry Roll
-
-
-
Direct Magical Attack
-
Indirect Magical Attack
-
Spell Expiry Roll

-
-
- - The Elements: Earth, Air, Fire, Water, Darkness - -
- - - - -
-
- - -
-
- - -

-
- - - - -
-
-
- -
Scroll
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
- -
- Name - Range - Duration
- Description
-
-
-
-
-
-
- - Name
- Description -
-
- -
- Skill
- Description
-
-
-
- -
- Skill - Level
- Description
-
-
-
-
-
- -
- Language - Fluency Level - Literate? - Script -
-
-
- -
- Language - Fluency Level - Literate? - Script -
-
+ +
+ Dragon Warriors + + + + + + + + +
+ + + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +

Characteristics

+ +
Strength
+
+ +
+
+ +
+ +
Reflexes
+
+ +
+
+ +
+ +
Intelligence
+
+ +
+
+ +
+ +
Psychic Talent
+
+ +
+
+ +
+ +
Looks
+
+ +
+
+ +
+
+ +
+

Combat Factors

+ +
Melee Attack
+
+ +
+
Ranged Attack
+
+ +
+
Melee Defence
+
+ +
+
Ranged Defence
+
+ +
+ +
+ +
+ +

Dodging

+
+ Evasion +
+
+ +
+
+ +
+

Magical Combat Factors

+
+ Magical Attack +
+
+ +
+
+ Magical Defence +
+
+ +
+
+ +
+

Stealth and Perception

+ + +
Stealth
+
+ +
+
+ + +
+ + +
Perception
+
+ +
+
+ + +
+
+ +
+ Dice Warriors +
+ +
+

Armour

+ +
+ Shield +
+ +
+ Type +
+ +
+ +
+ +
+ Armour Factor +
+ +
+ +
+ +
+ Shield Equipped? +
+
+ Roll on +
+
+ +
+
+
+
+ +
+

Health Points

+ + Maximum Health Points: +
+ Wounds Taken: +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ Poison Save +
+ +
+

Combat Summary

+ +
+ Melee Attack + +
+
+ Equipped Weapon:
+ Type:
+ Magic Bonus:
+ + + + +
+
+ Armour Bypass Roll:
+
+
+ Damage:
+
+
+ Sword +
+ +
+ Ranged Attack + +
+
+ Equipped Ranged Weapon: + Type: + Magic Bonus:
+ +
+
+ Ammunition Type: + Ammunition Special Effect: +
+ + +
+
+
+ Armour Bypass Roll: +
+
+ Damage: +
+
+ Bow +
+
+ Ranges: +
+ Short +
+ Medium +
+ Long +
+
+ +
+ + +

Profession Abilities

+ +
+
+ Skills Known +
+ + +
+
+
+ +
+ + + +

Barbarian Profession Abilities

+
+
+ Track + +
+ Roll Track +
+
+
+
+
+ Berserk + +
+ Defence Penalty +
+ Attack Bonus +
+
+
+
+
+
+ Bloodrage + +
+ +
+
+
+ +
+
+
+ Iron Will + +
+ Activate against the following spells: Command, Curse, Transfix, Enslave, Enthrall, Benight, Turncoat, Pacify, Dark Thoughts, Winds of Change, and Witch Steed. + +
+
+
+
+
+ Intimidating + +
+ Roll Intimidate +
+
+
+
+
+ +
+ Knight Profession Abilities +
+
+ Track + +
+ Roll Track +
+
+
+
+
+ Weaponskill + + +
+ Weaponskill +
+ + +
+ Weaponskill +
+ + +
+ Weaponskill +
+ +
+
+
+
+ Main Gauche + +
+ +
+
+
+
+
+ Disarm Technique + +
+ Roll Disarm +
+
+
+ +
+
+
+ Iron Will + +
+ Activate against the following spells: Command, Curse, Transfix, Enslave, Enthrall, Benight, Turncoat, Pacify, Dark Thoughts, Winds of Change, and Witch Steed. + +
+
+
+
+
+ Intimidating + +
+ Roll Intimidate +
+
+
+
+
+ +
+

Warlock Profession Abilities

+
+
+
+ Selected Weapon Groups +
+ Weapon Group 1: +
+ + +
+
+ Weapon Group 2: +
+ + +
+
+
+
+
+
+ Appraise Enemy + +
+ Activate +
+
+
+
+ +
+

Assassin Profession Abilities

+
+
+ Shock Attack + +
+ Roll Shock Attack result: +
+
+
+
+
+ Inner Sense + +
+ GM rolls +
+
+
+
+
+ Memorize + +
+ GM rolls +
+
+
+
+
+ Disguise + +
+ Roll Disguise +
+
+
+
+
+ Pilfer + + +
+ Roll Pilfer +
+
+
+
+
+ Pick Lock + + +
+ GM rolls for possibility of success + Roll Pick Lock +
+
+
+
+
+ Track + +
+ Roll Track +
+
+
+
+
+ Deathvow + +
+ Activate + +
+
+
+
+ +
+

Mystic Profession Abilities

+
+
+ Spell Mastery + Current Mastered Spell +
+
+
+
+ ESP + +
+ ESP Chance % + Roll ESP +
+
+
+
+
+ Premonition + +
+ Premonition Chance % + Roll Premonition +
+
+
+
+ +
+

Hunter Profession Abilities

+
+
+ Favoured Weapon + +
+ Weapon type +
+
+
+
+
+ Favoured Terrain + +
+ Terrain Type +
+
+
+ + +
+
+ Precise Shot + +
+ Defence Penalty +
+ Attack Bonus +
+
+
+ +
+
+ Stillness + +
+ Defence Penalty +
+ Stealth Bonus +
+ Apply favoured terrain bonus + +
+
+
+ +
+
+ Penetrating Shot + +
+ Activate when firing at short range + +
+
+
+ +
+
+ Hunter's Mind + +
+ Activate when in the wilderness and wearing at most padded armour + +
+
+
+ +
+
+ Fast Shot + +
+ Check if second shot is possible +
+ Roll second attack at end of round +
+
+
+ +
+
+ Forage + +
+ Roll Forage +
+
+
+
+ +
+

Knave Profession Abilities

+
+
+ Favoured Language + +
+ Add +1 to Perception and +1 to Looks when communicating with humans in that language. + +
+
+
+
+ Human Intuition + +
+ +
+
+
+
+
+ Disguise + +
+ Roll Disguise +
+
+
+
+
+ Pilfer + +
+ Roll Pilfer +
+
+
+
+
+ Distract + +
+ Roll Distract +
+
+
+
+
+ Bodyguard + +
+ Use the Bodyguard to Intimidate +
+
+
+
+
+ Gossip + +
+ Roll Gossip +
+
+
+
+
+ Presence + +
+ Roll Presence +
+
+
+
+
+ Sense Falsehood + +
+ Roll Sense Falsehood +
+
+
+
+
+ Hypnotic Suggestion + +
+ Roll Hypnotic Suggestion +
+
+
+
+
+ Network + +
+ Roll Network +
+
+
+
+
+ Words are Power + +
+ Roll Words are Power +
+
+
+
+ +
+ Elementalist Profession Abilities +
+
+ Raw Power + + +
+ +
+ Attack with Raw Power: +
+ +
+ Attack with Raw Power (alternate): +
+
+
+
+
+
+ Elemental Resistance + +
+ +
+
+
+
+ +
+ Priest Profession Abilities +
+
+ Linguist + +
+ Roll Linguist +
+
+
+
+
+ Exorcism + +
+ Roll Exorcism +
+
+
+
+
+ Sermon + +
+ Roll Sermon +
+
+
+
+
+ Remove Curse + +
+ Roll Remove Curse +
+
+
+
+
+ Remove Madness + +
+ Roll Remove Madness +
+
+
+
+ +
+ Demonologist Profession Abilities +
+
+ Demonology + + +
+ Roll Demonology +
+
+
+
+
+ The Ritual of Summoning + +
+ Perform The Ritual of Summoning +
+
+
+
+
+ Banishing a Demon + +
+ Roll to Banish a Demon +
+
+
+
+
+ The Pact of the Dark Companion + +
+ Roll to summon the Dark Companion +
+
+
+
+ +
+ No Magic Attributes +
+ +
+ +
+ +

Profession Magic and Guards

+ +
+ +
+
+ Magical Combat and Spell Expiry +
+ Direct Magical Attack +
+ +
+ Indirect Magical Attack +
+ +
+
+ Spell Expiry Roll +
+ +
+
+
+ +
+
+ Warlock Magics +
+ Direct Magical Attack +
+ +
+ Indirect Magical Attack +
+ +
+
+ Spell Expiry Roll +
+ +
+
+ +
+
+ Primary Magic Points + + Magic Points: + + Magic Points used: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ +
+
+ Secondary Magic Points + + Magic Points: + + Magic Points used: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Magic Points: + + Magic Points used: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ +
+
+ + Mystic Magics + +
+ Psychic Fatigue Check: +
+
+
+ + - spell level +
+
+ +
+
+
+
+ + +
+
+ + Basic Guards + +
+ +
+
+ Modifiers: +
+ Melee Attack: +
+
+
+ +
+
+ Melee Defence: +
+
+ +
+
+ Ranged Attack: +
+
+ +
+
+ Ranged Defence: +
+
+ +
+
+ Evasion: +
+
+ +
+
+ Other Effects: +
+ + +
+
+
+
+ + +
+
+ Advanced Guards + +
+ Guard Taken + +
+
+ Guard Countered? + +
+
+ Modifiers: +
+ Melee Attack: +
+
+
+ +
+
+ Melee Defence: +
+
+ +
+
+ Ranged Attack: +
+
+ +
+
+ Ranged Defence: +
+
+ +
+
+ Evasion: +
+
+ +
+
+ Other Effects: +
+ + +
+
+
+
+ +
+ No Magic Attributes +
+ +
+
+
+ +
+ +
+

Primary Statistics

+

Characteristic

+

Base Score

+

Modifier

+
+ Strength +
+
+ +
+
+ +
+
+ Reflexes +
+
+ +
+
+ +
+
+ Intelligence +
+
+ +
+
+ +
+
+ Psychic Talent +
+
+ +
+
+ +
+
+ Looks +
+
+ +
+
+ +
+
+ +
+ +
+
+ +
+ +
+

Base Factors

+

Attribute

+

Base Attribute

+

Modifier

+ +
Attack
+
+
See Below
+ +
Defence
+
+
See Below
+ +
Stealth
+
+
+ +
Perception
+
+
+ +
Evasion
+
+
+ +
Health Points
+
+
+
+ + + +
+ + +
+ For custom professions, input the number to be added to 1d6. +
+
+
+ +
+

Miscellaneous Modifiers - Melee Combat

+

Attribute

+

Modifier

+ +
Attack
+
+ +
Defence
+
+ +
Armour Bypass
+
+ +
Damage
+
+
+ +
+

Miscellaneous Modifiers - Ranged Combat

+

Attribute

+

Modifier

+ +
Attack
+
+ +
Defence
+
+ +
Armour Bypass
+
+ +
Damage
+
+
+ +
+

Totaled Combat Factors

+ +

Final Melee Attack

+ + +

Final Ranged Attack

+ + +

Final Melee Defence

+ + +

Final Ranged Defence

+ + +

Total Melee ABR Bonus

+ + +

Total Ranged ABR Bonus

+ + +

Total Melee Damage Bonus

+ + +

Total Ranged Damage Bonus

+ + +

Current Maximum Health Points

+ +
+
+ +
+ +
+

Magical Defence

+

Base Score

+ + +

Modifier

+ + +

Final

+ +
+ +
+

Magical Attack

+ +

Base Score

+ + +

Modifier

+ + +

Final

+ +
+ +
+ + +
+ Sword +
+ +
+
+ Magical Combat Values +

Direct Magical Attack

+ + +

Indirect Magical Attack

+ + +

Spell Expiry Roll

+ +
+
+ +
+
+ Warlock Magical Combat Values +

Direct Magical Attack

+ + +

Indirect Magical Attack

+ + +

Spell Expiry Roll

+ +
+
+ +
+
+ Elements + The Elements: Earth, Air, Fire, Water, Darkness +

Primary Element

+ + +

Secondary Element

+ + +

Secondary Element

+ +
+
+ +
+
+ Primary Magic Points + Magic Points +
+
+ +
+
+ Secondary Magic Points + Magic Points + + + Magic Points + +
+
+ +
+
+ Mystic Magic + Psychic Fatigue Check: + - spell level +
+
+
+ +
+ + +
+ Scroll +
+ +
+
+ Mystic Spells of Rank One +
+
Invigorate
+
Range: Self
+
+ Description:

The Mystic converts psychic energy into physical energy, releasing a powerful restorative force into his body. He regains two Health Points. The spell will not increase his Health Point score above its normal level, of course.

+
+
+
+
Mirage
+
Range: 10m
+
Duration: Spell Expiry Roll applies
+
+ Description:

A visual illusion is created, of anything the caster wishes so long as it is no bigger than man-sized. The Mirage can be ‘programmed’ to perform a set of actions (e.g., a guard marching up and down outside a door) or it can be controlled mentally, like a holographic puppet. There is a 10% chance that the Mirage will be recognized as such at first glance.

+
+
+ +
+
See Enchantment
+
Duration: Spell Expiry Roll applies
+
+ Description

While this spell is in effect, the Mystic is able to see powerful concentrations of magic energy. He could tell whether a weapon or talisman were magical but would not be able to sense impermanent enchantments, such as the presence of a Command spell.

+
+
+ +
+
Suspended Animation
+
Range: Self
+
Duration: Preset duration up to one year and a day
+
+ Description

The Mystic is able to sink into a deep coma, outwardly resembling death. This coma lasts for any preset duration up to a year and a day. Even ESP will detect no thoughts, but in fact, the Mystic does remain aware of his surroundings—except that his mental processes are slowed by a factor of sixty.

+
+
+ +
+
Pain Mastery
+
Range: Self
+
Duration: Spell Expiry Roll
+
Origin: Khitai
+
Rarity: Common in Khitai, rare elsewhere
+
+ Description

The Mystic focuses his mind on the higher planes, distancing himself from his physical body. For the duration of the spell, the Mystic is immune to pain, enabling him to pick up flaming brands without flinching and to take the mightiest blows with no outward sign of pain. The spell has no game effect outside of the lack of pain, and does not enable the Mystic to continue fighting below 0 Health Points. The warrior monks of Khitai use this spell as a training technique for their apprentices. A few Mystic wanderers have brought this technique to the west and have sometimes used the ability to circumvent tests for righteousness, such as plucking hot irons from the fire without flinching.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Rank Two + +
+
Darksight
+
Duration: Spell Expiry Roll applies
+
+ Description

The Mystic acquires the ability to see in darkness like an Elf. That is, he can see with perfect clarity by moonlight or under a star-filled night sky, and in the pitch dark of an underworld as though it were deep twilight.

+
+
+ +
+
Dazzle
+
Range: 5m
+
Duration: One Combat Round
+
+ Description

This spell produces a flash of brilliant light that will all but blind any sighted creature within 5m for one full Combat Round. This gives the Mystic the chance to escape from his foes or make one free strike while they are dazzled, making them -8 from defence.

+
+
+ +
+
Might
+
Duration: Spell Expiry Roll applies
+
+ Description:

A powerful spell for use in combat, this has the effect of increasing the Mystic’s Strength. If his normal Strength score is 15 or less, it temporarily increases to 16; if normally 16 or more, it increases to 19.

+
+
+ Activate Might Spell: + +
+
+ +
+
Pursuit
+
Duration: Lasts one day
+
+ Description

This enables the Mystic to follow the psychic spoor of a person or creature whom he knows or has had described to him. He may thus track his quarry over terrain of any sort, and in all weathers.

+
+
+ + +
+
Mind over Matter (Nephtu’s Arm)
+
Range: Self
+
Duration: 1 Action
+
Origin: Kaikuhuran Desert (uncommon), rare elsewhere
+
+ Description

The Mystic using this spell increases his Strength to 19 for a single action. He can use this strength to break down doors, launch a devastating attack, or any other single action he can think of. The Order of Nephtu created this spell to aid them in their sacred duty to protect the hidden tombs of the Pharaohs. This last remnant of the old Kaikuhuran tomb guards practise martial arts and battle the minions of the dark God Tenubis, who sought to cast the Pharaohs from the underworld to take their power for his own.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Three + +
+
Allseeing Eye
+
Duration: Spell Expiry Roll applies
+
+ Description

This extends the Mystic’s power of vision beyond the visible spectrum, enabling him to perceive any invisible object or being within 10m. The Mystic sees the invisible shapes as featureless silhouettes.

+
+
+ +
+
Mind Cloak
+
Duration: lasts ten minutes
+
+ Description

This spell puts up a psionic shield around the Mystic, preventing detection by ESP, Scry or similar magical means. If the caster is being tracked by another Mystic using the Pursuit spell, this spell will cause the latter to lose his ‘scent’.

+
+
+ +
+
Nourish
+
+ Description

This spell ensures the Mystic need never starve when he has no food or water. A single casting provides him with refreshment and nourishment for a full day.

+
+
+ +
+
Telekinesis
+
Range: 25m
+
Duration: Spell Expiry Roll applies
+
+ Description

This is the classic parapsychic ability to move and manipulate objects at a distance by the power of the mind. The spell affects a single object of up to 0.5kg weight. The maximum velocity at which an object can be moved by Telekinesis is about 15m per Combat Round, making for a rather ineffective missile (speed 8 to dodge, and doing no appreciable damage on impact anyway). The Mystic may wield a dagger by Telekinesis, in order to melee an opponent at a distance; he would do so with half his normal attack (telekinetic control is quite clumsy) and doing 1 HP less damage for a successful blow (because there is little strength in the spell).

+
+
+ +
+
Psychic Strike
+
Range: 3m
+
Duration: Instant
+
Origin: Ancient Kaikuhuru
+
Rarity: Rare everywhere today due to its complexity
+
+ Description

The Mystic launches a combined physical and mental assault on a single target. He makes a Magical Attack against the target’s Magical Defence while at the same time launching a physical attack such as a sword blow. If the Mystic is successful with his Magical Attack, the target’s Defence is reduced to ¼ against his physical attack. The target’s Defence is otherwise unaffected.

+
+
+ Psychic Strike Spell Attack Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Four + +
+
Clairvoyance
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell intensifies the Mystic’s inherent paranormal senses, and so confers the ability to see anything within 5m even through solid objects. A full 360° arc of ‘vision’ is obtained, making it very difficult to take the Mystic unawares.

+
+
+ +
+
Enthrall
+
Range: 5m
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster must match his magical attack against his target’s magical defence. If successful, this spell warps its victim’s judgement so that he believes the Mystic to be his friend. This delusion does not destroy the victim’s loyalty to his real friends, however, and neither does it make him well-disposed towards the Mystic’s companions. He will believe anything the Mystic tells him and, unless the Mystic openly attacks him, will trust him completely until the spell wears off.

+
+
+ Enthrall Spell Attack Roll: +
+
+ +
+
Hidden Target
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell enables the Mystic to pick off targets with arrow, sling, or thrown dagger even if blindfolded. He ignores the usual penalties for poor visibility. Even in thick fog or if the target is invisible, the Mystic shoots as if he could see him perfectly. He must know there is someone to shoot at, though—he cannot just walk into a room and lob off a few arrows ‘on spec’ in case there should happen to be an invisible Sorcerer about.

+
+
+ +
+
Telepathy
+
Range: 10km
+
Duration: lasts ten minutes
+
+ Description

The Mystic is able to communicate telepathically with another (who must be known to him) over considerable distances. Communication is in the form of images as well as words, so different languages need not prove an insurmountable obstacle. Note, however, that two characters from totally different cultures (a medieval wizard and an Inca priest, for instance) may be simply unable to think in the same terms.

+
+
+ +
+
Monkey Brother
+
Range: Self
+
Duration: 1 hour
+
Origin: Mungoda and Khitai
+
Rarity: Common in Mungoda and Khitai, rare elsewhere
+
+ Description

This spell infuses the Mystic with the essence of a monkey. For one hour the Mystic climbs as if he had a Reflexes score of 18. In addition, the Mystic can travel through forests and jungles by swinging from branch to branch, covering up to 20 km per hour in this manner. When the spell wears off, the Mystic’s Reflexes are reduced by 1 for an hour due to exhaustion and sudden unfamiliarity with his leaden human limbs.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Five + +
+
Force Field
+
Duration: Spell Expiry Roll applies (and see below)
+
+ Description

This spell protects the Mystic with a thin, invisible force barrier. When a blow is struck against him, the Force Field absorbs the damage and prevents it from harming him. Once it has absorbed a total of 15 HP damage, the Force Field collapses. It gives no protection from magical weapons, spells, or other forms of attack (such as flames or poisonous fumes).

+
+
+ +
+
Mystic Blast
+
Range: 30m
+
+ Description

This spell takes the form of a psychic force bolt. The caster must match the spell’s speed of 16 against the target’s evasion. If it strikes its target, the bolt inflicts 3d6 +1 HP damage. The target may reduce this damage by his Armour Factor, if any. (A character in mail armour would take only 3d6 –3 HP, for example.)

+
+
+ Mystic Blast Spell Attack Roll: +
+
+ +
+
Pass Unseen
+
Duration: Spell Expiry Roll applies
+
+ Description

The Mystic becomes invisible... up to a point. He can walk right past his enemies and they will not notice him. This is not as good as true Invisibility (the high-level Sorcerer variety) because he will still reflect in a mirror, and becomes visible at once if he tries to attack anybody or casts another spell. Also, the spell will only fool beings of 1st to 4th rank/rank-equivalent.

+
+
+ +
+
Truthsense
+
Duration: Spell Expiry Roll applies
+
+ Description

While the spell lasts, the Mystic is able to tell with 85% accuracy when someone is lying to him. That is, if a character tells him a lie, d100 is rolled. On a roll of 01-85, he knows it to be a lie. On a roll of 86-00, he is not sure one way or the other. The d100 roll is made secretly by the GamesMaster, for obvious reasons.

+
+
+ Truthsense Spell Effect Roll: +
+
+ +
+
Whisper of the Muse
+
Range: Self
+
Duration: Spell expiry roll applies
+
Origin: Khitai and Emphidor
+
Rarity: Uncommon in Khitai and Emphidor, rare elsewhere
+
+ Description

This spell provides the Mystic with amazing flashes of insight and creativity. Until the spell wears off, the Mystic becomes supernaturally creative and can tell a spell-binding, original story, recite enchanting poetry, write epic tales, or hold an audience captive with their tunes. He might also gain insight into puzzles and plots if the GM so wishes.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Six + +
+
Assessment
+
Range: 10m
+
+ Description:

By means of this spell, the Mystic can instantaneously assess all characters within range and determine the following: their Profession, rank (or rank-equivalent), and current Health Points. Assessment is blocked by Mind Cloak and will not give any information about characters above 10th rank.

+
+
+ +
+
Purification
+
+ Description

This spell cleanses the Mystic’s body of all ailments and poisons, and heals up to 8 Health Points if he is wounded.

+
+
+ +
+
Steel Claw
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster’s hand is transformed into a rigid talon of gleaming metal. When he strikes with this in combat, he uses a d12 for Armour Bypass Rolls and inflicts 8 HP damage with each successful blow.

+
+
+ Steel Claw Spell Melee Attack +
+
+ +
+
Survival
+
Duration: lasts one day
+
+ Description

The Mystic is able to endure extremes of heat and cold, such as might be experienced under a blazing desert sky or in an arctic waste. He is not protected from direct exposure to fire. Survival also enables the Mystic to go without air for up to an hour after drawing a single breath.

+
+
+ +
+
Fleeting Enlightenment
+
Range: Touch
+
Duration: Spell Expiry
+
Origin: Unknown
+
Rarity: Uncommon throughout Legend
+
+ Description

This spell enables the target to cast a single first-rank Mystic spell as if he were a Mystic of rank equal to the caster. The Mystic chooses the spell the target can cast. The target can cast the spell repeatedly until he fails a fatigue roll or the duration of Fleeting Enlightenment runs out. The spells cast by the target have their own spell expiry rolls and do not fail with the Fleeting Enlightenment spell.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Seven + +
+
Duel
+
Duration: see below
+
+ Description

To use this spell, the Mystic must close in mêlée with an opponent. The spell shifts both the Mystic and his opponent out of phase with the rest of the universe; they remain visible only as a flickering, indistinct blur. Out-of-phase characters are on another plane and cannot affect (or be affected by) their surroundings. Unable to move from the spot where they ‘phased out,’ the two combatants must continue their battle until one is slain. Only then does the spell terminate, returning them—alive or dead—to the normal world.

+
+
+ +
+
Levitation
+
Duration: Spell Expiry Roll applies, and see below
+
+ Description

This spell allows the caster to rise up into the air and float around. Levitational movement is quite slow—only 10m per Combat Round (normal walking speed, in other words). This spell requires concentration to sustain. If the Mystic wants to enter mêlée or cast another spell, he must first cancel the Levitation.

+
+
+ +
+
Paralysis
+
Range: 15m
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster must match his magical attack against his target’s magical defence. This spell, if it takes effect, results in paralysis of all the voluntary muscles. It will work only on a living being. The victim collapses at once but remains conscious. Another Mystic who was affected by this spell could still cast spells of his own, since Mystics need only the power of their psyche to work magic and do not rely on the chants and arcane gestures of the Sorcerer.

+
+
+ Paralysis Spell Attack Roll: +
+
+ +
+
Protection
+
Duration: lasts until Dispelled, and see below
+
+ Description:

A potent spell that adds 2 points to the caster’s magical defence and increases his Armour Factor by 2. The caster can sustain the Protection spell indefinitely if he chooses to, but he must add +1 to the die roll whenever he makes a Psychic Fatigue Check while the Protection spell is in effect.

+
+
+ +
+
One Mind
+
Range: 10m
+
Duration: Spell expiry roll applies
+
Origin: Mungoda
+
Rarity: Common in Mungoda, rare elsewhere
+
+ Description

This spell links the minds of everyone within range and, with eerie and silent coordination, those affected work together as if a single being. The spell is commonly used for hunting or tribal warfare. All physical actions undertaken while under the effect of the spell gain a +1 bonus for every two people in the link to a maximum of +5.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Eight + +
+
Intangibility
+
Duration: Spell Expiry Roll applies
+
+ Description

The Mystic and any items he is wearing or carrying become intangible. He can pass through solid objects as though they were not there. While intangible, a magical weapon is required to hit him in combat. Indirect-attack spells like Firestorm pass harmlessly through his insubstantial form, though direct-attack spells are still fully effective. The Mystic must take care when using this spell, for if it expires while he is inside a solid object he will die.

+
+
+ +
+
Mindpool
+
Range: 3m
+
Duration: lasts thirty seconds (5 Combat Rounds)
+
+ Description

This spell enables two Mystics to combine their power for a brief time. With multiple castings, more Mystics can be included in the Mindpool—up to five individuals at one time. Mystics in a Mindpool each resist hostile direct-attack spells with the total magical defence of the whole group, and each casts his own spells with the highest magical attack of the group.

+
+
+ +
+
Swiftness
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell accelerates the caster’s metabolism and physical movements. The caster gets two actions for every one Combat Round experienced by others. The first action is taken at the start of each CR, and the second occurs at the point in the CR when he would normally act. However, the Mystic cannot cast two spells in one CR because his thinking remains at normal speed.

+
+
+ +
+
Trance
+
Duration: lasts ten minutes
+
+ Description

The Mystic enters a trance-like state while his psychic self, or ka, is freed from his body and can travel up to five kilometres. The ka can see and hear, but is ethereal and cannot interact with or be seen by others. However, characters of equal or higher rank may sense it. Another Mystic could use Pursuit to trace the ka back to its body.

+
+
+ +
+
Serpent Trance
+
Range: Self
+
Duration: Spell Expiry Roll
+
Origin: Unknown
+
Rarity: Rare throughout Legend
+
+ Description

The Mystic opens his mind to his enemies’ thoughts, anticipating their next attacks before they make them. This spell grants the Mystic a base +5 in Defence that applies to all attacks made against him. In addition, the Mystic takes no penalties for fighting blind or being attacked from behind.

+
+
+ This spell requires you to manually add +5 to your defence, as it applies to each opponent and is not divided against multiple attackers. +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Mystic Spells of Level Nine + +
+
Impregnable Sphere
+
Duration: Spell Expiry Roll applies
+
+ Description

The Mystic is surrounded by an invisible force bubble that blocks all physical attacks. Neither missiles, creatures, nor indirect-attack spells can pass through the Sphere. However, direct-attack spells (requiring a magical attack vs magical defence roll) are unaffected. The Sphere is stationary, and the Mystic must remain in place.

+
+
+ +
+
Phoenix
+
Duration: Instant (must cast after death)
+
+ Description

This spell allows the Mystic to return from the dead if cast the Combat Round after being slain. The body burns fiercely, and after 5 Combat Rounds the Mystic rises from the ashes, fully healed but with 1 permanent HP reduction. Any equipment is destroyed, with exceptional magic items potentially surviving at the GM's discretion. This spell can only be cast once per week.

+
+
+ +
+
Teleport
+
Range: 100m
+
+ Description

The Mystic can vanish and reappear at a point within 100m. He can only teleport to a location he has been to before or can see when the spell is cast.

+
+
+ +
+
Thunderclap
+
Range: 1m
+
+ Description

The Mystic can blow a wall down with one shout! In fact, the shout is a focus for the immense destructive energy of the psyche. If directed at an opponent who fails to jump clear (match the spell’s speed of 12 vs the target’s evasion), the spell inflicts 6d6 +6 HP damage. Unenchanted armour gives no protection from this, and even enchanted armour absorbs only 2 HP. The Thunderclap can be used to smash a 2m-wide hole in stone walls up to half a metre thick.

+
+
+ Thunderclap Spell Attack Roll: +
+
+ +
+
Quavering Voice
+
Range: 20m
+
Duration: Instant
+
Origin: Krarth and Yamato
+
Rarity: Uncommon in Krarth and Yamato, Rare elsewhere
+
+ Description

The Mystic uses his own voice to draw upon the darkest power of the mind. He begins with a humming noise that soon becomes a single clear note that can strike dead any living thing hearing it. The caster can target a single sentient living being and slay it on a successful Spell Attack Roll. Alternatively, the Mystic can target up to four non-sentient living beings to slay in place of a sentient. The spell has no effect on undead or beings like golems.

+
+
+ Quavering Voice Spell Attack Roll +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+ +
+ Sorcerer Spells of Rank One +
+
Dragonbreath
+
Range: 20m
+
+ Description:

Range: 20m This spell creates a narrow jet of flame which can be directed at a single target. If the target fails to dodgethe flame (match the spell’s speed of 12 against the target’s evasion) he takes 1d6 +6 Health Points damage. This damage roll is reduced by the target’s Armour Factor, however, so a character in plate armour would lose only 1d6 +1 HP.

+
+
+ Dragonbreath Spell Attack Roll: +
+
+ +
+
Image
+
Range: 20m
+
Duration: see below
+
+ Description

The caster can create a visual image of no greater than man-size; this is nearly perfect, and has only a 10% chance of being recognized to be an illusion. The Image is a kind of hologram, and cannot be made to move around. It will last until touched or Dispelled.

+
+
+ +
+
Lesser Healing
+
Range: touch
+
+ Description

This spell restores 2 Health Points to a wounded character. It will not increase his Health Point score above its normal (unwounded) level, of course. Lesser Healing cannot bring a character back from the dead—such a feat is possible in the Dragon Warriors world, but more potent sorcery than this is needed!.

+
+
+ +
+
Moonglow
+
Duration: lasts for ten minutes
+
+ Description:

A circle of light 5m in radius surrounds the caster, who can dim the intensity to zero or brighten it to about the level of the full moon’s light, at will. Unlike torchlight, the illumination provided by this spell is sufficiently diffuse that it may not alert monsters lurking nearby. A party of characters using no other light source but Moonglow have a chance (the usual 1 in 6) of surprising any monster they meet.

+
+
+ +
+
Portal
+
Range: touch
+
Duration: see below
+
+ Description

This spell may be used in either of two ways. Open Portal will thrust open any door which could normally be forced by a character of Strength 16. The second mode of the spell, Close Portal, shuts andlocks a door magically. This form of the spell is durational, and will stay in effect until Dispelled or broken by physical force.

+
+
+ +
+
Weaken
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
+ Description:

Match the caster’s magical attack vs target’s magical defence. The character on whom this spell takes effects will be weakened. He temporarily loses 2 attack points and inflicts 1 less point of damage than usual when striking in combat.

+
+
+ Weaken Spell Attack Roll: +
+
+ +
+
Witchbane
+
Range: 10m
+
Duration: Instant
+
Origin: Algandy
+
Rarity: Common in Algandy, uncommon elsewhere
+
Replaces: Dragonbreath for Algandish Sorcerers
+
+ Description:

A stream of emerald flame bursts from the Sorcerer’s fingertips to engulf a single target. This spell works on all manner of supernatural entities but has no effect on a normal human – even one trained in the black arts. If a normal human is targeted the flame washes about him leaving him unharmed, though likely terrified. If the spell hits a supernatural being (Speed 12 versus the targets Evasion), the target suffers 1d6+6 damage reduced by its Armour Factor. This spell prevents a Sorcerer from being a threat to a knightly warrior while making them an excellent tool for rooting out “evil beings”.

+
+
+ Witchbane Spell Attack Roll: +
+
+ +
+
Bedevil
+
Range: 10m
+
Duration: Permanent
+
Origin: Algandy
+
Rarity: Common throughout Legend
+
+ Description

The Sorcerer casts this spell on a single tool, weapon, or implement. The target can be no larger than a small cart or plough. The spell causes the item to attempt to thwart any action a user tries to undertake with it. For example, a compass will give false readings, a hammer might strike a thumb, and a saddle might become undone. The spell rarely causes serious injuries but, for example, using a bedevilled rope to climb a mountain can be suicidal. The spell remains until the Sorcerer removes the spell or a Dispel Magic spell is cast on the item. Any Sorcerer who knows this spell can cast a “counter curse” on a bedevilled item.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Two + +
+
Detect Aura
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell enables the caster (or another on whom he casts the spell) to see the supernatural aura which surrounds enchanted beings and objects.

+
+
+ +
+
Hold Off the Dead
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell creates a zone around the caster, 2m in radius, which affects Undead whose rank-equivalent does not exceed the caster’s rank. If such Undead enter the zone, they are immediately subject to a magical attack (match the caster’s magical attack against the Undead’s magical defence). If successful, the spell prevents them from approaching the caster as long as the enchantment lasts.

+
+
+ Hold Off the Dead Spell Effect Roll: (roll when an Undead attempts to enter the area of effect) +
+
+ +
+
Inflict Wound
+
Range: 3m
+
+ Description:

Match the caster’s magical attack against the target’s magical defence. If successful, this inflicts a wound of 5 Health Points on the victim. Armour provides no protection against this damage.

+
+
+ Inflict Wound Spell Attack Roll: +
+
+ +
+
Peer
+
Range: 20m
+
Duration: Spell Expiry Roll applies, and see below
+
+ Description:

When this spell is cast, the Sorcerer specifies any point within the spell’s range (e.g. “14m due north of me”, “5m straight down”, etc.). He is then able to see anything that is happening within 3m of the specified point as though he were standing there. The spell is not hampered by intervening walls or floors unless these are made of metal; more than 2cm thickness of metal will block a Peer spell. The spell will expire immediately if the caster moves around while it is operating.

+
+
+ +
+
Tangleroots
+
Range: 15m
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell affects one target, causing a tangle of magical creepers to sprout out of the ground and ensnare his legs. If the target fails to leap clear (match spell’s speed of 14 vs target’s evasion) then he is caught and immobilized. With an edged weapon it is possible to cut oneself free within 2–8 Combat Rounds (roll 2d4); beings of great strength (Strength 16 or more) will be able to pull free of the roots in only 1–3 rounds, and animals such as Wolves will take 2–12 rounds to claw and chew through the roots. This spell is commonly used either to hold any enemy while trying to escape from him or to prevent him evading a more devastating follow-up spell.

+
+
+ Tangleroots Spell Attack Roll +
+
+ +
+
Warding
+
Duration: Spell Expiry Roll applies
+
+ Description:

Warding enhances the Sorcerer’s luck in combat. Any character attempting a Hit Roll against him, whether in mêlée or with a missile weapon, must add 2 to the d20 score.

+
+
+ +
+
Echoes of Spyte
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
Origin: Krarth
+
Rarity: Uncommon in Krarth and rare outside of that foul land
+
+ Description:

When cast, the Sorcerer must pick a point anywhere within 20m of where he stands. Until the spell expires or is cancelled, the Sorcerer hears everything as if he were standing at that point. This spell was used by the Krarth Magi of old to spy upon their rivals and enemies. Following the Blasting of Spyte, the remaining apprentices carried this spell out of the ruins, teaching it to their followers and spies as needed.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Three + +
+
Banquet
+
+ Description:

Enough food and drink is created to provide one meal for five people. The food is nourishing but—despite the spell’s appetising name—rather bland. Few would care to eat it if they had a choice; but when adventurers are starving they will fall upon Banquet fare enthusiastically enough!

+
+
+ +
+
Beacon
+
Range: 15m
+
Duration: Spell Expiry Roll applies
+
+ Description:

If any invisible object or being is within range when Beacon is cast, the spell causes a glowing ball of green light to appear just above it. This light will move as the invisible object/being moves, thus marking out its location.

+
+
+ +
+
Command
+
Range: 5m
+
Duration: Spell Expiry Roll applies
+
+ Description:

A successful casting of this spell (match caster’s magical attack vs target’s magical defence) brings the victim (who must be of 1st–3rd rank) under the Sorcerer’s control. He will then do whatever the caster tells him to do. Commanded beings do not become mindless slaves; they retain their normal intelligence and ability to reason, and are thus capable of following quite complex orders. Language barriers may be a problem—if the victim cannot understand what his ‘master’ is saying to him then he will simply act in what he believes to be his master’s best interests.

+
+
+ Command Spell Attack Roll: +
+
+ +
+
Greater Healing
+
Range: 5m
+
+ Description:

A more powerful version of Lesser Healing. It restores 7 Health Points to the recipient, with the same provisos as for the level-one spell (p. 80).

+
+
+ +
+
Illusion
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell creates an illusion no greater than two cubic metres in volume. This differs from an Image in two ways; the Illusion will move as the caster wishes, and it fools not just sight but the other natural senses as well. There is thus very little chance of distinguishing an Illusion from the real thing; even a rigorous examination gives only a 5% chance of this. If he wishes, the Sorcerer can cast Illusion over a character (himself included) in order to provide a near-perfect disguise. When overlapped in this way, the Illusion must be equal in at least one linear dimension to the thing it is covering. A man could thus be covered by the Illusion of a 2m-long snake, but not by the Illusion of a gnat. It is important to remember that Illusions exist only in the minds of those who behold them. An Illusion could not cast a spell, inflict a wound, carry treasure, open doors, or in any other way affect the real world.

+
+
+ +
+
Wolfcall
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell is usable only out-of-doors—in moorland, woods, and dense forest, the wild places where Wolves hunt. It summons one Wolf (see p. 253) to the caster’s side to fight for him. The Wolf will arrive 2–12 Combat Rounds after the spell is cast and will then remain until the spell wears off. The Sorcerer does not start making Spell Expiry Rolls until the Wolf turns up. (A note for the literal-minded: there does not actually have to be a Wolf nearby for Wolfcall to work. The Wolf may in fact be brought across miles of countryside in barely a minute, by the working of the Sorcerer’s magic.)

+
+
+ Wolfcall Time to Arrival: +
+ Wolf Stats +
    +
  • Attack: 15
  • +
  • Weapon: Fangs (d4, 5 points)
  • +
  • Defence: 3
  • +
  • Armour Factor: 0
  • +
  • Evasion: 3
  • +
  • Magical Defence: 1
  • +
  • Health Points: 1d6+4
  • +
  • Movement: 12m (25m)
  • +
  • Stealth: 16
  • +
  • Perception: 11
  • +
+
+
+
+ +
+
Summon Lesser Djinn
+
Duration: Spell Expiry Roll
+
Origin: Ta’ashim lands
+
Rarity: Common in Ta’ashim lands, rare elsewhere
+
+ Description

The Sorcerer calls upon the power of the seven great Djinn sultans to summon one of their lesser servants; a whirling cloud of sand about half the size of a man. This lesser Djinn can do anything a normal human can, such as serving food, opening doors, carrying, and lifting. The Djinn cannot attack and, being a cloud of sand and air, is immune to non-magical damage. A few northerners have managed to learn the secrets of this spell and it can be found from time to time in the hands of well-travelled Sorcerers. Those who frequently abuse the sultan’s servants (for example by getting them to open obviously trapped doors all the time) may feel the wrath of the Djinn lords.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Four +
+
Antidote
+
Range: 5m
+
+ Description

This reduces the potency of poisons or drugs in a character’s bloodstream. A poison which normally requires a 3d6 roll compared to the character’s Strength (see p. 122 in Chapter 11) is reduced to one which requires a 2d6 roll, etc. The spell must be applied within one Combat Round (six seconds) of the character being poisoned. It does not reverse any damage or other effects already caused by the poison.

+
+
+ +
+
Curse
+
Range: 15m
+
+ Description

This spell affects up to four beings (roll 1d4), cursing them with bad luck if it is successful (match caster’s magical attack vs target’s magical defence). Cursed beings must adjust all their die rolls by 2 so as to make them less favourable—i.e., +2 to the die score when making a Hit Roll, –2 when making an Armour Bypass Roll, etc.

+
+
+ Curse Number of Targets: + Curse Spell Attack Roll: +
+
+ +
+
Disease
+
Range: 15m
+
Duration: lasts until Dispelled
+
+ Description

A single living being may be afflicted with a rotting disease (match caster’s magical attack vs target’s magical defence). The victim loses 2 Health Points every Combat Round until cured or dead.

+
+ Disease Spell Attack Roll: + +
+ +
+
Oracle
+
Duration: lasts for one minute
+
+ Description

The Sorcerer attunes himself to the spirit world and is able to ask up to three questions. The questions must be phrased in such a way that they can be answered by a yes or a no. The spirits have a 75% chance of knowing the answer to any question they are asked. (The GamesMaster rolls d100. On 01–75 they know the answer; on rolls of 76–00 they don’t.) If they do not know the answer to a question, or if the question is worded vaguely, the spirits will give a random answer (roll d6: 1–3 = yes, 4–6 = no), and they will then stick to that answer if asked the same question again. The spirits can speak only of events concerning the past and present. They cannot see into the future, nor answer questions which concern a character’s thoughts and motives.

+
+
+ Spirit Knowledge Effect Roll: +
+
+ +
+
Shadowbolt
+
Range: 20m
+
+ Description

Causes an ebon bolt of energy to shoot from the caster’s hand to strike a single being. If the bolt hits (match spell’s speed of 14 vs target’s evasion), it does 2d6+10 HP damage. The damage roll is reduced by a number equal to the target’s Armour Factor, if any (see the Dragonbreath spell on p. 89).

+
+
+ Shadowbolt Spell Attack Roll: +
+
+ +
+
Wall of Magic
+
Range: Touch
+
Duration: Spell Expiry Roll applies, and see below
+
+ Description

The caster—or another on whom he casts the spell—is surrounded by a protective zone that will block enemy spells. The caster may expend as many points as he likes when casting the Wall of Magic (down to a minimum of 4 MP), and this is the number of Magic Points the Wall will absorb from spells cast into it. Once it has absorbed its Magic Point limit, the Wall collapses. Wall of Magic blocks only direct-attack spells, however—i.e. those that involve a magical attack vs magical defence roll. Indirect-attack spells such as Shadowbolt are unaffected. If the Wall collapses without having absorbed all the Magic Points from an incoming spell, the spell still has a chance of taking effect but the attacking Sorcerer or Mystic must adjust his attack die roll by the difference between the number of MPs left in the spell and the spell’s level.

+
+
+ +
+
Udjat
+
Range: Self
+
Duration: Spell Expiry Roll
+
Origin: Kaikuhuru
+
Rarity: Rare everywhere due to its obviously pagan effect.
+
+ Description

Upon casting this spell, a golden, glowing, eye-shaped glyph appears on the Sorcerer’s forehead. The spell increases the Sorcerer’s Psychic Talent and Intelligence to 16 or raises a score of 16-17 to 18. The Sorcerer gains all the associated bonuses for having these characteristics.

+
+
+ Activate Udjat Spell: + +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Five + +
+
Banish
+
Range: Touch
+
Duration: Lasts until Dispelled
+
+ Description

For this spell to take effect, the caster must actually touch his intended victim in the Combat Round following that in which he cast the spell. This means that the caster must make a successful Hit Roll on his opponent—though no Armour Bypass Roll is needed, as it is sufficient that he merely touch the opponent’s clothing or armour. If the spell takes effect (match caster’s magical attack vs target’s magical defence) the victim is banished to limbo, and can only be freed at the caster’s whim or if a Dispel Magic (see p. 84) is cast at the spot where the victim disappeared. A Sorcerer can communicate in his dreams with those he has banished, and will usually find them quite eager to barter information and secrets in return for a promise of freedom from limbo.

+
+
+ Banish Melee Attack Roll: (does not need to bypass armour) + Banish Spell Attack Roll: +
+
+ +
+
Divination
+
Duration: Lasts one minute
+
+ Description

A modification of the Oracle spell which enables the caster to ask a question even if the answer is not a simple yes/no. Only one question may be asked, and there is still the same limit (75%) on accuracy. The spirits will often answer in the form of a rhyme, riddle, or obscure clue—the GM is urged to be inventive and evasive! A Sorcerer may not cast more than one Divination in a single day.

+
+
+ Divination Spell Effect Roll: (to be rolled by GM) +
+
+ +
+
Fossilize
+
Range: 20m
+
Duration: Lasts until Dispelled
+
+ Description

If the spell is successful (match caster’s magical attack vs target’s magical defence), one being is turned to stone, along with anything he is wearing or carrying. Fossilize has no effect on Gargoyles (their bodies are made of rock in the first place) nor, for obvious reasons, on non-corporeal creatures such as Spectres.

+
+
+ Fossilize Spell Attack Roll: +
+
+ +
+
Mantlet
+
Duration: Spell Expiry Roll applies
+
+ Description

This highly useful spell surrounds the caster with an enchanted zone 3m in radius. Any arrow, quarrel, slingshot or other missile entering this zone will fall harmlessly to the ground. Magical or extremely large (more than 20kg) projectiles are not impeded by the spell, however.

+
+
+ +
+
Reanimate the Dead
+
Range: 5m
+
Duration: Spell Expiry Roll applies
+
+ Description

Using this necromantic spell, the Sorcerer can raise up to six (roll 1d6) dead Humans, Elves or Dwarves as Zombies (see p. 253) under his control. Zombies, having only limited intelligence, will not be able to comprehend complex instructions—the Sorcerer must limit his commands to four words or less.

+
+
+ Reanimate the Dead Number of Undead Summoned: +
+
+ +
+
Transfix
+
Range: 20m
+
Duration: Spell Expiry Roll applies (and see below)
+
+ Description

If the caster is successful (match caster’s magical attack vs target’s magical defence) then 2-8 beings (roll 2d4 for the number affected) suffer a ‘brainstorm’ which causes them to stop what they are doing and stand passively until the spell wears off. Afterwards, they will be unable to remember anything that happened while the spell was in effect or in the two Combat Rounds just before it was cast. If a Transfixed character is attacked, the spell is immediately broken.

+
+
+ Transfix Number of Targets: + Transfix Spell Attack Roll: +
+
+ +
+
Mask of Tooth and Claw
+
Range: Self
+
Duration: 5 Minutes then Spell Expiry Roll applies
+
Origin: Mungoda
+
Rarity: Uncommon in Mungoda and parts of Mercanian Coast, rare elsewhere
+
+ Description

By donning a carved wooden tiger mask the caster transforms into a sabre-tooth tiger. This grants the Sorcerer the physical aspects of the tiger like its vision, attacks, and movement speed. The spell does not change the caster’s other attributes, but does prevent him from speaking and casting spells. The spell is uncommon now and considered barbarous and uncouth by more “civilized” Sorcerers.

+
+
+ +
+
Mask of Feather and Talon
+
Range: Self
+
Duration: 5 Minutes then Spell Expiry Roll applies
+
Origin: Mungoda
+
Rarity: Uncommon in Mungoda and parts of Mercanian Coast, rare elsewhere
+
+ Description

The Sorcerer dons a stylized bird of prey mask, transforming into a raptor. The Sorcerer retains his normal attributes but gains the physical shape, size, and flight ability of a bird. Normal birds can sense the magic and flee from the Sorcerer while he is in this form.

+
+
+ +
+
Lugh’s Spear
+
Range: 2m
+
Duration: Spell Expiry Roll
+
Origin: Ellesland/Mungoda
+
Rarity: Uncommon in Ellesland and Mungoda, rare elsewhere
+
+ Description

This spell summons forth a spear of white ash with a copper head. Eldritch fire dances around the spear’s tip. The spear hovers beside and moves with the caster, automatically attacking any being within 2 meters, friend or foe. The spear can make one attack per round with an Attack of 22 (1d8, 5). The spear counts as a magical weapon. If the spear is struck in combat (Defence 23), it vanishes immediately. This spell was common among the early tribes of Albion but fell out of common use as most of Albion’s native Sorcerers died on the end of a legionnaire’s sword. In a strange case of parallel development, this spell has been seen among witchdoctors in Mungoda, where it is known as Ghost Assegai.

+
+
+ Lugh's Spear Melee Attack: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Six + +
+
Armour
+
Duration: Spell Expiry Roll applies
+
+ Description

The spellcaster becomes encased in jet-black plate armour with an Armour Factor (AF) of 6. It does not hinder spellcasting, and any clothing or armour the caster is already wearing is transformed. This spell cannot be stacked with other armours to increase AF.

+
+
+ Activate Armour spell: + +
+
+ + + +
+
Cure Disease
+
Range: 1m
+
+ Description

This spell cleanses the target of all illnesses, whether natural or supernatural in origin. Damage already suffered as a result of the disease is not healed.

+
+
+ +
+
Dishearten
+
Range: 30m
+
+ Description

If cast successfully (match caster’s magical attack vs target’s magical defence), this spell causes the victim’s heart to explode, killing them instantly. It has no effect on Undead or creatures without a heart. If it fails, the target still suffers 1d4 HP of damage.

+
+
+ Dishearten Spelll Attack Roll: + Dishearten Spell Fail Damage: (the target takes damage even if the spell is unsuccessful) +
+
+ +
+
Dispel Magic
+
Range: 5m
+
+ Description

This spell ends any durational spells within its range, provided the spells being dispelled cost fewer Magic Points than the Dispel Magic. It affects both enemy and caster's own spells.

+
+
+ +
+
Phantasm
+
Duration: Spell Expiry Roll applies
+
+ Description

The Sorcerer summons an ectoplasmic creature. The creature’s form may vary but always has fixed abilities: magical defence of 8, evasion of 5, AF 4, 4-24 Health Points (roll 4d6), and attack/defence values summing to 28. It moves at a rate based on its appearance, with 10m/round for human-like forms.

+
+
+
+ Phantasm Stats +
    +
  • Attack:
  • +
  • Weapon: Ectoplasmic Strike (1d10, 5)
  • +
  • Defence:
  • +
  • Armour Factor: 4
  • +
  • Evasion: 5
  • +
  • Magical Defence: 8
  • +
  • Health Points: 4-24 (4d6)
  • +
  • Stealth: (@{stealth})
  • +
  • Perception: (@{perception})
  • +
  • Movement: m/round (based on form)
  • +
+

Note: Attack and Defence values must sum to 28.

+
+
+
+ +
+
Sword of Damocles
+
Range: 10m
+
Duration: Until activated
+
+ Description

A glowing sword appears above the target, following them until the caster commands it to strike. Unless dodged (match its speed of 17 vs the target's evasion), it deals 4d6 HP damage on a successful hit. The sword vanishes after its attack.

+
+
+ Sword of Damocles Spell Attack Roll: +
+
+ +
+
Ushabti
+
Range: Touch
+
Duration: Spell Expiry Roll or 1 hour
+
Origin: Ancient Kaikuhuran spell
+
Rarity: Rare
+
+ Description

The Sorcerer touches a pre-prepared stone figurine (Ushabti), transforming it into a servant or bodyguard. The duration depends on the figurine used. A warrior figurine creates a guardian who vanishes upon a Spell Expiry Roll. A worker figurine produces a non-combat servant that lasts one hour. In both cases, the Ushabti reappears undamaged after the spell expires.

+

The tombs of ancient Kaikuhuran magi are filled with various forms of Ushabti, including animals and objects. Some tomb robbers claim to have discovered greater Ushabti spells in these tombs.

+
+
+
+ Ushabti Guardian +
    +
  • Attack: 20
  • +
  • Weapon: Shortsword (d8, 3)
  • +
  • Defence: 15
  • +
  • Armour Factor: 4 (Stone)
  • +
  • Evasion: 3
  • +
  • Magical Defence: 10
  • +
  • Stealth: 9
  • +
  • Perception: 7
  • +
  • Health Points: 20
  • +
+
+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Seven + +
+
Deathlight
+
Range: 40m
+
+ Description

A very powerful bolt of energy leaps from the caster’s hands, forking to strike 1-4 beings (match spell’s speed of 16 vs targets’ evasion). A being failing to evade takes 3d6+10 HP damage (reduced by Armour Factor, if any).

+
+
+ Deathlight Number of targets: + Deathlight Spell Attack Roll: +
+
+ +
+
Enslave
+
Range: 30m
+
Duration: Spell Expiry Roll applies
+
+ Description

This powerful variant of the Command spell affects a single being of any rank. A successful casting (match caster’s magical attack vs target’s magical defence) renders the victim completely subservient to the Sorcerer’s will. The victim becomes an unthinking slave, obeying only the Sorcerer’s direct commands. Language barriers are no issue; the victim will always understand instructions but follows them literally, which can sometimes lead to unexpected outcomes. Issuing or changing orders takes one Combat Round.

+
+
+ Enslave Spell Attack Roll +
+
+ +
+
Nova
+
Range: 5m
+
+ Description

Myriad beams of searing light shoot from the caster’s body in all directions. Any being within 5m who fails to evade (match spell’s speed of 18 vs targets’ evasion) is struck by 1-3 beams (roll 1d6: 1-2 = 1 beam, 3-4 = 2 beams, 5-6 = 3 beams). Each beam inflicts 3d8 HP damage, reduced by Armour Factor.

+
+
+ Nova Spell Attack Roll: + Nova Spell Damage Roll: (roll once for each target) +
+
+ +
+
Spell Screen
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell creates a defensive enchantment around the Sorcerer that protects from direct-attack spells (those involving a magical attack vs magical defence roll). The Spell Screen reduces any attacking spell by 5 Magic Points (MPs). The strength of the Spell Screen does not diminish over time. Casting multiple Spell Screens does not provide additional protection. If overlapped with a Wall of Magic, spells affect the Wall first, then the Screen. The Spell Screen only protects the caster and not external objects or weapons they carry.

+
+
+ +
+
Stasis
+
Range: 20m
+
Duration: Until Dispelled
+
+ Description

The caster can ‘freeze’ 1-3 victims in time (match caster’s magical attack vs target’s magical defence). Frozen characters cannot think, act, move, or be harmed in any way. They remain in stasis until the spell is dispelled.

+
+
+ Stasis Spell Attack Roll: +
+
+ +
+
Vorpal Blade
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster summons a magical sword as black as midnight, surrounded by green fire. This weapon grants the Sorcerer a +3 bonus to attack and defence while wielding it. It deals 1d8 +3 Armour Bypass and 7 HP damage on a successful hit. If the caster puts down the weapon, it vanishes immediately. If offered to another, it strikes the Sorcerer once and disappears forever.

+
+
+ Vorpal Blade Spell Melee Attack: +
+
+ +
+
Shoulders of the Colossus
+
Range: Touch
+
Duration: Spell Expiry Roll
+
Origin: Ancient Emphidor
+
Rarity: Uncommon everywhere
+
+ Description

This spell causes the person touched to grow until they reach 4m in height. The character gains 19 Strength for the duration of the spell. Their possessions grow proportionally, and any armour gains a +2 bonus to AF due to the thickening effect. This spell is useful for reaching high spaces, terrifying or impressing others, or crossing long distances quickly (Movement 15m (30m)). This spell can be cast on an unwilling target by making a standard Magical Attack versus the target’s Magical Defence.

+
+
+ Shoulders of the Colossus Spell Attack Roll: (when cast at an unwilling target) +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Eight + +
+
Astral Gate
+
Duration: See below
+
+ Description

A shimmering portal, a rent in the very fabric of space itself, is created in front of the caster. This portal leads to any place the caster wishes to reach (not more than 150km away), allowing characters to cross this distance in the blink of an eye. The intended destination should be a spot which the caster knows reasonably well. If he is trying to reach a place he has only seen once, the caster has a 40% chance of ‘missing’ by up to a hundred metres (roll d100 for the distance out and d8 for direction—1 = north, 2 = northeast, 3 = east, etc). If aiming for a destination he has never seen, and is guided only by another’s account, the caster has a 50% chance of missing by up to a kilometre.

+

The Astral Gate will teleport only living beings and whatever they are wearing or carrying. It is not possible to lob a Shadowbolt through first, to take care of anyone at the far end! As each character passes through the Gate, a d6 is rolled. On a roll of 6, the spell expires. A Sorcerer must take three Combat Rounds to visualize his intended destination before casting Astral Gate. Unless he takes this precaution, there is a 60% chance that the far end of the Gate will emerge onto another plane of reality, and any character passing through will then be lost forever.

+
+
+ +
+
Bastion
+
Duration: Spell Expiry Roll applies
+
+ Description

Motes of glittering light spread from the caster’s hands and rapidly spread, ‘painting’ a surface in the air as they do. Within a second, an impenetrable steel-grey barrier has been created. This barrier has a maximum surface area of some 25 square metres, and may be made to form a hemisphere roughly 4m across (within which the Sorcerer may shelter while healing himself or casting more defensive spells) or a wall (blocking a dungeon corridor, perhaps, while the caster and his companions speed away from their foes).

+
+
+ +
+
Burden
+
Range: 15m
+
Duration: Spell Expiry Roll applies
+
+ Description

Cast at an area of ground, the Burden spell causes the pull of gravity to become so overwhelmingly strong that any being standing there will fall down and be unable to move until the spell expires. Very large creatures fare no better than smaller and weaker ones: “the bigger they are...” The spell affects a circular area up to 5m across, extending upwards into the air no more than 3m. (It is not much use, therefore, against a flying creature.) The caster’s enemies have a chance to jump clear when he casts the spell, and this is represented by matching the spell’s speed of 16 against their evasion scores. No such opportunity is available to those who blunder into the zone once the spell has taken effect, however; they are remorselessly pulled to the ground.

+
+
+ Burden Spell Attack Roll: +
+
+ +
+
Destrier
+
Duration: See below
+
+ Description

This conjuration is usable only at night or in the lightless depths of an underworld, as it summons a demonic Warhorse which is driven back to its fey world by the rays of the dawn. It will also vanish at once if the Sorcerer dismounts. The Destrier is a sere black steed clad in tarnished silver armour; its eyes burn with an emerald light. Any seeing it will know it to be a faerie beast, and characters of 1st–3rd rank subtract 1 from attack when fighting it. The Destrier can carry its master across a hundred kilometres of open country or woodland in a single night. It is fierce and terrible in battle.

+

Note that it is only by this spell that a Sorcerer can ride a Warhorse. Normal Warhorses are available only to Knights, Barbarians and Warlocks.

+
+
+
+ Destrier Stats +
    +
  • Attack: 17
  • +
  • Weapon: Silver-shod hoofs and teeth (Bite 1d8+1, 4 or Kick 1d10+1, 6)
  • +
  • Defence: 4
  • +
  • Armour Factor: 3 (Silver barding)
  • +
  • Evasion: 4
  • +
  • Magical Defence: 13
  • +
  • Health Points: 2d6+12
  • +
  • Stealth: 8
  • +
  • Perception: 12
  • +
  • Special Abilities: Elfsight (see p. 123)
  • +
+
+
+
+ +
+
Evil Eye
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster of the spell becomes touched by the spirit of the Fomori demi-god Balor, whose gaze is Death. The caster’s left eye is filled with a fathomless dark. Any character mêléeing him has a 40% chance of meeting the hideous stare of this eye. This check is made at the end of each Combat Round. (The chance may be less than 40% if the caster’s opponent looks away or shuts his eyes—as for Gaze Attacks, p. 123). A character who looks into the eye’s gaze is subject to a 1d12 Fright Attack (see Fright Attacks, p. 122): a twelve-sided die is rolled and the victim’s rank is subtracted from the score. If the caster can roll less than or equal to the result on 2d10, the victim dies.

+

The user of this spell temporarily loses sight in the affected eye. Thus deprived of binocular vision, he subtracts 1 point from attack and 2 points from both defence and evasion while the spell lasts.

+
+
+ Evil Eye Chance to Meet Gaze Roll: + Evil Eye Fright Attack Roll: +
+
+ +
+
Rune
+
Duration: Lasts until activated
+
+ Description

This is a notorious spell used as a magical trap by high-ranking Sorcerers; experienced adventurers are always wary of stumbling across a Sorcerer’s Rune. The Rune is cast by inscribing an occult symbol on a wall, flagstone, tapestry or other suitable object. The Sorcerer can then cast into it any other spell that he is able to use. This spell will be held by the Rune and released if anyone except the caster comes within 3m line of sight. The Rune must be exposed if it is to work, but Sorcerers can be quite artful in contriving abstract murals or odd locations (the ceiling? behind a door?) to keep others from noticing a Rune before it goes off. A Sorcerer may have only one Rune at any given time.

+
+
+ +
+
Possession
+
Range: 10m (Initial casting)
+
Duration: 5 minutes, then Spell Expiry applies
+
Origin: Krarth
+
Rarity: Uncommon in Krarth; rare elsewhere
+
+ Description

This spell enables a Sorcerer to transfer his consciousness to another human’s body, taking control of the target. While this spell is active the Sorcerer’s own body collapses as if in a deep sleep. If the Sorcerer’s body suffers injury or death while he possesses another the spell ends immediately. To possess a target the Sorcerer must overcome their Magical Defence score. While possessing his target the Sorcerer has no access to their skills or powers and cannot cast spells himself. When the spell ends the target has no memory of anything that happened while he was possessed.

+
+
+ Possession Spell Attack Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Nine + +
+
Animate Bones
+
Range: Touch
+
+ Description

By casting this over the skeletal remains of someone the Sorcerer slew, the caster can animate the remains into a Skeleton. The Skeleton is simple-minded and fully obedient, possessing attack 10, defence 5, evasion 3, magical defence 3, and 2-7 Health Points (roll 1d6 + 1).

+
+
+
+ Skeleton +
    +
  • Attack: 11
  • +
  • Weapon: Skeletons will fight unarmed, unless they can acquire a weapon.
  • +
  • Defence: 5
  • +
  • Evasion: 3
  • +
  • Magical Defence: 3
  • +
  • Health Points: 2-7 (1d6+1)
  • +
+
+
+
+ +
+
Battlemaster
+
Duration: Spell Expiry Roll applies
+
+ Description

A supernatural, obsidian-armoured warrior is summoned from another Plane and bound in the caster’s service for the period of the spell. The Battlemaster is clad in magical mail armour and wields a magic axe. His characteristics and scores are:

+

When the spell runs out the Battlemaster returns to his own dimensional Plane, where any wounds he has received are supernaturally healed before the next time he is summoned. Although any given Sorcerer can materialize the Battlemaster only once per day, he exists on many planes simultaneously and it is thus possible for two Sorcerers actually to summon him at the same time. If the Battlemaster should be ordered to attack himself (i.e. another Battlemaster summoned by a different Sorcerer), his two selves will merge into one and he will be freed from the control of either summoner. He will then proceed to wreak havoc before returning to his own world.

+
+
+
+ Battlemaster +
    +
  • Attack: 30
  • +
  • Weapon: Axe (d8 +2, 8 points)
  • +
  • Defence: 24
  • +
  • Armour Factor: 6
  • +
  • Evasion: 8
  • +
  • Magical Defence: 17
  • +
  • Stealth: 12
  • +
  • Perception: 18
  • +
  • Health Points: 24
  • +
  • Strength: 18
  • +
  • Reflexes: 13
  • +
  • Special Abilities: Panoptical vision
  • +
+
+
+
+ +
+
Firestorm
+
Range: 30m
+
+ Description

The caster flings a ball of snarling flames which explodes into an inferno of 6m diameter. Characters will take 4d10 +4 HP damage if they fail to jump clear (match spell’s speed of 18 vs targets’ evasion)— and 4 HP damage even if they do, simply from the peripheral heat of this terrible blast! A target wearing magic armour (of any sort) may reduce the damage he takes by 3 points; armour that is not enchanted provides no defence.

+
+
+ Firestorm Spell Attack Roll: +
+
+ +
+
Invisibility
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster is rendered invisible. If his opponents become aware of his general location (perhaps he sneezed or knocked over a vase, or they saw him begin to cast the incantation), he may be attacked with spells. Direct-attack spells affect an invisible target normally, but indirect-attack spells are subject to a penalty of 1d8 speed points to represent their likelihood of being slightly off-target. A character attempting to mêlée the invisible Sorcerer incurs a penalty of –4 from attack and –8 from defence (just like fighting blind, of course—see p. 61). Missile weapons are almost useless against one who is invisible: the bowman halves his normal attack and subtracts 3. Sir Balin, who has an attack of 13, therefore shoots at an invisible enemy as though with an attack of only 4.

+
+
+ +
+
Miracle Cure
+
Range: 5m
+
+ Description

This spell restores the recipient to his normal Health Point score, cures any diseases and eradicates any toxins he is suffering from, and regenerates any missing limbs or organs. As with the Lesser Healing and Greater Healing spells, it has no effect on a dead character.

+
+
+ +
+
Raise Fog
+
Duration: Spell Expiry Roll applies
+
+ Description

With the casting of this spell (which must be used out-of-doors), a dense mist quickly rises to cover an area 60m across by 5m high. This area is centred on the Sorcerer’s position when he cast the spell. The Sorcerer himself can see quite normally within the fog, but for others the visibility is barely 3m.

+
+
+ +
+
Spirit Leech
+
Range: 10m (Initial casting)
+
Duration: Spell expiry applies
+
Origin: Kingdom of Wyrd
+
Rarity: Rare
+
+ Description

With a dread incantation, the Sorcerer summons forth this flying spectral worm from some dark dimension. The Spirit Leech cannot survive without magical energy, and attacks the nearest being to it (excluding the caster) that has Magic Points. The Spirit Leech can be blocked by magical shields like Spell Screen, but these defences only last a single round against it. The Spirit Leech moves at a base speed of 30m. Once the Spirit Leech makes physical contact with the target (Attack 23 against Defence, armour does not protect) it latches onto it, automatically drawing 5 MP from the unfortunate each turn. The Spirit Leech is impervious to all attacks, but can be destroyed by depriving it of Magic Points for two consecutive rounds. Smart magicians might cast a series of durational spells, let the leech vanish and then cancel their spells to recoup some of their lost power. There are reasons that the Magi of Krarth do not push their claim to the Kingdom of Wyrd.

+
+
+ Spirit Leech Melee Attack Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Sorcerer Spells of Level Ten + +
+
Doppelganger
+
+ Description

A soulless duplicate of a known person can be created using a clay simulacrum mixed with the caster’s own blood, resulting in a permanent 1d4 Health Point loss. The duplicate takes on the physical characteristics and skills of the original, but lacks reason, volition, and knowledge skills. It cannot walk on consecrated ground or cast a reflection.

+
+
+ +
+
Hecatomb
+
Range: 10m
+
+ Description

This spell causes instant death to all beings within 10m (match caster’s magical attack vs victims’ magical defence). The caster suffers a severe magical backlash, losing 1-100 experience points as a result.

+
+
+ Hecatomb Spell Attack Roll: + Hecatomb Spell Backlash Effect: (the caster suffers when using this spell) +
+
+ +
+
Pentacle of Entrapment
+
Duration: Three days
+
+ Description

This spell requires a large pentacle about 5m across to be drawn or engraved. When the spell is cast, the pentacle becomes a trap for the caster’s enemies. The first 2–12 beings of up to 5th rank to come within 20m (they must be able to see the pentacle) are subject to the spell. Those on whom it takes effect (match caster’s magical attack vs victim’s magical defence) will be instantaneously transported within the pentacle’s boundary. Though unharmed, they will be powerless to escape unless they know the ‘key’ word (arbitrarily chosen by the Sorcerer when he cast the spell) that unlocks the Pentacle of Entrapment. The spell is also negated if any part of the pentacle design is erased, but this cannot be accomplished by one trapped within it.

+
+
+ Pentacle of Entrapment Number of Targets Roll: + Pentacle Spell Attack Roll: (roll once for each target that comes into range, up to maximum targets) +
+
+ +
+
Resurrect
+
Range: Touch
+
+ Description

Restores life to a character who has been dead for no more than 28 days. The character loses 1d3 Health Points permanently, and their Strength and Reflexes are halved for one week. The spell must be cast at sunrise, and the caster cannot use spells above the fifth level for the rest of the day.

+
+
+ +
+
Scry
+
Duration: Three minutes
+
+ Description

Enables the Sorcerer to look into a specially prepared obsidian mirror to view far-off places, people, or past events. The mirror cannot show specific locations, penetrate physical barriers, or see onto consecrated ground. If a Sorcerer of equal or higher rank is observed, they will know and can cancel the spell, shattering the mirror.

+
+
+ +
+
Transformation
+
Duration: Three minutes
+
+ Description

The caster transforms into any creature whose rank-equivalent does not exceed their own rank. The Sorcerer retains their Health Points, magical attack, and magical defence, but gains the fighting skills of the new form. Magic cannot be used unless the form is humanoid.

+
+
+ +
+
Sleep of Ages
+
Range: Touch
+
+ Description

This spell places a willing target in a sleep lasting 100 years or until a specific condition is met. The target does not age during this time and can only be awakened by Dispel Magic or physical damage.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+
+ Warlock Spells of Level One +
+
Eyes of Night
+
Range: 20m
+
Duration: lasts for ten minutes
+
+ Description

The Warlock’s eyes glow brightly, casting a beam of red light to a distance of 20m. This enables him to see perfectly even in utter darkness, and by looking at something, they can illuminate it so that their companions can see it. Use of this spell temporarily reduces the Warlock’s stealth score by 2 and negates any chance of surprising their enemies.

+
+
+ +
+
Heal Injury
+
Range: touch
+
+ Description

The caster can use this spell to recover 1d4 HP when wounded. Alternatively, they can use it to treat an injured comrade. The spell cannot bring a character back from the dead (reduced to –3 HP or below), nor increase a character’s Health Points above their normal score.

+
+
+ +
+
Imperil
+
Range: touch
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

For this spell to take effect, the Warlock must touch the intended victim within one Combat Round of casting: that is, their next action after casting the Imperil spell must be a successful hit either with their hand or a mêlée weapon. If their Hit Roll fails, the spell is wasted. The spell will pass through clothing and armour, however, and does not depend on a successful Armour Bypass Roll. If it takes effect (match caster’s magical attack vs target’s magical defence), the victim is rendered more vulnerable to wounds. Any wound they takes from a mêlée weapon (i.e. swords, spears, etc., but not arrows or crossbow bolts) while the spell lasts will be for 1 Health Point more than usual. A character under this spell thus takes 5 HP damage from a normal sword, 7 HP from a battleaxe, and so on.

+
+
+ Imperil Melee Attack Roll: (needs to touch target, but not damage) + Imperil Spell Attack Roll: +
+
+ +
+
Perception of Sorcery
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This spell enables the Warlock to sense magic within a range of 3m. By concentrating on an object or being, they may be able to determine whether it is enchanted or under the effect of a spell. They is not able to determine anything about the nature or strength of the spell. Perception of Sorcery is not infallible; a d20 roll is made (by the GM) for each object/person scrutinized, and the Warlock only senses any spells present if the roll is under their Psychic Talent score. (Having got a negative result, successive examinations of the same object/person will continue to yield the same result unless a spell is later cast on it—see the description of Sixth Sense on p. 34). The Warlock must take a full Combat Round for each object or being they wishes to investigate using this spell.

+
+
+ +
+
Silent Warrior
+
Range: 5m
+
Duration: lasts one Combat Round
+
+ Description

A phantasmal warrior is created to strike at one of the caster’s enemies or perform some other action taking no more than one round. The Silent Warrior cannot be harmed, but they can be dispelled by means of a Ring of Negation, Dispel Magic, or Terminate Enchantment if there is time to do this before they attacks. They strikes at the end of the Combat Round in which they was created; their attack score is 18 and their greatsword is a (d10, 5) weapon. After this single blow, they fades out of existence.

+
+
+ Silent Warrior Melee Attack Roll: +
+
+ +
+
Battle Brother
+
Range: Self
+
Duration: Spell expiry applies
+
Origin: Emphidor
+
Rarity: Uncommon
+
+ Description

This spell summons an illusion of a heavily armed and armoured warrior to guard the Warlock’s flank. The warrior takes its appearance from the Warlock with subtle changes that make him more threatening, such as adding 6 inches to their height, larger weapons, or a scar or two. The Battle Brother shouts and threatens anyone approaching the Warlock from the back or side, both warning the caster of sneak attacks and acting in an intimidating manner to ward off attackers.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Two + +
+
Camouflage
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This spell enables the caster to blend in with whatever they is standing against, covering him with the illusion of a stone wall, a hedgerow, an open field, or whatever. They adds +2 to their stealth score and suffers no stealth penalty for lack of cover (see p. 63). However, they only gains these benefits when more than 5m from their enemies—at closer ranges, the Camouflage spell is ineffective.

+
+
+ +
+
Fearlessness
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

While under this spell, the Warlock cannot be affected by Fright Attacks (see p 122). The spell prevents him from experiencing the emotion of fear. It does not turn him into a berserker. Low-ranking characters are apt to become a little reckless when using the spell, but more experienced Warlocks will be accustomed to its effects and should be better able to distinguish between lack of fear and lack of caution.

+
+
+ +
+
Fortune
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This is an all-purpose ‘good luck’ charm. It enhances the Warlock’s chance of success in anything they attempts. In game terms, they may add or subtract 1 from any dice roll they makes—but they can only apply its modifier to one dice roll in any given Combat Round. That means that they could increase their chance of hitting an opponent, say, but they could not also increase the chance of the same blow striking through armour. They must declare when they is taking advantage of the spell’s effect before making the roll. The spell also may be used to influence rolls made by the GM on the player’s behalf. It cannot influence rolls made by other characters (e.g., a Hit Roll made by the Warlock’s opponent). The Fortune spell itself is excluded from its effect; the caster cannot use it to influence its own Spell Expiry Rolls.

+
+
+ +
+
Inquiry
+
+ Description

This spell enables the caster to assess instantaneously all characters within a radius of 15m to determine whether they are protected by some defence (such as Spell Screen or Wall of Magic) which shields against direct-attack spells. The caster may also be able to determine the strength of such defences. The chance of doing this is rank ×20%: the GM rolls d100, and if the score is less than or equal to the Warlock’s rank ×20, then they is told the strength of the magical defences. If the roll fails (and a 96–100 is always counted as a failure in this case), then the GM gives a misleading result within 1d8 Magic Points of the defence’s actual strength. Inquiry does not distinguish between the various types of direct-attack shields; it merely informs its caster of the total Magic Points (or spell-levels, in the case of a Mystic) that could be blocked by the shields at the instant of probing (A Spell Screen cannot be distinguished from a 5 MP Wall of Magic, for example).

+
+
+ +
+
Warning
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

A small bell, apparently fashioned of red gold, appears in the air behind the caster and floats noiselessly along with him when they moves. Being ethereal, it cannot be seized out of the air or separated from the caster by any means. Its function is to produce a warning clangour if they is about to be attacked, thus negating any chance of surprise or shock attack against him.

+
+
+ +
+
Djinn-Borne Leap
+
Range: Self (20m)
+
Duration: Instant
+
Origin: Caliphate of Zhenir
+
Rarity: Common in Zhenir, rare elsewhere
+
+ Description

A quick invocation to the seven great Djinn sultans enables the Warlock to leap vast distances trailing blue flames and sparks in their wake. The Warlock can use this spell to make a single leap of up to 20m in any direction. The spell carries the caster in a parabolic arc, so making it impossible to leap straight up using the spell. The high point of the arc is about 10m which is enough to clear most castle walls. The sparks that rain to the ground with the Warlock’s passing are likely to ignite flammable objects such as dry straw.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Three + +
+
Deceit
+
Range: touch
+
Duration: lasts one day
+
+ Description

The Warlock can apply this spell to a character (including themself) or object so that detection spells will obtain a false reading. They could, for example, apply it to an enchanted talisman so that it would register as non-magical under Detect Aura, or use it to make themself appear more or less powerful than they really is to a Mystic using the Assessment spell. The spells and abilities which may be fooled by Deceit are: ESP and Premonition, Detect Aura and Oracle, See Enchantment and Assessment, Perception of Sorcery and Warning. The spell always works against characters whose rank does not exceed the Warlock’s. More experienced magic-users have a chance (20% per rank higher than the Warlock’s) of realizing they are being deceived.

+
+
+ +
+
Enhancement
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This spell temporarily increases the Warlock’s Strength and Reflexes: if the characteristic is 17 or less it increases to 18, if it is normally 18, it increases to 19. After the spell wears off, both characteristics are depleted 1 point below their normal scores until sunset. The Warlock can go on to use this spell a second and third time, etc., in the same day—but each use depletes the normal characteristic scores by a further point, and they must not reduce either score below 1.

+
+
+ Activate Enhancement spell: + + Enhancement Spell Negative Modifier + +
+
+ +
+
Havok
+
Range: 12m
+
+ Description

This releases a glittering wave of energy that engulfs a single being; according to legend, it is sometimes possible to glimpse a giant ghostly hawk within the light of the blast. If it hits its target (match spell’s speed of 14 vs target’s evasion), the spell inflicts 3d10 HP damage. The damage roll is reduced by the target’s Armour Factor (if any).

+
+
+ Havok Spell Attack Roll: +
+
+ +
+
Illusion
+
Range: 20m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

Except for the different Spell Expiry probability, this is identical to the Sorcery spell of the same name (see p. 82). An Illusion of up to 2 cubic metres volume can be created, and even if examined closely there is only a 5% chance of distinguishing it from reality. An illusory sentry thus looks and sounds just like a real person, and even feels solid to the touch. It can be made to seem to attack someone who believes it and (although it is illusory and therefore not able to actually harm him) its sword will make a convincing clang and give off a shower of illusory sparks when it strikes their own. The Illusion can be cast onto a character (including the caster) in order to give a near-perfect disguise, with the single limitation that the Illusion must be equal in at least one linear measurement to the size of the thing it is covering.

+
+
+ +
+
Telekinesis
+
Range: 25m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This is the same as the Mystic spell of the same name (see p. 91). The caster can lift and move an object weighing up to 500 grams (1 pound) without touching it. Telekinesis does not move an object with any great speed or force—a missile would have a speed of 8; while a dagger or cudgel could be wielded at half the caster’s normal attack, but would inflict only 2 HP on a successful hit.

+
+
+ +
+
Ibn-Azi’s Shattering Blow
+
Range: Touch
+
Duration: Instant
+
Origin: Newly discovered in the Ta’ashim lands, virtually unknown outside of the Caliphate
+
Rarity: Rare in the Caliphate
+
+ Description

The Warlock lands a resounding blow on their target, causing any armour worn to fly apart in a spasm of leather and steel. The Warlock must make successful attack and armour bypass rolls or the spell fizzles. The spell does no permanent damage to the armour, but requires at least ten minutes of work to reassemble the pieces. The spell has no effect on targets with natural armour such as hair, thick skin, or scales. Beings of earth, stone, and metal like Automatons, Earth Elementals, Gargoyles, and Golems take 2d4 HP damage from this spell but suffer no armour factor reduction.

+
+
+ Ibn-Azi’s Shattering Blow Melee Attack Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Four + +
+
Aegis
+
Duration: 1d20 Spell Expiry Roll applies
+
+ Description

The Aegis spell provides the Warlock with a magical protection which takes effect when they is about to be struck by a weapon (whether in mêlée or by an arrow, etc.) or by an indirect-effect spell (see p. 75). On a roll of 1 on 1d6 the attack is negated.

+
+
+ +
+
Neutralize Toxin
+
Range: touch
+
Duration: 1d20 Spell Expiry Roll applies
+
+ Description

While this spell is in effect, poisons that enter the character’s body are immediately neutralized. If the spell is cast on a character after they has been poisoned, then it will prevent him from taking further damage but will not restore any Health Points already lost.

+
+
+ +
+
Oracle
+
Duration: lasts for one minute
+
+ Description

This duplicates a Sorcerer’s ability to contact the spirit Plane and put questions to its denizens (see p. 82). Three yes/no questions may be asked within the one minute the spell lasts, and there is a 75% chance that the spirits will know the answer to each. If they do not know, they will answer randomly, and will also do this if the question is phrased ambiguously. Questions about the future or a character’s thoughts will not be answered—the spirits speak only of tangibles, not speculations and fancies. It is quite important for the GM to time a player-character who uses this spell. Players should not be allowed to look at a watch, as accurate timekeeping devices are very rare in the medieval world of Dragon Warriors.

+
+
+ Oracle Spirit Knowledge Chance Roll: +
+
+ +
+
Turncoat
+
Range: 5m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

If successful (match caster’s magical attack vs target’s magical defence), this spell causes a single enemy of the caster’s party to switch sides and attack their own comrades. It can only be cast once a fight is in progress and has no effect on a lone foe (i.e., one who has no comrades to turn against). An affected character does not lose their hostility to the caster—if and when they has slain all their own companions, they will resume their attack on the caster’s party even if the spell is still operating.

+
+
+ Turncoat Spell Attack Roll: +
+
+ +
+
Vitality
+
+ Description

This restorative spell has the effect of adding up to 12 HP to the Warlock’s Health Points score when they is injured. It will not take him above their normal (unwounded) Health Points score, of course. Vitality can only be used to heal the Warlock themself; it has no effect on another character.

+
+
+ +
+
Faestus’ Wrath
+
Range: 10m
+
Duration: Spell Expiry Roll
+
Origin: Emphidian Empire
+
Rarity: Common today in Selentine lands, rare elsewhere
+
Replaces: Turncoat for Selentine Warlocks
+
+ Description

The Warlock casts this spell on an enemy’s weapon, making a magical attack as usual against the target's Magical Defence. If the attack is successful, the weapon leaps and twists in the owner’s hand, attempting to strike him repeatedly. The weapon attacks once per round with an Attack of 16, inflicting damage as if it was wielded by its owner. Exceptionally strong warriors beware! Anyone with Reflexes and Strength scores of 13 each can grab the weapon holding it in place and preventing it from attacking. Keeping the weapon at bay counts as a full action, and someone performing that action cannot move or attack without letting go of the weapon.

+
+
+ Faestus’ Wrath Spell Attack Roll: + Faestus’ Wrath Melee Attack Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Five + +
+
Force of Will
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This spell gives the Warlock the ability to completely ignore pain, allowing him to stay in combat until virtually hacked apart if need be. They does not black out on reaching 0 HP and must be reduced to –20 HP in order to kill him. Under the effect of this spell, it is thus possible to endure terrible wounds and then use Vitality or Heal Injury to restore oneself before the spell wears off. Of course, if the Force of Will spell should expire when the Warlock’s HP score is –3 or less, then they dies at once.

+
+
+ +
+
Hellfire
+
Range: 15m
+
Duration: lasts until dispelled or extinguished
+
+ Description

A character or creature who succumbs to this spell (match caster’s magical attack vs target’s magical defence) immediately bursts into flames. They takes 3d6 HP damage every round until the Hellfire is extinguished. Armour gives no protection (it is the victim’s body that is burning), and non-magical armour will be burnt away by the flames, losing 1 point from its Armour Factor each round. The Hellfire can be countered with Dispel Magic or Terminate Enchantment, or the flames can be beaten out. This requires a roll of 6 on 1d6, but before attempting this, each round the victim must roll equal to or under their rank on d8. Failure means that they starts to panic and can do nothing to save themself. Comrades can also try to put out the flames by pouring on water, smothering them with a cloak or whatever; each character attempting this rolls 1d6 and, as before, the flames go out on a roll of 6. Helping in this way is risky, though, because any character within 2m of the victim suffers 1d6 HP burn damage every round (in this case, less Armour Factor, if any).

+
+
+ Hellfire Spell Attack Roll: + Hellfire Ongoing Effects Roll: + Hellfire Victim Extinguish Attempt Roll: + Hellfire Area of Effect Damage Roll: (roll for each living being within 2m of the victim) +
+
+ +
+
Slow
+
Range: 12m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This causes 1-8 beings to move and think at half normal speed (caster’s magical attack vs targets’ magical defence). Slowed beings may only act in alternate Combat Rounds. Unless they has higher Reflexes than the Warlock and has thus acted already, an affected character loses their action (see p. 70) for the Combat Round in which the spell is cast.

+
+
+ Slow Number of Targets Roll: + Slow Spell Attack Roll: (roll once against each target) +
+
+ +
+
Soulbane
+
Range: 15m
+
+ Description

With this spell, the Warlock can fling a tendril of black fire that burns the psychic essence of the one it strikes (match spell’s speed of 17 vs target’s evasion). The effect of the spell is to reduce the target’s magical attack (if any) and magical defence by 2d8 points. If the target is wearing enchanted armour, then they can reduce the dice rolls by the armour’s magic bonus. Neither score will be reduced below 0, and depleted scores recover at the rate of 1 point every Combat Round. Note that this is an indirect-effect spell and is not impeded by Wall of Magic, Spell Screen, etc.

+
+
+ Soulbane Spell Attack Roll: +
+
+ +
+
Terminate Enchantment
+
Range: 5m
+
+ Description

erminate Enchantment dispels a single durational spell. As with Dispel Magic, it does not affect spells which were cast with more Magic Points than itself. If they directs it at a character who is under more than one durational spell, the Warlock must specify which spell they is trying to terminate—if they does not, the GM determines randomly which spell is affected.

+
+
+ +
+
Apep’s Fang
+
Range: Touch
+
Duration: Instant
+
Origin: Ancient Kaikuhuru
+
Rarity: Rare
+
+ Description

In the shadows of the Kaikuhuran Empire, the Warlock-Priests of Apep wielded weapons laced with venom that they claimed came from the fangs of their dread master. This spell envenoms a single blade as if it were coated in a single dose of Assassin’s Lotion. All standard rules for Assassin’s Lotion apply.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Six +
+
Annihilate
+
Range: 15m
+
+ Description

This silent spell affects a single being of up to 8th rank or rank-equivalent (match caster’s magical attack vs target’s magical defence). The victim is utterly destroyed and cannot be restored to life by any known means. Special note: If a player-character or important NPC should fall prey to an Annihilate spell, the GM may allow the other player-characters to discover some way to bring him back to life. This should not be an easy task—Divination or another magical source might reveal that they can recover their soul only by travelling to another Plane of reality or even venturing into Hell! Retrieving their body would then be another task; perhaps their original body would turn out to be lost forever, and their only hope would be for the soul to be bound into the body of the Warlock who slew him. The idea is that Annihilate is a very deadly spell but it should generally be possible for the player-characters to achieve even an ‘impossible’ task if they are prepared to persevere with the arduous quest it entails.

+
+
+ Annihilate Spell Attack Roll: +
+
+ +
+
Lunacy
+
Range: 2m
+
+ Description

This baleful conjuration can only be employed outdoors when the moon is in the night sky. It causes the Warlock’s eyes to fill with the cold, deranging gleam of moonlight. A character facing him in close combat at that moment has an 80% chance of looking straight into their eyes, and if this happens, the character is subject to a Fright Attack of intensity 21. Instead of killing the character, this Fright Attack drives him into a state of hopeless insanity. They becomes a mewling halfwit who can do no more than grin and gurgle unintelligibly. There is a drawback to this spell. In the round they casts it, the Warlock is blinded and consequently at –8 defence.

+
+
+ Lunacy Chance to Meet Gaze Roll: + Lunacy Fright Attack Roll: +
+ +
+ +
+
Panoply
+
Duration: 1d20 Spell Expiry Roll applies
+
+ Description

An invisible force surrounds and protects the Warlock, giving him a +2 bonus to their Armour Factor. If they is wearing mail armour, for instance, they gets a total AF of 6 as long as the spell lasts.

+
+
+ Activate Panoply Spell: + +
+
+ +
+
Sigil of Destiny
+
Duration: lasts one day
+
+ Description

o use this spell, the Warlock predicts something that might befall him or one of their companions in the next twenty-four hours and ‘seals’ their prediction with the Sigil of Destiny. The idea is that by making this prediction they prevents it from coming true. The prediction usually concerns a fatality (“I will be killed by a swordblow” or “Sir Cuthbert will slip while climbing and die from the fall”), though the Warlock can predict a non-fatal occurrence (e.g. “I will be wounded by a sword-blow”). If the occurrence happens as predicted within twenty-four hours, the Sigil is activated and cancels out the effect. For example, suppose the Warlock predicted that they would be slain by a dragon and this in fact happens. The last fatal wound is immediately negated as if it had never happened and combat proceeds—no doubt with the dragon wondering why its fiery breath didn’t leave so much as a scorch mark on the armour of this Warlock. The following limitations apply to the Sigil of Destiny:

+

The prediction must indicate death/wounding/ incapacitation by:

+

    +
  • i. a WEAPON—the weapon type must be specified (sword, spear, etc); the effect of the Sigil will be to negate the crucial wound;
  • +
  • ii. a CREATURE—any nonhuman species; in this case, the weapon (if any) does not need to be specified;
  • +
  • iii. a SPELL—the spell level and attack mode (direct or indirect) must be specified; the Sigil prevents it from affecting the protected character;
  • +
  • iv. as a result of a failed roll on Reflexes, Strength (includes poisons) or Intelligence—the characteristic involved must be specified;
  • +
+

the Sigil allows the character to take the roll again, this time with automatic success. The prediction must relate to a single character, and only that character can be saved by the Sigil. Each casting of this spell is good for only one ‘extra life’ and is then used up — you cannot predict taking a wound from a Skeleton and thus acquire total invincibility against every Skeleton you encounter while exploring the Labyrinth of Aktrium. The spell only covers effects that are direct, instant and obvious. Consider a Warlock who, having predicted death from a sword-blow, is struck a non-fatal wound with a sword. The sword happens to be coated in a slow-acting poison from which they dies several hours later. The sword may be said to have brought about their death, but only indirectly (it was actually the poison that killed him). The Sigil would not come into effect in this case.

+
+
+ +
+
Vaporize
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

The caster changes into a cloud of reddish mist. In this form, they is immune to normal (non-magical) weapons and to indirect-attack spells such as Energy Bolt. They can drift along at a rate of 3m per Combat Round and seep through even the smallest cracks, so only hermetic obstacles like Bastion can bar their way. While in vapour-form, the Warlock cannot cast spells, though durational spells that they cast beforehand continue to operate.

+
+
+ +
+
Call to Arms
+
Range: Self and up to 5 companions within 10m
+
Duration: Instant
+
Origin: Khitai
+
Rarity: Common in Khitai, uncommon elsewhere
+
+ Description

With a cry of alarm and a few quick gestures, the Warlock girds themself and their companions for battle. This spell instantly wakes the targets, places their weapons in their hands, and dons their armour. The weapons and armour must be accessible to the targets and within 10m of the caster. This spell is a favourite with civilized Khitai Warlocks travelling through the dark and dangerous western lands.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Seven +
+
Nemesis
+
Range: 15m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This spell increases the effectiveness of any attack the Warlock makes on one selected character within 15m: they can adjust their Hit Rolls, Armour Bypass Rolls and damage scores against the character by 3 points each. Any spells they casts at the character gain +3 to speed or magical attack (whichever is applicable), and if the spell inflicts damage on its target, then that is increased by 3. If the Warlock can slay their chosen foe while the Nemesis spell lasts, they gets twice the regular experience points award (see p. 129)—but if the foe is killed by someone else or is still alive when the spell wears off, the Warlock immediately loses 1d10 experience points.

+
+
+ +
+
Pacify
+
Range: 15m
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

This causes up to 2–12 beings to cease hostilities against the caster (match caster’s magical attack vs targets’ magical defence). They will still be able to attack the caster’s allies, but can take no action which might harm him. Pacify is not an Enthrall spell and affected characters do not become friendly to the caster; they merely acquire a mental block that prevents them from attacking him. If the Warlock attacks a character they has Pacified, that character snaps out of the spell immediately.

+
+
+ Pacify Spell Number of Targets Roll: + Pacify Spell Attack Roll: (roll once against each target) +
+
+ +
+
Runic Weapon
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

A magical weapon appears in the caster’s hand or in the hand of a specified character within 12m. This weapon is the colour of blood and shimmers with a strange golden light. It must belong to one of the caster’s chosen Weapon Groups (see p. 38), so a Warlock who specialized in the use of battleaxe and bow could not use the spell to create a magic sword. The Runic Weapon is +3 (see p. 137) and unlike a Vorpal Blade it can be put down or freely handed to another character.

+
+
+ Activate Runic Weapon Spell: Please manually add your +3 weapon to your weapon list, this sheet is unable to do so for you. +
+
+ +
+
Spell Screen
+
Duration: 1d20 Spell Expiry Roll applies
+
+ Description

Other than its shorter duration, this is the same as the 7th-level Sorcery spell of the same name. A Spell Screen protects its caster from direct-attack spells by reducing any spell cast at him by 5 Magic Points. It does not affect spells cast by the Warlock themself. A spell which gets through the Screen with reduced strength may still affect the Warlock, but its effective magical attack against him is reduced by the difference between the spell’s level and the number of Magic Points remaining in it.

+
+
+ +
+
The Trickster’s Hand
+
Range: touch
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

With this spell, the Warlock surrounds themself or one companion with a magical defence against missiles such as arrows or thrown rocks. Enchanted missiles that are shot at him simply drop out of the air at a distance of 3m. Non-magical missiles are more spectacularly affected: when such a missile gets to within 3m of the protected character, it stops in mid-air as though seized by an invisible hand. Suddenly, it reverses and flies back towards the person who shot it. The attacker is thus hit unerringly by their own missile, which penetrates armour in the normal way (Armour Bypass Roll as usual), although it inflicts 1 less Health Point of damage than usual. The spell defends only against missiles targeted at the protected character. An arrow or other projectile shot past him at another character will be unimpeded even if it passes closer than 3m. Any missile weighing more than 20kg (for instance, the shot of a trebuchet or siege catapult) will pass through the spell-barrier without being stopped.

+
+
+ +
+
Jupro’s Legion
+
Range: 20m radius around caster
+
Duration: Spell Expiry Roll
+
Origin: Selentine priests of Mars
+
Rarity: Uncommon in Selentine empire, rare elsewhere
+
Replaces: Nemesis for Selentine Warlocks
+
+ Description

With a sonorous chant, the Warlock empowers their allies with the strength of the ancient Selentine heroes. Any ally of the Warlock standing within 20m of him when they begins the chant gains a +2 to their Attack and Defence. This spell turns average troops into hardened warriors, and veteran fighters into legends. The chant that accompanies this spell is often taken up by surrounding units, giving them a feeling of invincibility and incidentally making it difficult to spot the unit that has been bolstered. Each character affected by the spell must continue to chant for the duration or the spell will cease to function on them. The Warlock is not affected by the spell and need not continue the chant.

+
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Eight +
+
Demon Path
+
Duration: lasts two minutes
+
+ Description

This enables the Warlock literally to walk on air. The effect is accompanied by faint, glowing red ‘stepping stones’ that appear under the Warlock’s foot with each step they takes and then fade as they passes on to the next. They can move safely at normal walking speed, but if they tries to run or fight on the Demon Path they must roll under their Reflexes on 1d20 or fall to the ground below.

+
+
+ +
+
Energy Bolt
+
Range: 15m
+
+ Description

A thunderous blast of scarlet energy rips through the air to strike 1–3 beings within 15m (spell’s speed of 17 vs targets’ evasion). If not dodged, the Energy Bolt inflicts 5d10 Health Points. This damage roll is reduced by the target’s Armour Factor if any—a Basilisk (AF 2) would take only 5d10 –2 HP, etc.

+
+
+ Energy Bolt Spell Number of Targets: + Energy Bolt Spell Attack Roll: +
+
+ +
+
Gauntlet
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

When this spell is cast, a disembodied gauntlet of glittering gold mail appears in the air within 6m of the Warlock. Gliding through the air at a speed of 24m per Combat Round, it will strike at the Warlock’s foes or perform other actions for him such as opening chests, fetching items, etc. It can be given a weapon (including a Runic Weapon) or can attack with its metal talons (d10, 4). It has attack 20, defence 18, Armour Factor 4, 12 Health Points, evasion 8. It is not affected by direct-attack magic. If its Health Points score is reduced to zero it falls from the air and vanishes in a blaze of red flames.

+
+
+
+ Gauntlet +
    +
  • Attack: 20
  • +
  • Weapon: Metal Talons (d10, 4 points), or other weapon equipped
  • +
  • Defence: 18
  • +
  • Armour Factor: 4
  • +
  • Evasion: 8
  • +
  • Health Points: 12
  • +
  • Movement: 24m (25m)
  • +
+
+
+
+ +
+
Killing Frenzy
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

While under the effect of this powerful combat spell the Warlock is able to make two attacks every Combat Round. The first must be taken at the point in the round when they would normally get their action (see p. 70) and the second at the very end of the round. The Killing Frenzy allows only multiple weapon attacks. If the Warlock does something else such as casting a spell or moving instead of attacking with a weapon they does not get a second action that round. Furthermore, only attacks with a weapon in which the Warlock specializes (i.e. which belongs to one of their chosen Weapon Groups) are affected.

+
+
+ +
+
Reincarnate
+
Range: touch
+
Duration: lasts until dispelled
+
+ Description

With this spell, any character who has been slain during the previous seven days can be brought back to life in the body of another. The target of the spell (whose body forms the ‘host’ for the Reincarnated soul) must be quiescent—unconscious or drugged—for the spell to work, and the caster must still match their magical attack against the target’s magical defence. If the spell works, the target’s body becomes possessed by the mind and soul of the slain character. Looks, Strength and Reflexes remain those of the host but in all other respects (skills, personality, memories, etc.) the Reincarnated character is dominant. Unlike an Amulet of Soul Storing (p. 143), this spell does not displace the original persona, which remains dormant within the body. In times of psychic stress (whenever the Reincarnated character has a direct-attack spell cast at him) the dormant ‘host’ persona may try to reassert possession of the body and suppress the ‘intruder’ persona. The Reincarnated character rolls 3d6, adds their rank, and subtracts the rank of the ‘host’; they must roll the final total or less on 2d10 in order to retain dominance. If they fails the roll, the ‘host’ persona regains mastery of their own body but the positions are merely reversed, the Reincarnated soul is not cast out but remains dormant within the body until banished by Dispel Magic or Terminate Enchantment. The advantage of the Reincarnate spell is that it may be used to bring a character back from the dead even if their original body is lost or destroyed. The disadvantages are twofold—first as explained above, and second that there is a small chance (5%) that the soul the caster places in the host body will not be the soul they intended. Reaching into the spirit world is like standing at the mouth of a vast dark cave and yelling for a friend lost within: someone—or something—else may come in answer to your call.

+
+
+ +
+
Rain of Death
+
Range: 20m radius within bow range
+
Duration: Instant
+
Origin: Unknown
+
Rarity: Uncommon among Nomad Khanates, rare elsewhere
+
+ Description

o cast this spell, the Warlock must have a loaded bow or crossbow in their hands. The Warlock fires a single shot as they casts the spell; no attack roll is necessary as this is just part of the ritual. The missile splits into dozens of duplicates of itself in mid-air, filling a 20m radius at the point the shot would strike (determined by the caster, no attack roll required) with arrows/bolts. The spell's range is determined by the weapon used. Everyone in the area of effect must make an Evasion check against Speed 14 or be struck by 1d4 arrows. Damage from the spectral arrows is (1d6, 4). This spell is used by Khanate Warlocks in the employ of their lords and is commonly used during the hit-and-run charges the nomads are famous for.

+
+
+ Rain of Death Spell Attack Roll: (roll for each target in the 20m radius area) + Rain of Death Spell Damage Roll: (roll for each target hit successfully) +
+ +
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+ +
+ Warlock Spells of Level Nine +
+
Flying Steed
+
Duration: lasts three hours maximum (see below)
+
+ Description

This spell brings a flying Hippogriff to act as the Warlock’s steed for up to three hours. The spell can be cast only during the hours of night and terminates at sunrise if it has not expired before then. The Hippogriff has attack 20, defence 6, magical defence 10, and evasion 6. In combat, it will bite (d8 +2, 5) or claw (d12, 6). It has 20-30 Health Points (roll 2d6 +18) and is 8th rank-equivalent.

+
+
+
+ Hippogriff Stats +
    +
  • Attack: 20 +
  • +
  • Defence: 6
  • +
  • Magical Defence: 10
  • +
  • Evasion: 6
  • +
  • Health Points: 2d6+18
  • +
  • Rank: 8
  • +
  • AF: 3 (0 vs magic weapons)
  • +
  • Movement: 15m (30m) flying—90m
  • +
  • Stealth: 10
  • +
  • Perception: 11
  • +
  • Notes: In horse form, stats as per Warhorse; can change between forms at will at night.
  • +
+
+ +
+ Warhorse Stats +
    +
  • Attack: 17 +
  • +
  • Defence: 4
  • +
  • Magical Defence: 4
  • +
  • Evasion: 4
  • +
  • Health Points: 1d6+16
  • +
  • Rank: 5
  • +
  • AF: 0 (3 wearing barding)
  • +
  • Movement: 15m (30m)
  • +
  • Stealth: 10
  • +
  • Perception: 6
  • +
+
+
+
+ +
+
Invulnerability
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

The Warlock encloses themself and one companion inside an invisible barrier that is impervious to all spells, ring-effects, creatures, and all weapons. Attacks such as hypnosis or Fright Attacks can affect those protected by this spell. The Warlock can move around slowly (5m/round).

+
+
+ +
+
Simulacrum
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

The Warlock can create their own double. The Simulacrum has all of the original’s normal stats and the current Magic Points score of the Warlock. The Warlock can see through their double’s eyes, and they obey their telepathic commands. There is a chance that if one takes a wound, the other may suffer the same effect.

+
+
+ +
+
Song of Battle
+
Duration: d20 Spell Expiry Roll applies
+
+ Description

The Song of Battle transforms the Warlock into a ferocious berserker. They becomes immune to direct-attack magic and gains +8 attack and +4 defence. Intelligent creatures up to 2nd rank and animals up to 4th rank-equivalent have a 30% chance of fleeing in panic if they attacks.

+
+
+ Activate Song of Battle Spell: + + Song of Battle Fear Effect Roll: +
+
+ +
+
Teleport
+
Range: 100m
+
+ Description

This spell enables the Warlock to transport themself instantaneously to somewhere within 100m. They can only teleport to a place which they can either see when they casts the spell or where they has been before.

+
+
+ +
+
Fog of War
+
Range: Self
+
Duration: Spell Expiry Roll
+
Origin: Ereworn
+
Rarity: Uncommon in Ellesland, rare elsewhere
+
+ Description

Ereworn is famous for its dark and deadly fogs. Peasant and noble alike fear the mists, and with good reason. This spell surrounds the Warlock in a magical mist that radiates 5m out in all directions and moves with the Warlock. The Warlock can be dimly seen by anyone outside the fog, resulting in a -2 Attack penalty to ranged attacks. The Warlock can make a Magical Attack against anyone entering the mist. If the attack fails, the target ignores the mist. If the attack is successful, the fog thickens about them, and the target is lost in the mist. Those lost in the mist must roll 1d8 each round and consult the following table: 1: Exit the fog. The target can re-enter the mist if they chooses and suffer a new magical attack.2-7: Wanders lost in the mist, unable to see.8: Encounter the Warlock. Once this is rolled, the target is no longer lost and can choose to fight or flee from the Warlock. Fleeing the Warlock provokes another magical attack as the target re-enters the mist. The fog warps space, and in theory, any number of people could become lost in it. If the Warlock wishes, they may choose to encounter a particular person instead of rolling randomly.

+
+
+ Fog of War Spell Attack Roll: (roll for each target in the area of efffect, or entering the fog) + Fog of War Spell Effect Roll: +
+
+ +
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+ + + + +
+
+ Earth Spells +
+ Level 1 +
+
Abundance
+
Duration: Spell Expiry Roll applies
+
+ Description

The Elementalist must find a soft patch of earth into which to thrust their staff. They may then cast the spell onto the staff; any fruit, of the Elementalist’s choice, will emerge sprouting from the side of the haft. This will occur at the rate of one fruit per Round until the Spell Expiry Roll takes place. A whole feast of fruit may be provided in this way, given lucky rolls!

+
+ +
+ Darkness:

If this spell is cast by a Darkness Elementalist, the fruit produced contains a medium poison, although superficially it is even more appetizing than the fruit produced above.

+
+
+
+
+ Level 2 +
+
Spider Magic
+
Range: 10m
+
+ Description

This is essentially a concealing spell. The sorcerer may cast the spell on a well-used path, and immediately the undergrowth will spring up making it look disused; or they may cast the spell over an archway, and spiderwebs will appear, making it seem as if no one has passed in this direction for a long time. It will only affect an area in a 10m radius of the caster.

+
+ +
+ Darkness:

If this spell is cast by a Darkness Elementalist, the plant growth/spider webbing will not cease within a 10m radius but will continue to expand at a rate of 1m per Round until a Spell Expiry Roll takes effect. The plant growth is acidic and, if touched, will cause the loss of 1 Health Point or one point of permanent damage to a character’s Armour Factor if they is wearing armour. The spider’s web is similarly acidic.

+
+
+ +
+
Feet (Roots) of the Earth
+
Range: Self
+
Duration: Spell expiry applies
+
Origin: Thuland
+
Rarity: Uncommon in Thuland, rare elsewhere
+
+ Description:

This spell originates from the hidden villages in the north-eastern Pagan Mountains. These legendary villages were inaccessible except by their Elementalist protectors, but they syill exist tucked away to this day, unaware of the passing of years or the deaths of their ancient religions. Darkness has overtaken some of these villages, and terrible things happen to outsiders who find them.

+
+ +
+ Darkness:

The darkness version of this spell kills all plant life within 3m of the caster… this effect moves with the Elementalist.

+
+
+
+
+ Level 3 +
+
Forest Murmurs
+
Duration: 10 minutes
+
+ Description

This spell allows the caster to communicate with wayside plants. The plants’ memory only stretches back for twenty-four hours, and they have no sight so cannot describe the appearance of people or things that have passed their way. However, they will be able to report the number of people and the time they passed (whether daylight or at night), report snatches of their conversation, etc. They can also detect the aura of magic. Unfortunately, this method of communicating with inanimate bodies is not totally foolproof, and the GM should roll for a 10% chance of the information being a false rumour.

+
+
+ Forest Murmers Spell Effect Roll: +
+ +
+ Darkness:

Any Darkness Elementalist, fearing that they is being followed, may cast the spell on a large stretch of path where they thinks their pursuers or enemies may stop. If they attempt to cast the normal Forest Murmurs spell, the rumours that the pursuers receive will always be false ones.

+
+
+
+
+ Level 4 +
+
Create Bog
+
Range: 10m
+
Duration: Spell Expiry Roll applies
+
+ Description

This is an aimed spell, and the caster must pit the spell’s speed of 12 against their opponent’s evasion. If the opponent fails to dodge, they will find that the ground at their feet has turned to a thick, viscous sludge which will temporarily immobilize him. Characters wishing to escape embogment should make a d20 roll under their Strength for each Round they are trapped. If they make the throw, the GM must assume they have managed to pull themselves free of the mire.

+
+
+ Create Bog Spell Attack Roll: + Create Bog escape roll: +
+ +
+ Darkness:

The bog created is a bottomless one, and a character thus captured will sink without trace unless they pulls themself free or is otherwise saved. Both categories are subject to the normal Spell Expiry Rolls.

+
+
+ +
+
Skadi’s Path
+
Range: Self (30m)
+
Duration: Instant
+
Origin: Mercanian Coast
+
Rarity: Uncommon on the Mercanian Coast, rare elsewhere
+
+ Description:

The Elementalist must cast this spell while standing on stone or earth. Casting the spell while in a boat or on the first floor of a dwelling causes it to fail. On casting this spell the Elementalist is engulfed by the earth and stone at their feet, sinking into the ground. The Elementalist is transported to a point of the caster’s choosing within 30m of their current location as long as it is connected to the ground. Once at the chosen destination the earth heaves and spits out the Elementalist.

+
+ +
+ Darkness:

The darkness version of this spell causes stone to erupt from the ground in a 3 meter radius from the point the Elementalist leaves from. The attack has a speed of 12 and inflicts 2d6 points of damage reduced by the target’s armour factor.

+ +
+
+
+
+ Level 5 +
+
Roots
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
+ Description

The sorcerer casts a directional spell that causes any roots around the vicinity of their opponent’s feet to spring from the ground and grasp at their ankles. The spell will affect any opponent within a 2m radius of where it lands. The number of roots appearing will vary depending on terrain:

+
    +
  • Forest: 10 roots
  • +
  • Open ground, temperate climate: 6 roots
  • +
  • Open ground, cold climate: 4 roots
  • +
  • Open ground, dry climate: 2 roots
  • +
  • Desert; indoors; stone flooring: 0
  • +
+

Each root has to be evaded, and each has a speed of 16. Characters are immobilized when held by a root. If a character is held by four roots, assume that all their limbs have been pinned and that they is borne to the ground, unable to move until the Spell Expiry Roll takes place. A character who still has one hand free can attempt to hack themself clear by striking out at each root around him. The roots have 4 Health Points each.

+
+
+ Roots Spell Attack Roll: (roll once per root summoned) +
+ +
+ Darkness:

The roots called up not only seize limbs but also strangle and crush: assume damage (1d6, 4) for each root in contact with the victim.

+ Roots Spell Darkness Damage Roll: (roll once for each root attached) +
+
+ +
+
Earth Mother’s Womb
+
Range: Touch (voluntary targets only)
+
Duration: 8 hours
+
Origin: Thuland and Mercanian Coast
+
Rarity: Uncommon in Thuland and on the Mercanian Coast, rare elsewhere
+
+ Description:

With a quick invocation to the Fay of the earth, the Elementalist or their chosen target sinks into the earth. The target stays beneath ground in a deep healing trance, protected from the outside world by 3m of earth and stone. Eight hours later, the target emerges from the earth refreshed and healed of 10 Health Points of damage. An Elementalist entombed in this manner regains all magic points from their Earth category due to their deep communion with the earth. The spell must be cast in an area that has at least 3m depth of earth or stone.

+
+ +
+ Darkness:

The darkness version of this spell is sometimes called Womb of Shadows and returns magic points to the Elementalist’s darkness category rather than the Earth category.

+
+
+
+
+ Level 6 +
+
Rock Wall
+
Range: 10m
+
Duration: Spell Expiry Roll applies
+
+ Description

An Elementalist may cast this spell on any freestanding rock and make it grow to ten times its normal size, on the condition that the sorcerer is capable of physically lifting the original rock by themself. As a rough guide, only rocks half the size of the average human body can be lifted in this way. These rocks can be used to block up doorways, topple down on enemies, etc. The rocks will keep their blown-up shape until a Spell Expiry Roll takes place.

+
+ +
+ Darkness:

The same as above, but no Spell Expiry Roll takes place and the transformation is permanent. A Darkness Elementalist could entomb someone behind one of these large rocks forever.

+
+
+
+
+ Level 7 +
+
Fissure
+
Range: 1m
+
+ Description

This spell causes a permanent 3m-wide fissure to appear in any surface in front of the caster. The fissure will extend 5m to either side of the caster and will be 5m in depth. Anyone standing in the affected area must evade the speed of the fissure (18) or fall into it (1d6 damage). Anyone trying to jump the fissure will find that they have to roll under their Reflexes on a d20 to succeed. A fissure will appear in any terrain, on the surface or underground.

+
+
+ Fissure Spell Attack Roll: +
+ +
+ Darkness:

The pit is filled with churning teeth of rock that will prove to be instantaneously fatal to anyone falling into it. A Spell Expiry Roll applies to these ‘teeth’, although in both cases, the fissure will remain a permanent feature.

+
+
+ +
+
Master of Earth and Stone
+
Range: 20m
+
Duration: Spell expiry applies (effects are permanent)
+
Origin: Thuland and Glissom
+
Rarity: Common in Thuland and Glissom, rare elsewhere
+
+ Description

This spell enables the Elementalist to sculpt up to 1 cubic meter of earth or stone per round. This can be used to dig trenches, open holes in stone walls, undermine foundations, create tunnels, or even plough fields. Stone liquefies, reshapes, and re-solidifies under the effects of this spell. Legend tells that the ancient dark fortress of Aegis Fell, in northern Glissom, was created by some forgotten druid using this spell. Certainly, the ruin seems to have been carved whole from a rocky tor overlooking the Hadran Sea.

+
+ +
+ Darkness:

Normal animals and insects will not approach earth or stone worked by this spell.

+
+
+
+
+ Level 8 +
+
Give Up the Dead
+
Range: 10m
+
+ Description:

The caster calls up the buried remains of all those interred within a 10m radius. This applies to human corpses as well as animal ones. It does not apply to any body that has not been buried at least one lunara. These bodies may act as bodyguards or perform simple tasks for him, but they are subject collectively to a Spell Expiry Roll, so their usefulness may be of limited duration. The state of the temporarily resurrected bodies will vary somewhat, but assume that all humans disinterred have the following basic characteristics:

+

For animal skeletons, assume they have half the Health Points, attack, defence, and magical defence that a living member of their species would have.

+ Chances of raising the dead: +
    +
  • Graveyard or other burial ground: 95% of producing 1-12 skeletons
  • +
  • Ancient ruins, catacombs etc.: A 60% of producing 1-6 skeletons
  • +
  • Open ground: 10% chance of producing 1-2 skeletons
  • +
+
+
+ +
+ Skeleton +
    +
  • Attack: 11
  • +
  • Weapon: Skeletons will fight unarmed, unless they can acquire a weapon.
  • +
  • Defence: 5
  • +
  • Evasion: 3
  • +
  • Magical Defence: 3
  • +
  • Health Points: 1d6+1
  • +
+
+
+ +
+ Darkness:

The necromancy is permanent, and the skeletons of man and beast will follow the spell caster until they are destroyed.

+
+
+
+
+ Level 9 +
+
Tremor
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell causes a violent tremor of the earth’s surface which increases in intensity as time elapses. The spell affects an area 10m across and anyone or anything in this radius will find that they are taking damage. The spell is subject to a Spell Expiry Roll.

+
+
+

Consult the table below for damage:

+
    +
  • Round 1: A slight shaking in the earth’s surface is noticeable beneath the soles of the feet. The surface of liquids held in cups, etc. begins to ripple, birds leave their nests and take flight.
  • +
  • Round 2: The earth is now vibrating so fast that the surface ripples. If it is covered by flagstones or other similar surface these will begin to gently undulate up and down. All animals in the area will cry out in fear. Fixtures on the wall will fall from their hangings and cups will overturn, spilling their contents.
  • +
  • Round 3: The first round in which anyone still in the vicinity of the tremor will take damage. The shaking is now so intense it jars the bones, cracks paving stones and exposes the roots of trees. Damage 1d4 (armour doesn’t protect).
  • +
  • Round 4: Human jaw bones are now chattering together like castanets, the walls of buildings are shaking, and cracks are appearing in them. Paving stones appear like waves rolling on a sea. It is nearly impossible to keep one’s footing (d20 roll under Reflexes). Damage 2d4 (armour doesn’t protect).
  • +
  • Round 5: No one can stand up and hence escape the zone of the tremor. Destruction is assured for them and they will take a further 1d4 damage to the 2d4 damage per round that they are already taking. If in an enclosed space, ceiling masonry will now begin to fall, posing an additional threat. Fissures will appear in the earth, swallowing humans, trees, articles of domestic furniture, or whatever else is appropriate to the place.
  • +
  • Round 6: Total destruction: normal wooden buildings (but not citadels or castles) will collapse in on themselves, the earth will split open revealing a great chasm into which all things will fall and where nothing can survive.
  • +
+
+ +
+ Darkness:

The effect of the spell is not subject to an Expiry Roll: the destruction of any wall or building in the area where this spell is cast is assured.

+
+
+
+
+ Level 10 +
+
Summon the Man of Stone
+
Range: Self
+
Duration: Spell expiry applies
+
Origin: Thuland
+
Rarity: Uncommon in Thuland, rare elsewhere
+
+ Description

If the Elementalist finds themself in a rocky area where there is plenty of free-standing stone, they may summon up a titanic figure made of rock who will serve him until the Spell Expiry Roll takes place. The Stone Man will be able to break through walls and always travels in a directly straight line once freed of its summoner’s control. It will disappear after exactly one hour.

+
+
+
+ Stone Man +
    +
  • Attack: 30
  • +
  • Weapon: Fist (d8 +2)
  • +
  • Defence: 24
  • +
  • Evasion: 8
  • +
  • Magical Defence: 17
  • +
  • Health Points: 24
  • +
+
+
+ +
+ Darkness:

The creature summoned is different to that above. It battens on to the flesh of living men, delighting in grinding their bones between its stony jaws. Such a Stone Man released on a settlement could devastate its population within minutes, so it is perhaps fortunate that, like its relative above, this juggernaut only remains on this plane for one hour’s duration. Like the species above, the titan moves in straight lines and can burrow through cliffs and subterranean tunnels.

+
+
+ +
+
Skadi’s Fortress
+
Range: Self
+
Duration: 1 day
+
Origin: Thuland
+
Rarity: Uncommon in Thuland, rare in Mercanian Coast and Ellesland, unknown elsewhere
+
+ Description

This spell gathers the earth and rock from around the caster and uses it to create a mighty fortress of stone and clay. The fortress consists of a three-story tower, with stone “cheval de frise” surrounding it in a 20m radius. The caster and their allies inside the fortress can rain death down from the tower battlements. The tower has 2m thick walls without any doors or windows. The Elementalist can choose to open a portal that allows allies to enter or exit the tower, although they must find their own way through the cheval de frise. This spell cannot be cast in areas that lack earth and stone. It is believed that the secret of Skadi’s Fortress was whispered to mortal man by the Goddess herself.

+
+ +
+ Darkness:

The fortress exudes a powerful sense of dread, and those below 2nd Rank cannot approach it or attempt to do it harm.

+
+
+
+
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+
+ Air Spells +
+ Level 1 +
+
Cutting Power of the Mind
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster invokes the power of air to enhance his thoughts, cutting through all distractions like a sharp knife. His Intelligence temporarily increases to 18, or, if already 18, to 19. In addition to the usual benefits of his newly increased Intelligence, he gains a +2 bonus on all attack rolls when wielding any ranged weapon; he is capable of influencing its movement even when it is in flight, using the power of his mind alone.

+
+
+ Activate Cutting Power of the Mind Spell: + +
+ +
+ Darkness:

Darkness: As above, except that the ranged weapon gains a +1 bonus to Damage also. +

+
+ +
+
Leaf on the Wind
+
Range: Self
+
Duration: Spell expiry applies
+
Origin: Mercanian Coast
+
Rarity: Common on the Mercanian Coast, uncommon elsewhere
+
+ Description

A hundred years ago, the cliffs and fjords of the Mercanian Coast were home to a number of brutal deaths, as followers of the True Faith took to hurling “devil worshippers” from the cliff tops. This spell saved the lives of a number of Völva Elementalists during those dark days. An Elementalist under the effects of this spell is buoyed up by the spirits of the air while falling and takes no damage from any fall… unless of course the spell ends while he is still in the air. Falling while under the effects of this spell is at a rate of 10m per round.

+
+ +
+ Darkness:

The darkness version of this spell can be cast on another person by touch

+
+
+
+
+ Level 2 +
+
Stargaze
+
Duration: 1 day
+
+ Description

The element of Wind and Air leads one’s thoughts naturally to the sky. Stargaze is a sorcerous ability to reduce the effect of hardship on the caster’s mind, making him able to bear hunger for a week without visibly weakening, and enabling him to stand in combat although his Health Point total may have gone below 0. If the caster should continue in combat until he is at –3 he will collapse dead. Stargaze will also allow the caster to hold his breath underwater for twice the usual time, endure twice the strength of heat as any other man, twice the cold etc.

+
+ +
+ Darkness:

The caster may negate the effects of adversity altogether. Wounds inflicted on him will cause no reduction in his Health Points, nor will fire and lack of air. Food will act like a poison on the body. At the same time, the caster will not be able to affect anyone or anything else physically; thus, he will not be able to enter into combat or even open a door although he will be able to pass through a Wall of Fire totally unharmed. This condition will last for exactly one day. At the end of that day the caster must make a roll against a magical attack of 1d6 +10 or he will find that his body begins to evaporate into a vapour until all that is left of him is a thin wraith of ethereal smoke. + Roll at the end of the day:

+ Stargaze Darkness Spell Attack Roll: +
+
+
+
+ Level 3 +
+
False Rumours
+
+ Description

An aural version of the various Illusion spells used by other magicians, in which the caster subdues the spirits of the air and makes them set up aural illusions to mislead the enemy. Any distortion may be added to the sound (scraps of a conversation, the clank of armour, the sound of falling bodies, marching armies, song, etc.) to make these noises in some way threatening to the person listening to them.

+
+ +
+ Darkness:

The sound created is always that of a demoniacal moan that will turn the hearer mad (see page 124) if they fail to resist a Fright Attack of 14 (see page 122).

+ Fright Attack Roll: +
+
+
+
+ Level 4 +
+
Windwall
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster may create a wall of wind around his body, or use the wall to block a corridor immediately in front or behind him. The wall of wind thus created is 1m thick and stretches for more than 10m to either side of the caster of the spell. Stepping into the wall is rather like stepping into the centre of a typhoon: on the first round anyone doing so will take 1d8 points of damage (armour does not protect) and will continue to do so for as long as they remain in the wall. The only way to break through the wall is to roll under one’s Strength on 2d20. The wall is subject to a normal Spell Expiry Roll.

+
+
+ Windwall Spell Damage Roll: + Windwall Attempt to Break Through Roll: +
+ +
+ Darkness:

The wall will advance forward at the rate of 1m per round and therefore can be used offensively against people trapped at the ends of corridors, etc.

+
+
+ +
+
Chosen of Tor
+
Range: Self
+
Duration: Spell Expiry Roll
+
Origin: Mercanian Coast
+
Rarity: Uncommon on the Mercanian Coast, rare elsewhere
+
Replaces: Windwall for Mercanian Elementalists
+
+ Description

The Elementalist calls upon the spirits of the air to protect him. Anyone attacking the Elementalist takes a -4 penalty to his Attack score, as a small hurricane blows up around him and the spirits howl their anger in his ears. The Völva of the Mercanian coast have made good use of this spell in the last few centuries. What was once used as a potent raiding tool is now, more often than not, used to protect Mercanian trading vessels from pirate attack.

+
+ +
+ Darkness:

The spirits of the air summoned by Darkness Elementalists are vengeful, and whisper dark secrets in the ears of those attacking him. The Darkness Elementalist makes a Magical Attack, and if he succeeds then the victim is inflicted with insanity. Roll on the Madness Table (see Dragon Warriors, p. 124)

+ +
+
+
+
+ Level 5 +
+
Summon the Host of the Air
+
Range: 1 mile
+
+ Description

The caster attracts to himself all those creatures currently in flight through the medium of air in a one-mile radius. These he may instruct to do as he wishes, getting them to attack his enemies or instructing them to spy out the land, etc. The caster will be able to communicate in simple terms with the summoned creatures. Some terrains may not, of course, be suitable for various types of creature. There may not be even a single insect in an arctic waste or an arid desert, but assume the following in a temperate climate:

+

1d6 Result:

+
    +
  • 1: A few miscellaneous insects.
  • +
  • 2: Insects as above and one or two birds.
  • +
  • 3: A swarm of insects and one or two birds.
  • +
  • 4: A cloud of stinging insects.
  • +
  • 5: A bird of prey that could attack an opponent.
  • +
  • 6: A flight of birds of prey, capable of carrying the caster in flight.
  • +
+
+
+ Summon the Host of the Air Effect Roll: +
+ +
+ Darkness:

The caster always manages to summon a swarm of insects and a flight of birds of prey to himself (as in 6 above).

+
+
+
+
+ Level 6 +
+
Intangibility
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell allows the caster to pass through the thickest of walls as if they were made of air: no barrier will be able to stop him apart from enchanted metal. (which will cause 1d6 points of damage to his incorporeal body). The spell is risky, particularly if the caster wishes to travel some distance underground or through a wall. The spell is subject to a normal Expiry Roll and if it wears off while the magician is travelling through something solid, he will be instantly crushed to a pulp. While intangible, the caster cannot cause any damage in combat etc.

+
+ +
+ Darkness:

Can be reversed to affect an opponent, rendering them ineffective in combat.

+ Intangibility Darkness Spell Attack Roll: +
+
+ +
+
Winds of Change
+
Range: 10m
+
Duration: Spell expiry roll
+
Origin: Desert of Songs
+
Rarity: Common in the Desert of Songs, rare elsewhere
+
+ Description

This spell targets one being and changes its thinking about a single topic named by the caster. The Elementalist whispers the new point of view and a gust of wind carries it to the target. A standard Magical Attack versus Magical Defence roll is made. Examples of new points of view include; “I am not a threat”, “I am too dangerous to attack”, and “the oasis should be shared”. When the spell expires, the target returns to his previous thinking, but still retains an understanding of the enforced point of view. This new understanding sometimes opens minds that would otherwise be closed to change.

+
+
+ Winds of Change Spell Attack Roll: +
+ +
+ Darkness:

The darkness version of this spell never leads to increased understanding. In addition, the spell can only inspire negative thoughts.

+
+
+
+
+ Level 7 +
+
Garrotte
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell (which must be dodged—speed 19) causes a mysterious constricting band to appear around the throat of an opponent, exerting enough pressure to throttle them if the caster so wishes, although the pressure can be relaxed or increased as he desires. The only way to release the grip of the garrotte is for the victim to roll under his Strength on 3d20, in which case he has broken the cord. Otherwise assume 3 Health Points of damage taken by the victim each round until he is dead.

+
+
+ Garotte Spell Attack Roll: + Garotte Victim Escape Roll: +
+ +
+ Darkness:

If the victim does not evade the spell, the air implodes around his head causing 1d20 points of damage automatically and leaving the victim deaf.

+ Garotte Darkness Spell Effect: +
+
+
+
+ Level 8 +
+
Flight
+
Duration: 1 hour
+
+ Description

The caster may use this on himself and fly through the air for one hour. When in flight, assume that the caster can move through the air at twice normal movement rate. He may carry anything up to his normal encumbrance, but this will usually preclude carrying other people unless he is either very strong or has shed all his equipment.

+
+ +
+ Darkness:

Darkness Elementalists may cast Flight on to other people (their magical attack vs magical defence) but can only control that person’s flight whilst they are still in sight. The controlled persons cannot in any way control their own flight. Indeed, the Darkness Elementalist may find putting flight on to one of his enemies and then flying them into the ground from a great height a convenient way of disposing of them.

+ Flight Spell Darkness Attack Roll: +
+
+ +
+
(Summon) Rukh
+
Range: 100m
+
Duration: Spell expiry applies
+
Origin: Batubatan
+
Rarity: Uncommon in the Desert of Songs, Khitai, and Batubatan, rare elsewhere
+
+ Description

This spell summons forth one of the legendary Rukhs, giant birds whose mastery of the skies is unrivalled. The great creature has a wingspan of over 50m and is capable of carrying away an adult elephant in its massive talons. The Rukh can be ordered to attack the Elementalist’s foes—typically by carrying them high in the air and dropping them—or to carry the Elementalist and his companions on its massive back. Anyone on the Rukh’s back when the spell expires will float to the ground supported by a gentle wind.

+
+
+
+ Rukh Stats: +
    +
  • Attack: 24
  • +
  • Talons (d10, 7)
  • +
  • Defence: 18
  • +
  • Magical Defence: 12
  • +
  • Evasion: 5
  • +
  • Armour Factor: 3
  • +
  • Stealth: 10
  • +
  • Perception: 16
  • +
  • Health Points: 30
  • +
+
+
+
+

This spell was created by an isolated community of Elementalists living on an island off the coast of Batubatan. The peaceful Elementalists were under constant attack from raiders, and so they sent a flight of Rukhs to carry off the pirates' ship. The vessel was found 50 miles inland, speared on a mountaintop.

+
+ +
+ Darkness:

The Rukh’s shadow causes a 1d6 Fright Attack (see Dragon Warriors, p. 122) on anyone it falls upon.

+ +
+
+
+
+ Level 9 +
+
Spin
+
+ Description

A character may cast this on an opponent (who has a chance to resist its effects). If they fail they will begin to rotate, slowly rising into the air. The rotation of their body will become quicker and quicker until they eventually fly apart limb from limb. If a Spell Expiry takes place they will immediately return to the earth, over which they will have been spinning at a height of 2m. Assume the character will take 1d2 damage per round of spinning (no armour protection).

+
+
+ Spin Spell Attack Roll: +
+ +
+ Darkness:

The effect is the same, apart from the fact that the victim will bore down into the ground causing 1d6 damage per round (no armour protection).

+ Spin Darkness Spell Attack Roll: +
+
+
+
+ Level 10 +
+
Banshee
+
+ Description

The Elementalist may summon a Banshee, an animate vortex of violent, shrieking wind. The Banshee will deafen anyone within a 10m radius apart from the spell-caster. The Elementalist may direct the Banshee to attack one opponent specified by himself. The Banshee will pursue this victim until it has achieved its goal, which is to implode upon its victim. This implosion causes immediate death on the victim’s part. Summoning a Banshee requires the expenditure of 5–50 (5d10) Experience Points on the part of the caster.

+
+
+
+ Banshee +
    +
  • Attack 17, Implosion (Death)
  • +
  • Movement: 25m
  • +
  • Defence 12
  • +
  • Evasion 8
  • +
  • Magical Defence 16
  • +
  • Health Points 18 (immune to nonmagical weapons)
  • +
+
+ Banshee Caster XP Loss: +
+ +
+ Darkness:

The Banshee thus summoned will not be satisfied by just one victim but will run amok, its shrieking increasing as it sucks in the screams of its victims. It will only dissipate once it has destroyed one hundred victims. A Banshee summoned by a Darkness Elementalist costs the caster 10–100 (10d10) Experience Points.

+ Banshee Darkness Caster XP Loss: +
+
+
+
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+
+ Water Spells +
+ Level 1 +
+
Rain
+
Range: Self
+
Duration: 5 minutes
+
+ Description

The caster causes a light rainfall in a small area of 5m radius, yielding two gallons of drinkable water if collected. The rain can also be used to extinguish the lights of foes.

+
+ +
+ Darkness:

The water is mildly acidic; treat as a mild poison if drunk or a weak acid if exposed to armour for a long time.

+
+
+ +
+
Marid’s Gift
+
Range: Touch
+
Duration: Instant
+
Origin: Marid giants
+
Rarity: Common in the Desert of Songs or Azure Coast; rare elsewhere
+
Replaces: Rain for the Water Elementalists of those regions
+
+ Description

This spell causes a body or container of water touched by the Elementalist to be purified and drinkable. It removes poisons, impurities, parasites, and the effects of stagnancy. When cast on salt water, the spell makes it drinkable, though it still retains a salty tang. The spell can affect a single pool or container no greater than 10m x 10m x 2m; this is usually enough to purify the water from an oasis. The water from wells or pools remains pure until it refills naturally. This spell was a gift from the Marid giants of the Azure Coast to the storm-wizards of the Desert of Songs. The Marid giants are a wise and peaceful race, who suffered greatly at the hands of Kappa invaders until the storm-wizards intervened on their side.

+
+ +
+ Darkness:

The darkness version of this spell reverses the effect above, polluting an oasis or water vessel. Use of this spell has in the past caused open warfare between the tribes of the Desert of Storms.

+
+
+
+ +
+ Level 2 +
+
Wave Mastery
+
Range: 10m
+
Duration: Spell expiry roll
+
+ Description

The Elementalist controls the movement and direction of waves within a 10m radius, propelling ships or reducing wave activity.

+
+ +
+ Darkness:

Propel other craft away and create a mini tidal wave of 6m height aimed at a target, damaging small boats (1d6 Ship Points loss).

+ Darkness Wave Mastery Darkness Spell Ship Damage Roll: +
+
+
+
+ Level 3 +
+
Icewall
+
Range: 2m
+
Duration: Spell expiry roll
+
+ Description

The caster may throw up a wall made of solid ice in front of him, around himself, or around an opponent as long as they are standing within the 2m radius of the spell’s effect. The ice wall is 1m thick and will extend 5m to either side of the caster. If the spell is used offensively the victim will be entrapped if he fails to evade the spell speed of 10. It will take one man-hour to break through the ice wall with a weapon although the ice will have completely melted within six hours in a temperate climate.

+
+
+ Iceewall Spell Attack Roll: +
+ +
+ Darkness:

The ice barrier does not melt and is more impervious to the blows of humanity. As a spell of entrapment it is more useful than the version above. It will take one day for the victim to break through the barrier (assuming he has a sword, axe or mace to use for this purpose) and the ice itself will not melt even in the brightest sunshine.

+
+
+
+
+ Level 4 +
+
Walk on Water
+
Range: Self
+
Duration: Spell expiry roll applies
+
+ Description

The Elementalist may cast this spell on himself to become able to walk on any watery surface as if it were solid ground. Unfortunately this spell is subject to an Expiry Roll, so many an Elementalist has been discomfited by suddenly disappearing beneath the surface on which he was treading in front of his friends. It is therefore perhaps advisable for use on short crossings only.

+
+ +
+ Darkness:

The Spell Expiry Roll does not apply to the Darkness version of the above spell: instead the caster may walk on the water for exactly one hour before the effects of the spell wear off.

+
+
+ +
+
Lyrr’s Cleansing
+
Range: Touch
+
Duration: Instant
+
Origin: Unknown
+
Rarity: Uncommon throughout Legend
+
Replaces: Waterwalk
+
+ Description

Running water is a powerful tool for removing enchantments. This spell works in much the same manner as the Sorcerer spell Dispel Magic, except that it affects a single target that the caster must immerse in running water for the magic to work.

+
+ +
+ Darkness:

The darkness version of this spell requires stagnant water to work.

+
+
+
+
+ Level 5 +
+
Ice Spear
+
Range: Normal javelin range
+
Duration: Instant
+
+ Description

A glittering shard of ice, the shape and length of a normal throwing spear, will appear in the Elementalist’s hand. No matter what the caster’s normal attack is, it will be 20 with this weapon, reflecting the magical homing qualities it is imbued with. The spear is effective over the normal ranges for a javelin (p. 69) and will do (d10, 8). It will instantly dissolve on impact with the target.

+
+
+ Ice Spear Ranged Attack Roll +
+ +
+ Darkness:

The same as above, except that if the ice spear penetrates armour then the victim is subjected to a direct attack spell (caster’s magical attack vs victim’s magical defence) of Paralysis (see p. 93).

+ Ice Spear Darkness Spell Effect Roll: +
+
+
+
+ Level 6 +
+
Breathe Under Water
+
Range: Self
+
Duration: 10 minutes
+
+ Description

The caster will find that without holding his breath he is able to stay underwater for ten minutes at a stretch. At the end of this period he will have to resurface or he will begin to drown.

+
+ +
+ Darkness:

The Elementalist may reverse the effect, so that their victim will not be able to breathe normal air for ten minutes. Unless tehy can get to water before they black out, they will suffocate on dry land. A successful magical attack vs magical defence roll is required for the spell to take effect.

+ +
+
+ +
+
Ship of Fays
+
Range: 10m
+
Duration: 1 hour
+
Origin: Coastal Ellesland and Mercania
+
Rarity: Uncommon in coastal Ellesland and the Mercanian Coast; Rare elsewhere
+
+ Description

This spell must be cast while the Elementalist stands waist-deep in a river or sea. The spell summons forth a longboat made of mist and water-weed, which slowly rises from the water. The craft carries up to 8 passengers to a destination specified by the Elementalist when casting the spell. The destination must be connected by water to the Elementalist's current location. If the destination is over 100 miles away, the Ship of Fays takes the passengers that far and disintegrates away into nothing but useless weeds. This can be quite dangerous on ocean crossings. The journey takes one hour, regardless of distance, and the passengers remember nothing of the journey—for them it is if it passed in the blink of an eye. Some believe that those touched by the Fay can remember the journey, though none have chosen to speak openly about the experience.

+
+ +
+ Darkness:

While passengers will not remember the journey, they will be touched by a nameless dread. The passengers will not sleep for the next two nights and suffer a -1 to all actions due to sleep deprivation.

+
+
+
+
+ Level 7 +
+
Blizzard
+
Range: 20m
+
+ Description

The Elementalist may call down a thick blanket of swirling ice particles 20m across. He may either use this to conceal himself and the people that he is with (there is a 5m-wide sphere of clear air at the centre of the area of effect), or he may use it offensively against opponents. Defensively, anyone entering the blizzard will have their movement rates halved and their visibility reduced to the level of extreme darkness. The caster, however, will be able to see anyone enter the blizzard from the protected central sphere at its heart.

+

Similarly, the Elementalist may make the blizzard descend on a party of his enemies as long as they are no more than 20m distant. Again, he will be able to see clearly, but they will not be able to unless they reach the heart of the storm at the centre of the blizzard.

+
+ +
+ Darkness:

The ice particles are razor-sharp. Anyone moving through the storm will find that the ice particles do 2 points of damage to naked flesh per round, or will strip away 1 Armour Factor point every round that armour is exposed to them.

+
+
+
+
+ Level 8 +
+
Freeze
+
Range: 60m
+
+ Description

This is an offensive spell which can be directed at any enemy within 60m. A jet of freezing water emerges from the caster’s hands with a speed of 16: if the victim does not evade the jet, he is immediately covered from head to toe in freezing ice and will be totally immobilized for ten rounds. Victims must also roll to survive the shock of the cold-water jet. The victim must roll under his current Health Points on d20 or be assumed to have died of shock.

+
+
+ Freeze Spell Attack Roll + Freeze Victim Resist Roll +
+ +
+ Darkness:

This is similar to the above, except that the speed of the spell is 20.

+ Freeze Darkness Spell Attack Roll + Freeze Darkness Victim Resist Roll +
+
+
+
+ Level 9 +
+
Lightning
+
+ Description

Although many would categorize lightning under the elements of Air or Fire, its province is properly that of Water, lightning being the harbinger of violent storms and deluges. During such a storm the Water Elementalist becomes extremely powerful, acting as a conduit for the supernatural forces of the sky and directing them on to the earth. Holding up a copper rod, which is part of the equipment of all such Elementalists, he will attract the lightning down on to himself, but will not take any damage. The copper rod will then become charged and the Elementalist will be able to do the following with it (three uses):

+
    +
  • 1. Fire lightning bolts at opponents: these bolts have speeds of 20 and cause 12 points of damage. Eve iif the victim survives this damage, he still has to roll under his remaining Health Points on a d20 or die from the electric shock.
  • +
  • 2. Animate a corpse: if the rod touches a new corpse (not dead longer than one month) it will become animated and function very much like a Zombie would for the period of a day (for Zombies, see p. 253).
  • +
  • 3. Create a force field: anyone entering within a radius of 20m of the caster will automatically receive a 3-point loss to their Health Points. They will continue to lose another 3 points per round that they remain in the area, or until the effect wears off. It will wear off when the magician shifts his ground.
  • +
+
+
+ Lightning Spell Attack Roll: + Lightning Victim Resist Electric Shock Roll: +
+ +
+ Darkness:

The caster has five uses of the above powers. Alternatively, he can use up the entire charge (all five uses) to animate a single corpse as a permanent Zombie, rather than the type that lasts a single day.

+
+
+ +
+
Manannán’s Due
+
Range: 200m
+
Duration: Instant
+
Origin: Mercanian Coast
+
Rarity: Uncommon in coastal Ellesland and Mercania; Rare elsewhere
+
+ Description

The Elementalist awakens an ancient god of the sea, offering 2d8 beings specified by the caster within range as tribute. The spell only affects beings on, in, or within sight of the ocean (such as on a ship or on a beach) and has no effect on beings of 2nd Rank or above. If the Elementalist succeeds on a Magical Attack, then the targets simply drop what they are doing, walk into the water and drown themselves. The target’s companions can attempt to save them by restraining them for 20 rounds, at which point the compulsion fades. A friendly Elementalist can use Wave Mastery to keep water out of the target’s lungs until the spell breaks.

+
+
+ Manannán’s Due Spell Number of Targets Roll: + Manannán’s Due Spell Attack Roll: +
+ +
+ Darkness:

Wave Mastery has no effect on the darkness empowered version of this spell.

+
+
+
+
+ Level 10 +
+
Summon Tidal Wave
+
+ Description

The caster can create a 10m-high wall of water from the surface of a lake or the sea and direct it towards any target he chooses. The tidal wave can wreak terrible devastation amongst shipping, swamping all but the largest cogs to the extent of 2d10 Ship Points damage. Coastal towns can be flooded—possibly with the loss of hundreds of lives. Ranked characters may survive inundation by rolling equal to or under their rank on 1d12, but even if this roll succeeds the character takes 1d6 Health Points damage. The wall of water can only penetrate about half a mile inland and is only 30m across. Each casting of the spell costs the Elementalist the permanent loss of 1d4 Health Points.

+
+
+ Summon Tidal Wave Ship Damage Roll: + Summon Tidal Wave Target Survival Roll: + Summon Tidal Wave Caster's Cost Effect Roll: +
+ +
+ Darkness:

The tidal wave will roll on over land, spurred by some occult power that only those masters of the Darkness element are familiar with. Its movement rate is 20mph (50m per combat round) and it will destroy everything in its path. The tsunami will dissipate according to the normal Spell Expiry Rolls.

+
+
+
+
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+
+ Fire Spells +
+ Level 1 +
+
Candle
+
Range: 10m
+
Duration: 1 hour
+
+ Description

The caster may create a magical candle that will glitter in the air in front of him and will not go out even when it is immersed in water. The candle and its illumination are not visible to anyone else but the caster. It has the range of light of a normal torch (10m) and will last for one hour.

+
+ +
+ Darkness:

The candle will create an area of darkness around the caster, and people standing outside the range of the candle will only be able to see indistinctly the form within it, no matter if there is strong daylight or other illumination (add 3 to evasion and defence).

+
+
+ +
+
Brigantia’s Heart
+
Range: Touch
+
Duration: One Night
+
Origin: Glissom
+
Rarity: Common in Glissom, uncommon in Ellesland, rare elsewhere
+
Replaces: Pyrotechnics for Druids from Glissom
+
+ Description

The Elementalist calls upon the old pacts imploring Brigantia, the Goddess of flame to bless a single fire (campfire or heath fire). The spell can only be cast at night and lasts until the first light of dawn. Anyone sleeping beside the fire for the night regains 2 health points in addition to any regained through normal rest. The fire must be kept fuelled, but may be put out in the normal manner.

+
+ +
+ Darkness:

The darkness version of this spell curses a single fire so that its smoke forms a malignant fume. Any person spending four hours next to the fire (outdoors or indoors) suffers the effects of a medium poison (see Dragon Warriors, p. 122).

+
+
+
+
+ Level 2 +
+
Pyrotechnics
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster may create any illusions involving light and fire he chooses. Thus, he may wish to create the impression of a torchlight procession, fire fairies that flit across the moonlit glades or ghostly shades lurking in graveyards. As with any illusion, there is a 5% chance of ‘disbelieving’ pyrotechnics. The Spell Expiry Roll applies.

+
+ +
+ Darkness:

The caster will be able to create monstrous illusions from the shadows or revenants. As above, there is a normal chance of disbelieving these.

+
+
+
+
+ Level 3 +
+
Fire Arrow
+
+ Description

The caster may create a fire arrow by placing this spell on an enchanted arrow. It will immediately flare up with occult flames, but these will in no way harm the caster as he notches the arrow on to his bow and shoots. The shot involving the fire arrow will always be as if shot with a bonus of +5 to attack, doing (d10 + 10) damage and, of course, setting anything inflammable on fire in the process.

+
+
+ Fire Arrow Ranged Attack Roll: (you must have an appropriate bow equipped for this to work) +
+ +
+ Darkness:

An arrow of darkness will be produced that will do the damage described above with the same attack bonus, etc.

+ Fire Arrow Darkness Ranged Attack Roll: (you must have an appropriate bow equipped for this to work) +
+
+ +
+
Ifrit’s Cloak
+
Range: 3m radius centred on caster
+
Duration: Spell expiry applies
+
Origin: Desert of Songs and Azure Coast
+
Rarity: Uncommon on the Desert of Songs and Azure Coast, rare elsewhere
+
Replaces: Fire Arrow for certain storm-wizards
+
+ Description

The spell wraps the caster in a mantle of smoke and embers that billow from his cloak, blinding those close to him. Enemies suffer a -3 to Attack and Defence while within 3m of the caster. As an action, the Elementalist can also choose to swirl the cloak about himself to release a shower of embers. These embers ignite any flammable substances within 2m of the caster. This spell is known to the storm-wizards of the Desert of Songs, where they call upon ancient elemental compacts to conjure this mantle.

+
+ +
+ Darkness:

The embers created by the darkness version of this spell have Speed 12 and burn anyone failing to dodge for 1d8 Health Points of damage, minus the target’s Armour Factor.

+ +
+
+
+
+ Level 4 +
+
Sheet of Flame
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster may produce a wall of fire, 1m across and 5m to either side of him. This may also be used to surround himself or an opponent. Anyone trying to cross this barrier will automatically take 8 points of damage. As a protection to the caster, this wall of fire is a mixed blessing. Although it can protect the caster, the flames also suck away his oxygen supply and, unless he disbands the spell within six rounds, this will be totally used up and he will pass out. If the spell is used in order to trap an opponent, they will have an opportunity to jump out of the mounting ring of fire that springs up around them. The speed of the fire is 14. Opponents thus trapped will also pass out within six rounds unless the wall is dispelled or it expires.

+
+
+ Sheet of Flame Spell Attack Roll: +
+ +
+ Darkness:

Darkness Elementalists can get the Sheet of Flame to move forward at the rate of 1m per Round.

+
+
+
+
+ Level 5 +
+
Protection from Fire
+
Duration: Spell Expiry Roll applies
+
+ Description

The caster becomes immune to all fire damage as long as he has already placed the spell upon himself before entering the combat or danger zone where he is likely to be harmed.

+
+ +
+ Darkness:

The Elementalist is protected from flame as above. In addition, any offensive spell involving the use of fire will rebound upon the spell caster with their own magical attack.

+
+
+ +
+
Fires of Purification
+
Range: Self
+
Duration: Instant
+
Origin: Kastrian Sorcerers of Khitai
+
Rarity: Common among the Kastrian Sorcerers; Rare elsewhere
+
+ Description

In far Khitai fire is seen as a means of purification. This spell engulfs the caster in flame for a few seconds, which can be quite terrifying for those not used to the sight. The caster is immediately cleansed of any disease, poison, or mental malady. The Kastrian Sorcerers of Khitai are famous for their devout beliefs in the elemental spirits, and they consider this spell to be a form of prayer.

+
+ +
+ Darkness:

This darkness version of this spell requires a second target, to which the disease or poison is transferred. The caster must make a successful Magical Attack roll to succeed.

+ +
+
+
+
+ Level 6 +
+
Extinguish
+
+ Description

The caster will cause all light, whether natural or magical, to be doused in a one mile radius of himself. He himself will be able to see as if it were broad daylight in this area. The Elementalist may also extinguish fires in this way.

+
+ +
+ Darkness:

As well as the lights going out in the area, the Darkness version of the above spell will be accompanied by a dank and dismal rain.

+
+
+
+
+ Level 7 +
+
Flash
+
+ Description

The Elementalist causes a blinding flash of light to appear in the sky: anyone not consciously averting their gaze (roll under Reflexes on 1d20) will be blinded for 2d10 Rounds and must fight at -4 attack and -8 defence until the effect is gone. The flash will be visible at a distance of ten miles during the day and fifty miles at night.

+
+
+ Flash Spell Attack Roll: +
+ +
+ Darkness:

The blindness is permanent and can only be alleviated by Dispel Magic.

+
+
+
+
+ Level 8 +
+
Fire Weapon
+
Range: 20m
+
Duration: Spell Expiry Roll applies
+
+ Description

This spell, when cast upon a melee weapon, will make it glow with a white-hot heat, increasing its armour penetration and its damage factor by 2 each. The weapon will not damage the wielder’s hand in any way.

+
+
+ Fire Weapon Melee Attack Roll: (you must have an appropriate weapon equipped for this to work) +
+ +
+ Darkness:

The heat of the weapon is so intense that no armour can protect against it at all: the victim’s Armour Factor is assumed to be 0.

+ Fire Weapon Darkness Melee Attack Roll: (you must have an appropriate weapon equipped for this to work) +
+
+ +
+
Blood of Molten Fire
+
Range: Self
+
Duration: Spell expiry applies
+
Origin: Desert of Songs
+
Rarity: Uncommon among the storm-wizards of the desert, rare elsewhere
+
+ Description

This spell turns the Elementalist’s blood into flaming magma. The caster suffers no ill effects beyond mild indigestion from having their blood turned to flaming death. Anyone cutting the caster’s skin is splattered with the burning fluid (Speed 12, damage 6). Any nonmagical weapon cutting the caster is destroyed. Creatures damaging the caster with natural weapons, such as claws or teeth, suffer 8 Health Points of damage automatically. If the caster chooses, he can break his own skin and use his own blood to light fires. The storm-wizards employ this spell in their battles with the undead creatures which plague the ancient tombs and ruins of the Desert of Songs. Many an undead monster has turned itself into a burning cinder attempting to kill a prepared stormwizard.

+
+
+ Blood of Molten Fire Spell Attack Roll: +
+
+
+
+ Level 9 +
+
Conflagration
+
+ Description

The caster may start a fire at a distance of a mile from where he stands merely by gesturing to the place where he wishes the fire to start, or by conjuring up in his mind’s eye a place which he has visited in the past week. The fire produced will be of the strength of a roaring bonfire and will easily catch on any combustible material in the area near it.

+
+ +
+ Darkness:

If the fire is started in a domestic building, all the doors and windows of the building will mysteriously jam or lock, preventing the escape of the people inside.

+
+
+ +
+
Wrath of the Hearth Spirit
+
Range: The building the fire is contained within
+
Duration: Spell expiry applies
+
Origin: Kastrian Sorcerers of Khitai
+
Rarity: Uncommon in Khitai, extremely rare elsewhere
+
+ Description

The Kastrian Sorcerers of Khitai created this spell to defend their homes from the seemingly endless waves of demons that besiege their land. This spell must be cast on a single hearth fire in a dwelling whereupon it awakens the spirit of the hearth fire to defend the domicile. The fire leaps outward, blasting a single intruder for 10 Health Points of damage (Speed 16); armour reduces the damage by its armour factor. The flame jumps to a different target each round, as directed by the caster, until the spell expires. The spell cannot target someone who lives in the house or is a guest there.

+
+
+ Wrath of the Hearth Spirit Spell Attack Roll: +
+ +
+ Darkness:

The darkness version of this spell drives the hearth spirit insane. The spirit attacks at random, and will attack those who dwell within the building.

+
+
+
+
+ Level 10 +
+
Summon the Holocaust
+
+ Description

The Holocaust is a being made entirely of fire and stands over 3m tall. Its touch will set alight a wooden wall or gradually melt metal objects, and no human can stand beside it for more than a round without being horribly scorched. To summon one of these creatures, the Elementalist needs the bones of one who has been killed by fire and must cast these up in the air, muttering a ritual incantation. The fire-being will then appear and serve the caster for one hour on this plane.

+
+
+
+ The Holocaust +
    +
  • Attack: 32
  • +
  • Fist of Fire: (d10 +2, 10)
  • +
  • Defence: 26
  • +
  • Evasion: 8
  • +
  • Magical Defence: 19
  • +
  • Health Points: 28
  • +
+
+
+ +
+ Darkness:

The methods and the effect are similar to above, except that after the hour time period, the Holocaust will not disband but will begin to act on its own accord, feasting on all the combustible things in the area. It will continue to burn for one day.

+
+
+
+
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+ +
+
+ Darkness Spells +
+ Level 1 +
+
Catspaw
+
Duration: 10 minutes
+
+ Description

This spell allows the caster to move with absolute silence over all surfaces, be they broad paving stones or brittle twigs. At the same time, the character casts no shadow. The character gains +1 stealth for every 2 ranks he has attained.

+
+
+

Geas: The absence of shadow will become permanent after ten uses.

+
+
+
+ +
+ Level 2 +
+
Darkeyes
+
Duration: 1 hour
+
+ Description

The character will be able to see perfectly even in pitch blackness. The limits of vision are the same as for a normal character during the day, except that the Darkness Elementalist will be able to detect infinitesimally small movements that would not normally be noticed by a character during daylight.

+
+
+

Geas: If a sudden light is produced in front of a Darkness Elementalist using this particular spell, he will be blinded for 1d20 rounds.

+
+
+
+ +
+ Level 3 +
+
Benight
+
Duration: Spell Expiry Roll applies
+
+ Description

This creates a zone of darkness 10m across, which the caster can direct over one or more of his enemies if they are grouped suitably. This zone will move on to the opponents with a speed of 20. Anyone failing to dodge will find themselves lost in an area of complete and utter inky darkness in which their combat abilities will be reduced as if they were fighting blind. A nameless dread will come over them, and they must try to resist the caster’s magical attack, or fall prey to one of the madnesses listed in the Madness Table (see p. 124).

+
+
+ Benight Spell Attack Roll: + Benight Madness Effect Roll: +
+
+

Geas: If no one succumbs to madness, the caster himself is attacked by a magical attack of 30; if the attack is successful, he goes mad himself (consult the Madness Table, p. 124).

+
+
+ +
+
Dark Thoughts
+
Range: 10m
+
Duration: Spell expiry applies
+
Origin: Krarth
+
Rarity: Rare in Krarth
+
+ Description

This is another spell from the pen of Vald the Mad Monk of Krarth. The spell affects a single target, filling their minds with dark and violent thoughts. The target flies into a berserker rage, attacking the nearest living beings. If a number of living beings stand close to him, the target will attack those he cares the most about first. The target will continue to attack until he can no longer see anyone. This spell gained some notoriety a few years ago when it was used during a noble marriage ceremony in Kurland; the groom, a duke of some importance, slew six people before his own bodyguard ended his life.

+
+
+ Dark Thoughts Spell Attack Roll: +
+
+

Geas: The first time the Darkness Elementalist casts this spell, his closest friend or family member will betray him.

+
+
+
+ +
+ Level 4 +
+
Curtain of Night
+
Duration: Spell Expiry Roll applies
+
+ Description

The Elementalist casts a wall of darkness in front of himself. This barrier is 1m wide and extends 5m to either side of him. Although the spell caster can see through the barrier, anyone on the other side cannot see back through it. The Elementalist can cast spells through the barrier, but no hostile spell magic can reach him: all spells involving fire or light cast at the barrier will be reflected back on the caster with the same magical attack as the caster’s.

+
+
+

Geas: If the Darkness Elementalist ever passes through his own Curtain of Night (voluntarily or not), he is attacked by a magical attack equivalent to his own which, if successful, causes him to fade away to nothingness, leaving behind only his shadow (if he still has one).

+
+
+
+ +
+ Level 5 +
+
Javelin of Darkness
+
+ Description

A mystic javelin appears in the Elementalist’s hands as he casts this spell. If he hurls it at an opponent or opponents, the spear affects them with the caster’s magical attack. Success leads to their being blinded; although the javelin may only effectively ‘hit’ one opponent (doing (d6, 3) damage if it does), its magically blinding effect will take place within a 10m radius of where it lands.

+
+
+ Javelin of Darkness Ranged Attack Roll: + Javelin of Darkness Blindness Spell Effect Roll: +
+
+

Geas: A black, star-shaped sooty patch will appear on the palm of the Elementalist’s hand after three successful uses of this spell.

+
+
+
+ +
+ Level 6 +
+
Shadowfall
+
+ Description

The Elementalist casts this spell over a one-mile radius. An eerie premature twilight settles over this area as if it were dusk, even if it is the middle of the day. If the spell is cast at night, then the darkness becomes utter and terrible. All creatures in the area are subject to an attack of Phobia (see the Madness Table, p. 124). A character failing to resist will be seized by panic and run for 2–12 hours from the epicenter of the spell (NB: the panic lasts longer than the normal phobia attack).

+
+
+ Shadowfall Spell Attack Roll: +
+
+

Geas: After three successful uses of this spell, the Elementalist becomes prone to intermittent attacks of sunlight phobia.

+
+
+
+ +
+ Level 7 +
+
Summon the Creatures of the Night
+
+ Description

The sorcerer raises the following dire phantasms from the shadows of the night. These creatures will remain until an hour before sunrise, serving the caster’s wishes (roll 1d6):

+
    +
  • Bats (see p. 238)
  • +
  • Giant Spider (see p 250)
  • +
  • Ghost (see p. 241)
  • +
  • Hag (see p. 243)
  • +
  • Wraith (see p. 253)
  • +
  • Spectre (see p. 250)
  • +
+

These phantasms are illusory, but unless disbelieved (see p. 103), they will create the same psychic and physical effects as the ‘real’ versions. Characters will therefore take damage, suffer Fright Attacks etc., unless they disbelieve them.

+
+
+ Summon the Creatures of the Night Spell Effect Roll: +
+
+

Geas: Every time the Darkness Elementalist casts this spell, he must resist becoming a creature of the shadows, an insubstantial Wraith (see p. 253). Roll a magical attack of 2d8 +1 against the character’s magical defence.

+
+
+ +
+
Dark Rebirth
+
Range: Touch
+
Duration: Variable, ends on the next night of a full moon
+
Origin: Krarth
+
+ Description

This blasphemous spell is a hideous parody of resurrection. The spell requires the sacrifice of a human being in an hour-long ritual in order to bring another back to life. The spell does indeed bring the person back, but without their soul, and the process is so scarring they are invariably mad in some way… usually quietly psychopathic. The spell’s effect is only temporary, but the Darkness Elementalist rarely lets this be known.

+
+
+

Geas: In future, the resurrected character may only be raised from the dead again by means of the Darkness version of this spell; other forms of resurrection or rebirth are forever barred to him.

+
+
+
+ +
+ Level 8 +
+
Eclipse of the Moon
+
+ Description

The caster may cause a temporary eclipse of the moon for ten Rounds: this will cause a Fright Attack (see p. 122) on anyone observing it with a strength of 12. Anyone failing to resist the effect of the spell will become permanently phobic about darkness (see the Madness Table, p. 124).

+
+
+

Geas: A shadowy half-moon will appear on the character’s forehead once he has cast this spell three or more times.

+
+
+
+ +
+ Level 9 +
+
Shadow Self
+
+ Description

By a great effort of will, the caster of this spell detaches his self from his body, slipping away from it by means of his shadow (anyone noticing this transformation would see the caster’s shadow flowing away from him and eventually detaching itself from his body). Once at a suitable distance from the old body, the shadow will reform into a corporeal shape that is an exact duplicate of the caster’s body (complete with his persona and ‘soul’) except that he will have lost 1 Health Point permanently in the transition. The old body will continue performing actions for another ten rounds after the Shadow Self has left it, but its Intelligence has been drained to zero and it therefore cannot cast spells. After this time, the body will crumple in on itself rather like a punctured balloon and fall to the ground as a lifeless husk. This spell is obviously useful to the Darkness Elementalist in an impossible combat situation where death is inevitable.

+
+
+

Geas: The permanent loss of 1 Health Point.

+
+
+
+ +
+ Level 10 +
+
Summon Balor, Prince of Darkness
+
+ Description

The eyes of Balor are death, and no one has seen him and lived, not even his disciples who dwell in the Lost City of Nem beneath the frozen lake of Nimmur. The geas of summoning Balor is therefore death to the caster, as it is to everyone else within a 20m radius.

+
+
+

Geas: Summoning Balor results in death to the caster and everyone within a 20m radius.

+
+
+ +
+
Karach
+
Range: Touch
+
Duration: Permanent
+
Origin: See text
+
+ Description

The Elementalist uses clay mixed with the heart-blood of a dead person to fashion a likeness of the dead individual. The Elementalist then calls upon all the dark gods of the underworld to breathe life into the mockery. The Karach appears as an almost perfect duplicate of the original, having all his skills and powers but lacking a soul, and as such cannot set foot on holy ground. It also has a single physical imperfection, such as an extra toe or a short tail, which might be spotted if it is captured and examined. The Karach is under the complete control of the Elementalist, and carries out his orders without question. An Elementalist can only have a single Karach active at one time.

+

There are ten thousand blasphemies written on every wall of the Lost City of Nem. This spell was transcribed from there by the mad monk Vlad of Krarth and placed in a series of books simply titled “The Black Passages”. Following Vlad’s untimely death, devout monks from his monastery scrubbed the Black Passages from the vellum and sent the books to Tamor for proper disposal. However, the blank books never made it as far as Tamor, and they were later sold to a dozen monasteries across the west where they were turned into illuminated manuscripts. The text from the Black Passages still lurks in the vellum waiting to be discovered.

+
+
+

Geas: The Elementalist permanently loses 1d2 points of Looks. The caster’s flesh becomes more and more clay-like until at 0 Looks, his flesh transforms completely to wet clay. This effect is cosmetic only and does not impair the Elementalist in any other way.

+
+
+
+
+
+ Name +
+ Range +
+ Duration +
+ Description +
+ + +
+
+
+
+
+
+
+ +
+ +
+ +
+
+

Melee Weapons

+
+ +
+ Weapon name +
+ Weapon type +
+ Magic Bonus + Armour Bypass Roll + Damage + Other Effects +
+ + +
+
+ +
+
+
+ +
+

Ranged Weapons

+
+ +
+ Weapon name + Weapon type + Magic Bonus + Armour Bypass Roll + Damage +
+ Short + Medium + Long +
+ +
+
+
+ +
+

Ammunition

+
+ +
+ Ammunition Name + Ammunition Type + Quantity + Magic Bonus +
+ Special Ammunition Modifiers: Attack + ABR + Damage +
+ Special Effects +
+ + +
+
+ +
+
+
+ +
+ +
+

Armour

+
+ Armour Type +
+ +
+ Base Armour Factor
+ Magic Bonus
+ Miscellaneous Bonus +
+ +
+

Non-Proficiency Penalties

+ Attack
+ Defence
+ Stealth +
+ +
+ Helmed Skull +
+ +
+ Shield Equipped?
+ Magic Bonus + +
+
+ Roll on +
+
+ +
+
+
+ +
+ +
+

Coin Purse

+ +
+ Crowns +
+ +
+ Florins +
+ +
+ Pennies +
+ +
+ Coin Chest +
+ +
+

Other Wealth

+
+ + +
+
+
+ + +
+

Possessions

+
+ Item
+ Location
+ Quantity       + Encumbrance Value +
+
+ + +
+

Encumbrance

+
+ Total Encumbrance
+



+ Maximum Encumbrance
+ +
+
+ Encumbrance Icon +
+
+
+ +
+
+ +
+

Assassin Profession Skills

+
+ +
+ Combat Techniques: +
+ Max: + + + Selected: + +
+
+ + +
+ Mental Techniques: +
+ Max: + + + Selected: + +
+
+ + +
+ Alchemical Techniques: +
+ Max: + + + Selected: + +
+
+ + +
+ Skills of the Assassin: +
+ Max: + + Selected: + +
+
+
+
+ Assassin Combat Techniques +
+
+
+ Armour Piercing + +
+ + +
+
+
+ +
+
+ Shock Attack + + +
+ +
+
+ + +
    Shock Attack Table +
  • Roll Description Effect
  • +
  • 1 Stunned Opponent’s attack, defence and evasion are all at 0
  • +
  • 2 Aghast Opponent’s attack and evasion are at 0; defence is half normal
  • +
  • 3-4 Astonished Opponent’s attack is at 0; evasion and defence at half normal
  • +
  • 5-6 Surprised Opponent’s attack is at 0; evasion and defence are unimpaired
  • + Any special effect from the above table lasts for a round, after which the victim may act normally.
+
+
+
+ +
+
+ Throwing Spike + +
+ + +
+
+
+ +
+
+ Unarmed Combat + +
+ + +
+
+
+
+
+
+ Assassin Mental Techniques +
+
+
+ Inner Sense + + +
+ +
+
+ + +
+
+
+
+
+ Memorize + + +
+ +
+
+ + +
+
+
+
+
+ Deathvow + +
+ + +
+
+
+
+
+
+ Assassin Meditational Techniques +
+
+
+ Light Trance + +
+ + +
+
+
+
+
+ Darkness Trance + +
+ + +
+
+
+
+
+ Water Trance + +
+ + +
+
+
+
+
+ Earth Trance + +
+ + +
+
+
+
+
+ Void Trance + +
+ + +
+
+
+
+
+ Fire Trance + +
+ + +
+
+
+
+
+ Wind Trance + +
+ + +
+
+
+
+
+
+ Assassin Alchemical Techniques +
+
+
+ Assassin’s Lotion + +
+ + +
+
+
+
+
+
+ Smoke Jar + +
+ + +
+
+
+ +
+
+ Flash Pellets + +
+ + +
+
+
+
+
+ The Skills of Assassins +
+
+
+ Breakfall + +
+ + +
+
+
+ +
+
+ Climbing + +
+ + +
+
+
+ +
+
+ Jumping + +
+ + +
+
+
+ +
+
+ Disguise + + + +
+ +
+
+ + +
+
+
+ +
+
+ Pilfer + + + +
+ +
+ +
+
+
+
+ Pick Lock + + + +
+ + +
+ +
+
+
+
+ Track + + +
+ +
+ +
+
+
+
+
+
+

Knight Profession Skills

+
+ +
+ Special Abilities of a Knight: +
+ Max: + + Selected: + +
+
+ +
+ The Supremacy of the Sword: +
+ Max: + + + Selected: + +
+
+
+
+ Special Abilities of a Knight +
+
+ Track + + +
+ +
+
+ + +
+
+
+ +
+
+ Armour Expert + +
+ + +
+
+
+ +
+
+ Ride Warhorse + +
+ + +
+
+
+
+
+ Disarm Technique + + +
+ +
+
+ + +
+
+
+
+
+ Expert Parry + +
+ + +
+
+
+
+
+ Main Gauche + +
+ + +
+
+ +
+
+ + , + + , + + + + + + + + + + +
+
+
+
+
+
+ Master Bowman + +
+ + +
+
+
+
+
+ Quick Draw + +
+ + +
+
+
+
+
+ Swordmaster + +
+ + +
+
+
+
+
+ Weaponskill + +
+ Weaponskill 1 + +
+ +
+ Weaponskill 2 + +
+ +
+ Weaponskill 3 + +
+
+ + +
+
+
+
+ +
+
+ The Supremacy of the Sword +
+
+ Fearless + +
+ + +
+
+
+
+
+ Intimidating + + +
+ +
+
+ + +
+
+
+
+
+ Iron Will + +
+ + +
+
+
+
+
+ Tireless + +
+ + +
+
+
+
+
+ True Grit + +
+ + +
+
+
+
+
+ Oak Fists + +
+ + +
+
+
+
+
+
+
+

Barbarian Profession Skills

+
+ + +
+ The Supremacy of the Sword: +
+ Max: + + + Selected: + +
+
+
+
+ Special Abilities of a Barbarian + +
+
+ Track + + +
+ +
+
+ + +
+
+
+
+
+ Berserk + +
+ + +
+
+
+
+
+ Ride Warhorse + +
+ + +
+
+
+
+
+ Bloodrage + +
+ + +
+
+
+
+ +
+
+ The Supremacy of the Sword +
+
+ Fearless + +
+ + +
+
+
+
+
+ Intimidating + + +
+ +
+
+ + +
+
+
+
+
+ Iron Will + +
+ + +
+
+
+
+
+ Tireless + +
+ + +
+
+
+
+
+ True Grit + +
+ + +
+
+
+
+
+ Oak Fists + +
+ + +
+
+
+
+
+
+
+

Sorcerer Profession Skills

+
+ Special Abilities of a Sorcerer +
+
+ Calligraphy + +
+ + +
+
+
+
+
+ Alchemy + +
+ + +
+
+
+
+
+ Craft Talismans + +
+ + +
+
+
+
+
+ Craft Amulets + +
+ + +
+
+
+
+
+ Craft Rings + +
+ + +
+
+
+
+
+ Craft Novel Items + +
+ + +
+
+
+
+
+ Craft Wands + +
+ + +
+
+
+
+
+
+

Mystic Profession Skills

+
+ The Special Abilities of a Mystic +
+
+ Spell Mastery + +
+
+
+
+ Premonition (or Sixth Sense) + + +
+ +
+
+ + +
+
+
+
+
+ ESP (or Seventh Sense) + + +
+ +
+
+ + +
+
+
+
+
+ Enchantment of Arms and Armour + +
+ + +
+
+
+
+
+ Adepthood + +
+ + +
+
+
+
+ +
+
+

Elementalist Profession Skills

+ +
+
+
+ Raw Power + + +
+ +
+
+ + +
+
+
+
+
+ Raw Power (alternate version) + + +
+ +
+
+ + +
+
+
+
+
+ Elemental Essence + + +
+ + +
+
+
+
+
+ Elemental Resistance + +
+ + +
+
+
+
+
+
+

Warlock Profession Skills

+
+ +
+ Special Abilities of a Warlock: +
+ Max: + + + Selected: + +
+
+
+ + +
+
+ Select Weapon Groups +
+ Weapon Group 1: + + + Weapon Group 2: + +
+
+
+ +
+
+ Special Abilities of a Warlock +
+
+ Appraise Enemy + +
+ +
+
+ + +
+
+
+
+
+ Arrow Cutting + +
+ + +
+
+
+
+
+ Fight Blind + +
+ + +
+
+
+
+
+ Unarmed Combat + +
+ + +
+
+
+
+
+ Minor Enchantment (Weapons) + +
+ + +
+
+
+
+
+ Minor Enchantment (Armour) + +
+ + +
+
+
+
+
+ Major Enchantment (Weapons) + +
+ + +
+
+
+
+
+ Major Enchantment (Armour) + +
+ + +
+
+
+
+
+ Ride Warhorse + +
+ + +
+
+
+
+
+
+

Knave Profession Skills

+
+ +
+ Special Abilities of a Knave: +
+ Max: + + + Selected: + +
+
+
+ +

Knave Profession Skills

+
+ The Special Abilities of a Knave +
+
+ Disguise + + +
+ +
+
+ + +
+
+
+
+
+ Pilfer + + +
+ +
+
+ + +
+
+
+
+
+ Second Tongue + +
+ + +
+
+
+
+
+ Favoured Language + +
+ Language + +
+
+ + +
+
+
+
+
+ Natural Linguist + +
+ + +
+
+
+
+
+ Human Intuition + +
+ + +
+
+
+
+
+ Uncanny Intuition + +
+ + +
+
+
+
+
+ Infuriate/Pacify + + +
+ + +
+
+
+
+
+ Distract + + +
+ +
+
+ + +
+
+
+
+
+ Magic Hands + +
+ + +
+
+
+
+
+ Bodyguard + +
+ +
+
+ + +
+
+
+
+
+ Gossip + +
+ +
+
+ + +
+
+
+
+
+ Presence + +
+ +
+
+ + +
+
+
+
+
+ Sense Falsehood + +
+ +
+
+ + +
+
+
+
+
+ Skills of the Mighty +
+
+ Hypnotic Suggestion + +
+ +
+
+ + +
+
+
+
+
+ Network + +
+ +
+
+ + +
+
+
+
+
+ Words are Power + +
+ +
+
+ + +
+
+
+
+
+
+

Hunter Profession Skills

+
+ +
+ Special Abilities of a Hunter: +
+ Max: + + Selected: + +
+
+
+
+ Special Abilities of a Hunter +
+
+ Track + + +
+ +
+
+ + +
+
+
+
+
+ Bowyer & Fletcher + +
+ + +
+
+
+
+
+ Precise Shot + +
+ + +
+
+
+
+
+ Favoured Weapon + +
+ Weapon type + +
+
+ + +
+
+
+
+
+ Favoured Terrain + +
+ Terrain Type + +
+
+ + +
+
+
+
+
+ Set Traps + +
+ + +
+
+
+
+
+ Forage + +
+ +
+
+ + +
+
+
+
+
+ Stillness + +
+ + +
+
+
+
+
+ Hunter’s Mind + +
+ + +
+
+
+
+
+ False Trail + + +
+ + +
+
+
+
+
+ Climb + + +
+ + +
+
+
+
+
+ Sneak Attack + +
+ + +
+
+
+
+
+ Soldier + +
+ + +
+
+
+
+
+ Penetrating Shot + + +
+ + +
+
+
+
+
+ Master Fletcher + +
+ + +
+
+
+
+
+ Fast Shot + +
+ + +
+
+ + +
+
+
+
+
+
+

Priest Profession Skills

+
+ +
+ Special Abilities of a Priest: +
+ Max: + + + Selected: + +
+
+
+
+ Special Abilities of a Priest +
+
+ Literate + +
+ + +
+
+
+
+
+ Ancient Script + +
+ + +
+
+
+
+
+ Breadth of Knowledge + +
+ + +
+
+
+
+
+ Linguist + +
+ +
+
+ + +
+
+
+
+
+ Bulwark + +
+ + +
+
+
+
+
+ Exorcism + +
+ +
+
+ + +
+
+
+
+
+ Sermon + +
+ +
+
+ + +
+
+
+
+
+ Healing Hands + +
+ + +
+
+
+
+
+ Remove Curse + +
+ +
+
+ + +
+
+
+
+
+ Depth of Knowledge + +
+ + +
+
+
+
+
+ Remove Madness + +
+ +
+
+ + +
+
+
+
+
+ Words are Power + +
+ + +
+
+
+
+
+
+

Special Abilities of a Demonologist

+
+ Special Abilities of a Demonologist +
+
+ Demonic Specialism + +
+ + +
+
+
+
+
+ Demonology + + +
+ Roll Demonology + +
+
+ + +
+
+
+
+
+ The Pentacle of Protection + +
+ + +
+
+
+
+
+ The Ritual of Summoning + +
+
+ Perform The Ritual of Summoning + +
+
+
+ + +
+
+
+
+
+ Banishing a Demon + +
+ Roll to Banish a Demon + +
+
+ + +
+
+
+
+
+ The Pact of the Dark Companion + +
+ Roll to summon the Dark Companion + +
+
+ + +
+
+
+
+
+
+

Custom Special Abilities

+
+ Customised Abilities of the +
+ Skill Name + +
+ 1 Rank + 2 Ranks + 3 Ranks +
+ Description +
+ + +
+
+
+
+
+ +
+ + Path Taken + + Name + +
+ Description +
+ + +
+ +
+ +
+ Secondary Skills +
+ Skill + + Level + +
+ Description +
+
+ + +
+
+
+
+
+ +
+
+ Modern Languages +
+ Language + + Fluency Level + + Literate? + + Script + +
+
+
+ Ancient Languages +
+ Language + + Fluency Level + + Literate? + + Script + +
+
+
+ +
+
+ Physical and Biographical Details + Gender +
+ Age +
+ Height +
+ Build +
+ Eye Colour +
+ Hair Colour / Style +
+ Origin Country +
+ Family Background +
+ Description +
+ + +

+ + Biography +
+ + +
+
+
+ +
+

Settings

+ Berserk: + Elementalist Raw Power + Combat Guards + The Supremacy of the Sword + Paths + Secondary Skills + Players Guide Spells +

Known Issues

+
    +
  • Demonologist Spells not yet implemented
  • +
+

Documentation

+

This character sheet includes material based on the Dragon Warriors setting, created by Dave Morris and Oliver Johnson, and used under the Serpent King Games Fan Policy. We are not permitted to charge for access to this content. This character sheet is not published, endorsed, or officially approved by Serpent King Games. For more information about Dragon Warriors products and Serpent King Games, please visit www.serpentking.com.

+ +

Serpent King Games expects you to use the Dragon Warriors setting responsibly and legally. This means avoiding associations with extreme graphic violence, explicit sexual content, hate speech against any real-world groups, or anything else that does not present Dragon Warriors in a positive light.

+ +

If you have any questions about Dragon Warriors or the conditions of use for this character sheet, please email info@serpentking.com.

+ +

Most images on this character sheet come directly from the Dragon Warriors books. The image representing Magic Points, named "effect," was created by ATOM and sourced from the Noun Project.

+ +

A huge shoutout to Roll20 forums members Gigs, vÍnce, and Scott, without whom this sheet would not have been built successfully.

+ +

Brendan R (SouthernSkies) and Norman, who have been absolute champions at doing the serious playtest/debugging of version 2.0

+ +

And most certainly not least, the brave group of adventurers who have been my primary playtesters: Gille, Hariot, Cador, Randos, Ulfthak, Argane, Ivon, and Kallister.

+ + Release Notes +

Ver 2.0

+
    +
  • Killed the 'Click to Update!' Button. The sheet now updates on change (Fair Warning: this may add lag to the sheet functions,this is the price of having a responsive sheet).
  • +
  • Removed legacy code; the character sheet is now CSE compliant.
  • +
  • Completely rewrote the JavaScript sheetworkers to add automation to nearly everything (and to clear out some old bugs that just wouldn't quit).
  • +
  • Base scores:All base scores are now calculated for you. Input your Profession and Rank, and the rest is handled automatically. You can override defaults, but your changes may be lost if the sheet recalculates (This should only happen if you change the content of the Profession input, but no garuantees it won't bug another way).
  • +
  • Custom professions can now be input, but will not auto-populate. All Profession's abilities and skills will remain visible and available to select for custom professions.
  • +
  • Characteristic scores now properly modify all base scores, including Atk, Def, MAtk, MDef, Stealth, Percep, Eva, ABR, Dmg, Encumbrance.
  • +
  • The experience field now automatically adjusts your rank.
  • +
  • Increasing your rank will adjust all scores appropriately (including MaxHp and Magic Points), unless you are using a custom profession.
  • +
  • Roll buttons for Base Characteristics and Starting HP can be hidden by a checkbox to help prevent accidental rerolls.
  • +
  • Weapons, Ammo, and Armour now use datalists and self-populate on selection. Custom entries can still be added as long as they are named uniquely.
  • +
  • Armour non-proficiency penalties now self-calculate based on your Profession. For Hunters, it takes the 'Soldier' skill into account.
  • +
  • Equipping special ammo types adjusts scores and Attack score by an additional -1 for non-Hunter professions.
  • +
  • Updated Wounds and Mana radio button logic: Clicking the first button a second time will clear it (first click sets the value to 1, second click sets it to 0).
  • +
  • Added a numerical input box for users who find it difficult to track the number of radio buttons clicked/un-clicked.
  • +
  • All skills known that modify stats should now apply those modifiers directly (if it is something tracked on the character sheet).
  • +
  • Skills with no conditional modifiers only need to be selected from the relevant Profession list on the skills page.
  • +
  • Some skills with conditional modifiers still need to be activated from the front of the sheet (as with the old sheet).
  • +
  • Skills selected as 'known' populate a list on the front sheet for player quick reference.
  • +
  • Added all spells (except, see above) from the Core book and Player's Guide to the sheet. All spells that have an associated roll, or effect, include a button to roll it.
  • +
  • Added a 'settings' element to the Documentation page, you can now control the visibility of certain items and change certain rules with controls on the settings tab.
  • +
+ + Other Requested Functional Changes: +
    +
  • Dice Roll buttons now better represent the kind of die they roll.
  • +
  • Encumbrance calculation now considers only coins and items in the inventory, not weapons/ammo lists or the shield tick (add those items to your inventory list to have them counted).
  • +
  • Encumbrance calculations can now handle fractions.
  • +
  • The item location field now impacts encumbrance calculation; items listed in any location other than "On person" are excluded from encumbrance calculations.
  • +
  • Moved magic attributes from the side of the Magic page to the top.
  • +
  • Added a button beside Stealth/Perception to choose between rolling 1d20 or 2d10.
  • +
  • Changed the Skills page to use a datalist for Secondary Skills, removing the old repeating table.
  • +
  • Fixed spelling of "Armour Piercing".
  • +
  • Added a Max HP Misc Modifiers input to help track temporary Maximum HP loss.
  • +
+ +

Ver 1.2.4

+ Token Integration and Radio Button Bug Fix +
    +
  • Implemented new attributes: currenthp, currentmp, currentmpelementtwo, and currentmpelementthree for accurate representation of wounds and magic points on token bars.
  • +
  • Corrected a bug requiring double clicks on wound/mp radio buttons to function properly.
  • +
+ + Layout Changes: +
    +
  • Removed redundant magic point trackers from the Magic page, which interfered with the currentmp set of attributes.
  • +
+ +

Ver 1.2.3

+ Workaround to Address Lag Issue +
    +
  • Streamlined Sheet Workers to reduce overall attribute calls. Added a "Click to Apply Changes" button to apply changes made to the sheet.
  • +
  • Note: This solution is temporary; further optimization is needed.
  • +
+ +

Ver 1.2.2

+ Layout Fixes, Bug Fixes +
    +
  • Fixed error preventing Precise Shot modifiers from being applied to rolls.
  • +
  • Removed spinners from read-only boxes to avoid confusion.
  • +
  • Moved base score inputs to the renamed "Base Scores" tab.
  • +
  • Removed ABR/DMG bonus boxes from the front sheet; moved AF misc bonus to the AF section of the Inventory page.
  • +
  • Opened base Magic Stats on the Magic page for all classes.
  • +
  • Changed the tab name from "Skills" to "Path and Skills" and added a paths box.
  • +
  • Added a classic DW picture to the front page to reduce spacing issues.
  • +
  • Added a poison save roll button under health points.
  • +
+ +

Ver 1.2.1

+ Layout Changes, Bug Fixes, and Sheet Roll Updates +
    +
  • Improved display using CSS Grid, removed redundant information.
  • +
  • Revised "Combat" tab to "Miscellaneous Modifiers" for entering modifiers.
  • +
  • All guard functions now controlled on the front page.
  • +
  • Updated roll templates and fixed PFC sheet roll.
  • +
  • Increased Max Wounds and Magic Points to 50 dots each.
  • +
  • Removed API dependency for ESP and Premonition checks; suggested "Blind Roll" API for Pro Subscribers.
  • +
+ +

Ver 1.2

+ Total Overhaul Update +
    +
  • Major layout changes and font style corrections.
  • +
  • Added artworks and fixed issues with Elementalist MP sections and Mystic's Psychic Fatigue field.
  • +
  • Added Combat page to track Attack and Defence scores.
  • +
  • Changed button images and added wound counters.
  • +
  • Added magic bonus section to weapons and shields, and ensured only one weapon's magic bonus applies at a time.
  • +
  • Modified Armour Factor area and added basic game roll functions.
  • +
+ +

Ver 1.1

+ Bug Fixes and Feature Updates +
    +
  • Improved error checking for HP, MP, and other stats.
  • +
  • Added manual rolling options for skills and improved formula accuracy.
  • +
+ +

Ver 1.0

+ Initial Release +
    +
  • First version of the Dragon Warriors character sheet.
  • +
-
-
- - - - - - - - - - - -
-
-
- This character sheet includes material based on the Dragon Warriors setting, as created by and copyright (c) Dave Morris and Oliver Johnson, and used according to the terms of the Serpent King Games Fan Policy. We are not permitted to charge you to use or access this content. This character sheet is not published, endorsed, or officially approved by Serpent King Games. For more information about Dragon Warriors products and Serpent King Games, please visit www.serpentking.com
- Serpent King Games expects you to use the Dragon Warriors setting responsibly and legally. That means avoiding associating the setting with extreme graphic violence, explicit sexual content, hate speech against any particular real-world segment of society, or anything else that does not present Dragon Warriors in a positive light.
- If you have any questions about Dragon Warriors, or the conditions of use of this character sheet, please email info@serpentking.com

- Most of the images used on the character sheet come directly from the Dragon Warriors books.

- The image used to represent Magic Points named "effect" and was created by ATOM and sourced from the Noun Project.

- A huge shoutout to Roll20 forums member GiGs, without whom this sheet would not have been built.

- Thank you to DragonWarriors Discord user SouthernSkies for playtesting and issue reporting.

- And most certainly not least, the brave group of adventurers who have been my primary playtesters: Gille, Hariot, Cador, Randos and Ulfthak.

- - - - Implemented new attributes: currenthp, currentmp currentmpelementtwo and currentmpelementthree.
- These attributes are to be used with token bars to accurately represent wounds and magic points which count down properly.
- In developing these attributes, I was able to correct a bug which was requiring players to double click on wound / mp radio buttons to function properly.
- Layout changes:
- Removed redundant magic point trackers from the magic page. Not only were they redundant, but they interferred with the function of the currentmp set of attributes.
- - - Problem: -     "Need to streamline Sheet Workers in the code to reduce overall attribute calls (looking for experienced JS coders for some help here!)." - The sheet will no longer seek to automatically update scores after any changes, as users had reported significant performance issues due to too many attribute checks/calls.
- I have added a button to the top-bar "Click to Apply Changes", which the user will need to click to apply any changes made to the sheet.
- While this is not the ideal solution I would choose, I do not have enough coding experience to rebuild the Sheet Workers myself.
- - Layout fixes, Bug fixes - - Fixed error preventing Precise Shot modifiers from being applied to rolls. - Spinners removed from read-only boxes to avoid confusion.
- Have moved base score inputs (all) to the renamed tab "Base Scores" (formerly Miscellaneous Modifiers).
- Removed ABR / DMG bonus boxes from front sheet as unnecessary.
- Moved AF misc bonus to the AF section of the Inventory page.
- Opened up base Magic Stats on the Magic page for all classes.
- Changed tab name from "Skills" to "Path and Skills" and added a paths box.
- Added a classic DW picture to the front page to reduce strange spacing issues after taking out unnecessary input boxes.
- Poison save roll button added under health points
- - Layout changes, Bug fixes and Sheet Roll updates

- - Improved display of all areas of the sheet utilising CSS Grid more substantially. - Removed redundant information from across the entire sheet:
-      - "Combat" tab has been revised and is now "Miscellaneous Modifiers". It is now possible to enter misc modifiers for almost every numerical entry on the sheet.
-      - All guard functions are now controlled on the front page.
-      - The majority of roll templates are now handled primarily on the front page.
-      - Final tally modified scores now appear alongside their base stats, or in the Combat Summary box
- Encumbrance was not calculating properly due to an old Sheet Worker which was not updated properly, fixed.
- Sheet rolls were clumsy and unprofessional looking, they have been updated to use roll templates. Thanks to @SouthernSkies on the Dragon Warriors Discord server for his assistance with this.
- PFC sheet roll was not working at all, fixed.
- Max Wounds and Magic Point pools have been increased to 50 dots each.
- ESP and Premonition checks were dependent on an API, this requirement has been removed for the published version. If you are a Pro Subscriber, I suggest that you install the "Blind Roll" API and create the following macros:
- ESP "!broll 1d100<@{espchance}"
- Premonition "!broll 1d100<@{premonitionchance}"
- - Total Overhaul Update

- - Major changes to layout, and corrected font style for inputs
- Added artworks
- Corrected problems with Elementalist MP sections
- Fixed issues with Mystic's Psychic Fatigue field
- Added Combat page to track all changes to Attack and Defence scores through guards, profession abilities and equipment modifiers
- Changed the button image on wounds and mana points trackers
- Added wound counters to track Health Points down to -1, -2 and -3 (wounds tracker for Macros does not take these into account, but they are not relevant for KO/shock calculations anyway)
- Added a magic bonus section to weapons and shields for applying bonuses to combat attributes.
- Added 'equipped' value to weapons selection to ensure only a single weapon's magic bonuses applies at a time.
- Modified the Armour Factor area to be more specific.
- Added sheet rolls for attacks, attribute checks and other basic game roll functions
- Further code stream-lining.
-
- - - Missing Languages added and literacy checkbox default value fixed
- Slight remodel of the front page to incorporate new elements
- Sheet Worker now rounds off encumberance, and calculates total (including equipment, coins, weapons and shield) and maximum encumbrance values
- Added a quantity field for inventory items
- Added an ammunition section underneath the Weapons
- Wounds checkboxes have been updated, the number of radioboxes available is set to equal a character's max HP. The sheet can calculate remaining HP based on the wounds counter.
- Show/hide magic sections (front page and magic page) dependant on profession selected from the dropdown list
- Major code tidy up
-
- - None known, let me know if you see one so I can squash it!
-
- - Change Attribute names so that making custom Macro Calls for end users is easier to work.
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ {{#title}}
{{title}}
{{/title}} + {{#subtitle}}
{{subtitle}}
{{/subtitle}} +
+
+ {{#roll}}
Roll
{{/roll}} + {{#roll}}
{{roll}}
{{/roll}} + {{#Vs}}
Vs
{{/Vs}} + {{#Vs}}
{{Vs}}
{{/Vs}} + {{#allprops() title subtitle roll Vs desc}} +
{{key}}
+
{{value}}
+ {{/allprops() title subtitle roll Vs desc}} + {{#desc}}
{{desc}}
{{/desc}} +
+
+
+ + +
+
+ {{#title}}
{{title}}
{{/title}} + {{#subtitle}}
{{subtitle}}
{{/subtitle}} +
+ +
+ {{#spellattackroll}}
Spell Attack Roll
{{/spellattackroll}} + {{#roll}}
Roll Result
{{/roll}} + + {{#spellattackroll}} +
{{spellattackroll}}
+ {{#rollTotal() spellattackroll 20}}
Critical Failure!
{{/rollTotal() spellattackroll 20}} + {{#rollTotal() spellattackroll 2}}
Critical Success!
{{/rollTotal() spellattackroll 2}} + {{/spellattackroll}} + + {{#roll}} +
{{roll}}
+ {{#rollTotal() roll 2}}
Critical Success!
{{/rollTotal() roll 2}} + {{#rollTotal() roll 20}}
Critical Failure!
{{/rollTotal() roll 20}} + {{/roll}} + + {{#^rollTotal() spellattackroll 20}} + {{#speedvsevasion}}
Speed vs Evasion
{{/speedvsevasion}} + {{#speedvsevasion}}
{{speedvsevasion}}
{{/speedvsevasion}} + {{#magicalattackvsmagicaldefence}}
Magical Attack vs Magical Defence
{{/magicalattackvsmagicaldefence}} + {{#magicalattackvsmagicaldefence}}
{{magicalattackvsmagicaldefence}}
{{/magicalattackvsmagicaldefence}} + {{#range}}
Range
{{/range}} + {{#range}}
{{range}}
{{/range}} + {{#damage}}
Damage
{{/damage}} + {{#damage}}
{{damage}}
{{/damage}} + {{/^rollTotal() spellattackroll 20}} + + {{#^rollTotal() roll 20}} + {{#Vs}}
Target number to roll, or less
{{/Vs}} + {{#Vs}}
{{Vs}}
{{/Vs}} + {{/^rollTotal() roll 20}} + + {{#allprops() title subtitle desc spellattackroll speedvsevasion magicalattackvsmagicaldefence range damage roll Vs}} +
{{key}}
+
{{value}}
+ {{/allprops() title subtitle desc spellattackroll speedvsevasion magicalattackvsmagicaldefence range damage roll Vs}} + {{#desc}}
{{desc}}
{{/desc}} +
+
+
+ + +
+
+ {{#title}}
{{title}}
{{/title}} + {{#subtitle}}
{{subtitle}}
{{/subtitle}} +
+
+ {{#attackroll}}
Attack Roll
{{/attackroll}} + {{#attackroll}}
{{attackroll}}
{{/attackroll}} + + {{#roll}}
Roll Result
{{/roll}} + {{#roll}}
{{roll}}
{{/roll}} + + {{#rollWasFumble() roll}}
Critical Failure!
{{/rollWasFumble() roll}} + {{#rollWasFumble() attackroll}}
Critical Miss!
{{/rollWasFumble() attackroll}} + + {{#^rollWasFumble() roll}} + {{#rollWasCrit() roll}}
Critical Success!
{{/rollWasCrit() roll}} + {{#^rollWasCrit() roll}} + {{#Vs}}
Target number to roll, or less
{{/Vs}} + {{#Vs}}
{{Vs}}
{{/Vs}} + {{/^rollWasCrit() roll}} + {{/^rollWasFumble() roll}} + + {{#^rollWasFumble() attackroll}} + {{#attackvsdefence}}
Attack vs Defence
{{/attackvsdefence}} + {{#attackvsdefence}}
{{attackvsdefence}}
{{/attackvsdefence}} + {{#attackvsranged}}
Attack vs Ranged Adjustments
{{/attackvsranged}} + {{#attackvsranged}}
{{attackvsranged}}
{{/attackvsranged}} + {{#abr}} + {{#^rollWasCrit() attackroll}} +
Armour Bypass Roll
+
{{abr}}
+ {{/^rollWasCrit() attackroll}} + {{/abr}} + {{#rollWasCrit() attackroll}}
Critical Hit!
The attack automatically bypasses armour.
{{/rollWasCrit() attackroll}} + {{#Damage}} +
Damage
+
{{Damage}}
+ {{/Damage}} + {{/^rollWasFumble() attackroll}} + + {{#^rollWasFumble() attackroll}} + {{#^rollWasFumble() roll}} + {{#allprops() title subtitle desc roll attackroll attackvsranged attackvsdefence Vs abr Damage}} +
{{key}}
+
{{value}}
+ {{/allprops() title subtitle desc roll attackroll attackvsranged attackvsdefence Vs abr Damage}} + {{#desc}}
{{desc}}
{{/desc}} + {{/^rollWasFumble() roll}} + {{/^rollWasFumble() attackroll}} +
+
+
+ + const buttonlist = ["character","inventory","basescores","magic","skills","languages","biographical","documentation"]; + buttonlist.forEach(button => { + on(`clicked:${button}`, function() { + setAttrs({ + sheetTab: button + }); + }); + }); + + const repeatingSum = (destinations, section, fields, ...extras) => { + const isNumber = value => parseFloat(value).toString() === value.toString(); + const isOption = value => [...checks.valid, ...checks.roundtypes].includes(value); + const isRounding = value => checks.roundtypes.includes(value); + const isFraction = value => value.includes('/') && !(value.includes(',') || value.includes('|')); + const getTrimmed = value => value.toLowerCase().replace(/\s/g, ''); + const getRounded = (type, value, pow) => (Math[type](value * Math.pow(10, pow)) / Math.pow(10, pow)).toFixed(Math.max(0, pow)); + const getFraction = (value) => /*{ console.log(`value: ${value}`); */ + parseInt(value.split('/')[0]) / parseInt(value.split('/')[1]); + const getMultiplier = (value, rounding = 1) => 'undefined' === typeof value ? (rounding ? 0: 1) : ( + isNumber(value) ? parseFloat(value) : (isFraction(value) ? getFraction(value) : value)); + if (!Array.isArray(destinations)) destinations = [getTrimmed(destinations)]; + if (!Array.isArray(fields)) fields = [getTrimmed(fields)]; + const fields_trimmed = fields.map(field => getTrimmed(field).split(':')[0]); + const subfields = fields_trimmed.slice(0,destinations.length); + const checks = { valid: ['multiplier'], roundtypes: ['ceil', 'round', 'floor'] }; + let properties = {attributes: {}, options: {}}; + extras.forEach(extra => { + const [prop, v] = getTrimmed(extra).split(':'); + const multiplier_maybe = getMultiplier(v, isRounding(prop)); + const obj = isNumber(multiplier_maybe) ? subfields.reduce((obj,field) => { + obj[field] = multiplier_maybe; + return obj; + },{}) : multiplier_maybe.split(',').reduce((obj, item) => { + const [stat, value] = item.split('|'); + const multiplier = getMultiplier(value, isRounding(prop)); + obj[stat] = multiplier; + return obj; + }, {}); + properties[isOption(prop) ? 'options' : 'attributes'][prop] = obj; + }); + getSectionIDs(`repeating_${section}`, idArray => { + const attrArray = idArray.reduce((m, id) => [...m, ...(fields_trimmed.map(field => `repeating_${section}_${id}_${field}`))], []); + getAttrs([...attrArray, ...Object.keys(properties.attributes)], v => { + const getValue = (section, id, field) => v[`repeating_${section}_${id}_${field}`] === 'on' ? 1 : parseFloat(v[`repeating_${section}_${id}_${field}`]) || 0; + const commonMultipliers = (fields.length <= destinations.length) ? [] : fields.splice(destinations.length, fields.length - destinations.length); + const output = destinations.reduce((obj, destination, index) => { + let sumTotal = idArray.reduce((total, id) => total + getValue(section, id, fields_trimmed[index]) * commonMultipliers.reduce((subtotal, mult) => subtotal * ((!mult.includes(':') || mult.split(':')[1].split(',').includes(fields_trimmed[index])) ? getValue(section, id, mult.split(':')[0]) : 1), 1), 0); + sumTotal *= (properties.options.hasOwnProperty('multiplier') && Object.keys(properties.options.multiplier).includes(fields_trimmed[index])) ? (parseFloat(properties.options.multiplier[fields_trimmed[index]]) || 0): 1; + sumTotal += Object.entries(properties.attributes).reduce((total, [key, value]) => + total += (value.hasOwnProperty(fields_trimmed[index]) ? parseFloat(v[key] || 0) * (parseFloat(value[fields_trimmed[index]]) || 1): 0) , 0); + checks.roundtypes.forEach(type => { + if (properties.options.hasOwnProperty(type)) { + if (Object.keys(properties.options[type]).includes(fields_trimmed[index])) { + sumTotal = getRounded(type, sumTotal, (+properties.options[type][fields_trimmed[index]] || 0)); + } else if (properties.options[type] == '0' || !isNaN(+properties.options[type] || 'x') ) { + sumTotal = getRounded(type, sumTotal, +properties.options[type]); + } + } + }); + obj[destination] = sumTotal; + return obj; + }, {}); + setAttrs(output); + }); + }); + }; + +on("change:xp", function() { + getAttrs(['xp', 'rank'], function(values) { + let xp = parseInt(values.xp) || 0; // Default xp to 0 if not provided + let rank = 1; // Initialize rank to 1 + + // Determine rank based on experience points + if (xp >= 650) { + // Calculate rank beyond 9th + rank = 9 + Math.floor((xp - 650) / 250); + } else if (xp >= 450) { + rank = 8; + } else if (xp >= 300) { + rank = 7; + } else if (xp >= 200) { + rank = 6; + } else if (xp >= 130) { + rank = 5; + } else if (xp >= 90) { + rank = 4; + } else if (xp >= 60) { + rank = 3; + } else if (xp >= 30) { + rank = 2; + } + + // Set attributes for rank + setAttrs({ + rank: rank + }); + }); +}); + +on("change:profession change:rank", function() { + // Retrieve profession and rank values + getAttrs(['profession', 'rank'], function(values) { + let profession = values.profession || "Unknown"; + let rank = parseInt(values.rank) || 1; // Default rank to 1 if not provided + + // List of valid professions from the datalist + const validProfessions = ["Knight", "Barbarian", "Warlock", "Assassin", "Knave", "Elementalist", "Hunter", "Priest", "Mystic", "Demonologist", "Sorcerer"]; + + // Check if the profession is valid + if (!validProfessions.includes(profession)) { + return; // Exit the function if profession is not in the valid list + } + + // Define base values based on profession + let baseAttack = 0; + let baseDefence = 0; + let baseMagicalAttack = 0; + let baseMagicalDefence = 0; + let baseEvasion = 0; + let baseStealth = 0; + let basePerception = 0; + + // Determine base values based on profession + if (profession === "Knight") { + baseAttack = 13; + baseDefence = 7; + baseMagicalAttack = 0; + baseMagicalDefence = 3; + baseEvasion = 4; + baseStealth = 13; + basePerception = 5; + } else if (profession === "Barbarian") { + baseAttack = 14; + baseDefence = 6; + baseMagicalAttack = 0; + baseMagicalDefence = 3; + baseEvasion = 5; + baseStealth = 13; + basePerception = 5; + } else if (profession === "Sorcerer") { + baseAttack = 11; + baseDefence = 5; + baseMagicalAttack = 15; + baseMagicalDefence = 5; + baseEvasion = 3; + baseStealth = 13; + basePerception = 5; + } else if (profession === "Mystic") { + baseAttack = 12; + baseDefence = 6; + baseMagicalAttack = 14; + baseMagicalDefence = 4; + baseEvasion = 3; + baseStealth = 14; + basePerception = 6; + } else if (profession === "Elementalist") { + baseAttack = 11; + baseDefence = 5; + baseMagicalAttack = 15; + baseMagicalDefence = 5; + baseEvasion = 3; + baseStealth = 13; + basePerception = 5; + } else if (profession === "Warlock") { + baseAttack = 12; + baseDefence = 5; + baseMagicalAttack = 12; + baseMagicalDefence = 4; + baseEvasion = 3; + baseStealth = 13; + basePerception = 5; + } else if (profession === "Assassin") { + baseAttack = 13; + baseDefence = 5; + baseMagicalAttack = 0; + baseMagicalDefence = 3; + baseEvasion = 5; + baseStealth = 18; + basePerception = 8; + } else if (profession === "Knave") { + baseAttack = 11; + baseDefence = 5; + baseMagicalAttack = 0; + baseMagicalDefence = 3; + baseEvasion = 5; + baseStealth = 14; + basePerception = 8; + } else if (profession === "Hunter") { + baseAttack = 13; + baseDefence = 6; + baseMagicalAttack = 0; + baseMagicalDefence = 3; + baseEvasion = 5; + baseStealth = 16; + basePerception = 8; + } else if (profession === "Priest") { + baseAttack = 11; + baseDefence = 6; + baseMagicalAttack = 0; + baseMagicalDefence = 6; + baseEvasion = 3; + baseStealth = 12; + basePerception = 6; + } else if (profession === "Demonologist") { + baseAttack = 11; + baseDefence = 5; + baseMagicalAttack = 15; + baseMagicalDefence = 5; + baseEvasion = 3; + baseStealth = 13; + basePerception = 5; + } + + // Calculate rank-based increases + let attackIncrease = 0; + let defenceIncrease = 0; + let magicalAttackIncrease = 0; + let magicalDefenceIncrease = 0; + let evasionIncrease = 0; + let stealthIncrease = 0; + let perceptionIncrease = 0; + + if (profession === "Assassin") { + attackIncrease = rank; + defenceIncrease = Math.floor((rank - 2) / 2); + magicalDefenceIncrease = rank; + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = rank; + perceptionIncrease = rank; + } else if (profession === "Barbarian") { + attackIncrease = rank; + defenceIncrease = rank; + magicalDefenceIncrease = rank; + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 2) / 2); + perceptionIncrease = Math.floor((rank - 2) / 2); + } else if (profession === "Knight") { + attackIncrease = rank; + defenceIncrease = rank; + magicalDefenceIncrease = rank; + evasionIncrease = Math.floor((rank - 4) / 4); + perceptionIncrease = Math.floor((rank - 2) / 2); + stealthIncrease = Math.floor((rank - 3) / 3); + } else if (profession === "Elementalist") { + attackIncrease = Math.floor((rank - 3) / 3); + defenceIncrease = Math.floor((rank - 3) / 3); + magicalAttackIncrease = rank + Math.floor((rank - 6) / 6); + magicalDefenceIncrease = rank + Math.floor((rank - 6) / 6); + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = Math.floor((rank - 3) / 3); + } else if (profession === "Mystic") { + attackIncrease = Math.floor((rank - 2) / 2); + defenceIncrease = Math.floor((rank - 2) / 2); + magicalAttackIncrease = rank + Math.floor((rank - 6) / 6); + magicalDefenceIncrease = rank + Math.floor((rank - 6) / 6) + Math.floor((rank - 12) / 12); + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = rank; + } else if (profession === "Sorcerer") { + attackIncrease = Math.floor((rank - 3) / 3); + defenceIncrease = Math.floor((rank - 3) / 3); + magicalAttackIncrease = rank + Math.floor((rank - 6) / 6); + magicalDefenceIncrease = rank + Math.floor((rank - 6) / 6); + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = Math.floor((rank - 3) / 3); + } else if (profession === "Warlock") { + attackIncrease = rank; + defenceIncrease = rank; + magicalAttackIncrease = rank; + magicalDefenceIncrease = rank; + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = Math.floor((rank - 3) / 3); + } else if (profession === "Knave") { + attackIncrease = rank; + defenceIncrease = Math.floor((rank - 2) / 2); + magicalDefenceIncrease = rank; + evasionIncrease = rank; + stealthIncrease = rank; + perceptionIncrease = rank; + } else if (profession === "Hunter") { + attackIncrease = rank; + defenceIncrease = rank; + magicalDefenceIncrease = rank; + evasionIncrease = rank; + stealthIncrease = rank; + perceptionIncrease = rank; + } else if (profession === "Priest") { + attackIncrease = Math.floor((rank - 2) / 2); + defenceIncrease = Math.floor((rank - 2) / 2); + magicalAttackIncrease = Math.floor((rank - 4) / 4); + magicalDefenceIncrease = rank + Math.floor((rank - 6) / 6); + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = Math.floor((rank - 3) / 3); + } else if (profession === "Demonologist") { + attackIncrease = rank; + defenceIncrease = Math.floor((rank - 2) / 2); + magicalAttackIncrease = rank; + magicalDefenceIncrease = rank; + evasionIncrease = Math.floor((rank - 4) / 4); + stealthIncrease = Math.floor((rank - 3) / 3); + perceptionIncrease = Math.floor((rank - 3) / 3); + } + + // Calculate final values + let finalAttack = baseAttack + attackIncrease; + let finalDefence = baseDefence + defenceIncrease; + let finalMagicalAttack = baseMagicalAttack + magicalAttackIncrease; + let finalMagicalDefence = baseMagicalDefence + magicalDefenceIncrease; + let finalEvasion = baseEvasion + evasionIncrease; + let finalStealth = baseStealth + stealthIncrease; + let finalPerception = basePerception + perceptionIncrease; + + // Set final attribute values + setAttrs({ + attack: finalAttack, + defence: finalDefence, + magicalattack: finalMagicalAttack, + magicaldefence: finalMagicalDefence, + evasion: finalEvasion, + stealth: finalStealth, + perception: finalPerception + }); + }); +}); + +on("change:profession change:rank change:maxhp_mod change:base_maxhp", function() { + // Retrieve necessary attributes + getAttrs(['profession', 'rank', 'maxhp', 'previousRank', 'maxhp_mod', 'base_maxhp'], function(values) { + let profession = values.profession || "Unknown"; + let rank = parseInt(values.rank) || 1; + let maxHP = parseInt(values.maxhp) || 1; + let previousRank = parseInt(values.previousRank) || 1; + let maxHP_Mod = parseInt(values.maxhp_mod) || 0; + let baseMaxHP = parseInt(values.base_maxhp) || 1; // Retrieve base max HP + + // Define base HP increases based on profession + let hpIncreaseCurrentRank = 0; + let hpIncreasePreviousRank = 0; + + // Calculate HP increase for the current rank + switch (profession) { + case "Knight": + case "Hunter": + hpIncreaseCurrentRank = rank; + break; + case "Barbarian": + hpIncreaseCurrentRank = rank * 2; + break; + case "Sorcerer": + case "Mystic": + case "Elementalist": + case "Warlock": + case "Assassin": + case "Knave": + case "Priest": + case "Demonologist": + hpIncreaseCurrentRank = Math.floor(rank / 2); + break; + } + + // Calculate HP increase for the previous rank (using the same logic) + switch (profession) { + case "Knight": + case "Hunter": + hpIncreasePreviousRank = previousRank; + break; + case "Barbarian": + hpIncreasePreviousRank = previousRank * 2; + break; + case "Sorcerer": + case "Mystic": + case "Elementalist": + case "Warlock": + case "Assassin": + case "Knave": + case "Priest": + case "Demonologist": + hpIncreasePreviousRank = Math.floor(previousRank / 2); + break; + } + + // Calculate new max HP using the base value + let newMaxHP = baseMaxHP + hpIncreaseCurrentRank - hpIncreasePreviousRank + maxHP_Mod; + + // Update attributes + setAttrs({ + maxhp: newMaxHP, + previousRank: rank, + base_maxhp: baseMaxHP // Store the base max HP if it's not already set + }); + }); +}); + +on("change:rank change:profession", function() { + getAttrs(['profession', 'rank'], function(values) { + let profession = values.profession || "Unknown"; + let rank = parseInt(values.rank) || 1; + let maxmp = 0; + let twomaxmp = 0; + let threemaxmp = 0; + + switch (profession.toLowerCase()) { + case "sorcerer": + maxmp = 4 + (rank > 1 ? (rank - 1) * 4 : 0); + break; + case "elementalist": + maxmp = 3 * rank; + twomaxmp = rank; + threemaxmp = rank; + break; + case "warlock": + maxmp = 2 * rank; + break; + case "demonologist": + maxmp = 4 + (rank > 1 ? (rank - 1) * 3 : 0); + break; + default: + maxmp = 0; + break; + } + + // Set attributes for max magic points + setAttrs({ + maxmp: maxmp, + twomaxmp: twomaxmp, // Secondary pool for Elementalist + threemaxmp: threemaxmp // Tertiary pool for Elementalist + }); + }); +}); + +on('change:strength change:enhancement change:enhancement_neg change:cutting_power_of_the_mind_toggle change:udjat change:might change:reflexes change:intelligence change:psychictalent change:looks change:miscstrength change:miscreflexes change:miscintelligence change:miscpsychictalent change:misclooks change:adepthood change:favoured_language', function() { + getAttrs([ + 'strength', 'reflexes', 'intelligence', 'psychictalent', 'looks', + 'miscstrength', 'miscreflexes', 'miscintelligence', 'miscpsychictalent', 'enhancement', 'enhancement_neg', + 'misclooks', 'adepthood', 'favoured_language', 'might', 'udjat', 'cutting_power_of_the_mind_toggle' + ], function(values) { + // Parse attributes with default value of 0 if not present + let str = parseInt(values.strength, 10) || 0; + let ref = parseInt(values.reflexes, 10) || 0; + let int = parseInt(values.intelligence, 10) || 0; + let psy = parseInt(values.psychictalent, 10) || 0; + let lks = parseInt(values.looks, 10) || 0; + let mstr = parseInt(values.miscstrength, 10) || 0; + let mref = parseInt(values.miscreflexes, 10) || 0; + let mint = parseInt(values.miscintelligence, 10) || 0; + let mpsy = parseInt(values.miscpsychictalent, 10) || 0; + let mlks = parseInt(values.misclooks, 10) || 0; + let adepthood = values.adepthood === "1"; + let favoured_language = values.favoured_language === "1"; + let might = values.might === "1"; + let udjat = values.udjat === "1"; + let cuttingpower = values.cutting_power_of_the_mind_toggle === "1"; + let Enhancement = values.enhancement === "1"; + let enhancementNeg = parseInt(values.enhancement_neg, 10) || 0; + + // Calculate base values + let fstr = str + mstr; + let fref = ref + mref; + let fint = int + mint; + let fpsy = psy + mpsy; + let flks = lks + mlks; + + // Apply Adepthood rule + if (adepthood) { + fref = 18; + fpsy = 18; + } + + // Apply Might rule + if (might) { + if (fstr <= 15) { + fstr = 16; // If strength is 15 or less, increase it to 16 + } else if (fstr >= 16 && fstr <= 18) { + fstr = 19; // If strength is between 16 and 18, increase it to 19 + } + } + // Apply cutting_power_of_the_mind rule + if (cuttingpower) { + if (fint <= 17) { + fint = 18; + } else if (fint == 18) { + fint = 19; + } + } + + //Apply Enhancement rule + if (Enhancement) { + if (fstr <= 17) { + fstr = 18; + } else if (fstr == 18) { + fstr = 19; + } else { + fstr = fstr; + } + if (fref <= 17) { + fref = 18; + } else if (fref == 18) { + fref = 19; + } else { + fref = fref; + } + } + + //Apply Enhancement Negative modifiers + if (enhancementNeg < 0) { + fstr += enhancementNeg; + fref += enhancementNeg; + } + + // Apply Udjat rule + if (udjat) { + // For fint (intelligence) + if (fint <= 15) { + fint = 16; // If intelligence is 15 or less, increase it to 16 + } else if (fint >= 16 && fint <= 18) { + fint = 19; // If intelligence is between 16 and 18, increase it to 19 + } + + // For fpsy (psychic talent) + if (fpsy <= 15) { + fpsy = 16; // If psychic talent is 15 or less, increase it to 16 + } else if (fpsy >= 16 && fpsy <= 18) { + fpsy = 19; // If psychic talent is between 16 and 18, increase it to 19 + } + } + + // Apply Favoured Language bonus + if (favoured_language) { + flks += 1; + } + + + + // Update final attributes + setAttrs({ + finalstrength: fstr, + finalreflexes: fref, + finalintelligence: fint, + finalpsychictalent: fpsy, + finallooks: flks + }); + }); +}); + +// Handle changes to the Secondary Skill Name +on('change:repeating_secondaryskills:secondaryskill', function(event) { + if (event.sourceType === 'sheetworker') return; + + const skillDescriptions = { + "Artist": "At basic level, a character can draw simple, childlike pictures and maps. At intermediate level, she can draw quick, expert sketches of whatever is in front of her. At advanced level, a character's drawing skills increase, and she can also be capable of working with other media such as stone or wood.", + "Blacksmith": "At basic level, a character can act as a blacksmith’s assistant, shovelling coal and occasionally being permitted to swing a large hammer (under careful instruction). At intermediate level, he can make nails, ploughs, simple knives and tools, and horseshoes, as well as shoe a horse. At advanced level, he can forge (non-magical) weapons and armour.", + "Builder": "At basic level, a character can make a simple overnight shelter of branches or reeds. At intermediate level, he can make a house of wattle and daub, or a simple hut of wood. At advanced level, he can build in stone, including making complex structures such as churches or castles.", + "Cavalry": "At basic level, a character can mount a trained horse (perhaps with some assistance) and ride it along a road or track, in the daytime while at a walk; she can also muck out a stable. At intermediate level, she can also ride at an amble, trot, canter, or gallop, and jump a horse over small obstacles; groom and feed a horse; and set up a saddle, bit, bridle, and other gear appropriately. She can also lead a group of horses and riders at an amble or trot, even if some of the riders only have basic skill. At the advanced level, given time, she can catch, break, and train a wild horse. The Advanced level also allows her to ride a trained warhorse into battle and have it fight under her control. For PCs, advanced riding is solely the domain of Knights, Barbarians, and Warlocks. It is not possible to learn this level of control outside of these professions as a PC. NPCs without professions can learn the Advanced level of Cavalry as though it were any other skill.", + "Farmer": "At basic level, a character can dig a ditch or hole, and feed and water animals. At intermediate level, she can also milk cows, shear sheep, catch chickens, and sow and reap all kinds of crops. At advanced level, she can treat simple, common ailments in farm animals, build and repair fences and gates, evaluate the optimal farming potential of a plot of land, make cheese, butter, and cream, and plan simple crop rotation.", + "Goldsmith": "At basic level, a character can act as a goldsmith’s assistant, shovelling coal and occasionally being permitted to tend crucibles of molten metal (under careful instruction). At intermediate level, she can work with semi-precious metals to make simple jewellery and decorative items. At advanced level, she can work with gold and silver, too, and set gems into her pieces.", + "Leatherworker": "At basic level, a character can make simple repairs to leatherwork, using either needle and thread, or rivets. At intermediate level, she can make simple leather goods such as pouches, holders, or bags, assuming she has plenty of leather and other materials. At advanced level, she can make leather clothing and armour, as well as tanning any hides she may have acquired.", + "Merchant": "At basic level, a character knows the typical prices and availabilities of the weapons, armour, and other goods listed in the main rulebook, as well as being able to count and do basic mathematics; addition and subtraction, so long as the sums involved are no more than double figures. At intermediate level, she can do advanced mathematics, including accounting and calculating interest on loans; she can evaluate the worth of any non-magical goods, including taking into account their condition and age, and their different values at retail, wholesale, second-hand, etc.; and she can negotiate a 5% discount on all purchases. At advanced level, her discount increases to 10%, and she can run a successful business as a money-lender or a merchant, and can evaluate the worth (in Florins) of magical items, so long as she knows their precise properties and capabilities.", + "Miner": "At basic level, a character can dig clay out of a riverbed and identify common stone types. At intermediate level, she can mine for various kinds of stone, and (under instruction), ore, and have a good sense of direction underground. At advanced level, she can safely prop up mine tunnels, identify ores and veins by sight, and plan and carry out undermining of enemy fortifications.", + "Priest": "At basic level, a character knows the Commandments and a couple of standard prayers. At intermediate level, she can lead a basic religious service—including officiating at births, marriages, and deaths—and knows many prayers, with a reasonable knowledge of the tales of the True Faith. At advanced level, she can officiate at all religious rituals, debate fine theological points, and create excellent illuminated manuscripts (in any language she can write) by copying existing ones.", + "Sailor": "At basic level, a character can row a small boat in calm waters without significant risk of capsizing. At intermediate level, he can also carry out all the shipboard tasks of a professional sailor, including casting off, rowing as part of a team, gauging depth, predicting the weather (at sea, only, 60% chance to predict the weather for the next 8 hours), dropping and weighing anchor, towing, knots and ropework, operating sails, and simple sewing. At advanced level, his weather prediction chance increases to 85%, and he can navigate, pilot a ship around any ports and seas he knows well, and captain ships of any size.", + "Shipwright": "At basic level, a character can make a simple raft, given suitable tools and materials. At intermediate level, she can build small riverboats or coracles, assist an advanced shipwright in building a larger ship, and repair minor damage at sea. At advanced level, she can build, repair, maintain, and overhaul full-sized ships of all kinds.", + "Survival": "At basic level, a character can gather suitable firewood, and start and maintain a campfire in good weather. At intermediate level, she can start and maintain a fire in poor weather, as well as gathering plant foods and setting simple snares and traps to catch small animals, and, if near water, fishing. At advanced level, she can track, skin, and prep prey animals and humans (as per the Track talent), as well as being able to train and command hunting animals (other than horses) such as hounds and falcons.", + "Tailor": "At basic level, a character can make simple repairs to clothing, if he has a needle and thread. At intermediate level, he can make simple, non-fitted clothing. At advanced level, he can make more complex clothing, fabric armour, uniforms, and even banners." + }; + + const skillName = event.newValue; + const description = skillDescriptions[skillName] || ''; // Set description or leave blank for custom skills + const repeatingId = event.sourceAttribute.split('_')[2]; + + setAttrs({ + [`repeating_secondaryskills_${repeatingId}_secondaryskilldescription`]: description + }); +}); + +on("clicked:repeating_meleeweapons:equippedmeleewep", function(eventInfo) { + // Get the row ID of the clicked button + const rowId = eventInfo.triggerName.split('_')[2]; + + getSectionIDs('repeating_meleeweapons', function(ids) { + const output = {}; // Initialize 'output' here + + ids.forEach(function(id) { + output[`repeating_meleeweapons_${id}_hide`] = (id == rowId) ? 1 : 0; + }); + + // Define the fields to retrieve from the current row + const fields = [ + `repeating_meleeweapons_${rowId}_meleeweaponname`, + `repeating_meleeweapons_${rowId}_meleeweapon`, + `repeating_meleeweapons_${rowId}_magicmeleeweaponbonus`, + `repeating_meleeweapons_${rowId}_meleeabr`, + `repeating_meleeweapons_${rowId}_meleedamage`, + `repeating_meleeweapons_${rowId}_meleeothereffects` + ]; + + // Get the attributes of the current row + getAttrs(fields, function(values) { + // Add the equipped weapon attributes to the existing 'output' object + output.equippedmeleeweaponname = values[`repeating_meleeweapons_${rowId}_meleeweaponname`] || "Unnamed"; + output.equippedmeleeweapontype = values[`repeating_meleeweapons_${rowId}_meleeweapon`] || ""; + output.equippedmeleeweaponmagicbonus = parseInt(values[`repeating_meleeweapons_${rowId}_magicmeleeweaponbonus`]) || 0; + output.equippedmeleeweaponabr = values[`repeating_meleeweapons_${rowId}_meleeabr`] || "0d0"; + output.equippedmeleeweapondamage = values[`repeating_meleeweapons_${rowId}_meleedamage`] || "0"; + output.equippedmeleeweaponother = values[`repeating_meleeweapons_${rowId}_meleeothereffects`] || "No other effects"; + + setAttrs(output); + }); + }); +}); + +on('change:unarmed_combat change:oak_fists change:repeating_meleeweapons', function(event) { + getSectionIDs('repeating_meleeweapons', function(ids) { + const id = event.sourceAttribute.split('_')[2]; + + // Retrieve attributes and ensure unarmed_combat and oak_fists are set to 0 if unchecked + getAttrs(['unarmed_combat', 'oak_fists', event.sourceAttribute], function(v) { + let weaponName = v[`repeating_meleeweapons_${id}_meleeweapon`] || ''; + let unarmed_combatActive = parseInt(v['unarmed_combat']) || 0; + let oak_fistsActive = parseInt(v['oak_fists']) || 0; + + // Ensure unarmed_combat is set to 0 if unchecked + if (v['unarmed_combat'] !== "1") { + setAttrs({ unarmed_combat: "0" }); + unarmed_combatActive = 0; + } + + // Ensure oak_fists is set to 0 if unchecked + if (v['oak_fists'] !== "1") { + setAttrs({ oak_fists: "0" }); + oak_fistsActive = 0; + } + + // Initialize weapon options + const weaponOptions = { + "Battleaxe": {abr: "d8", damage: "6", warlockweapongroupmelee: 5}, + "Cudgel": {abr: "d3", damage: "3", warlockweapongroupmelee: 8}, + "Dagger": {abr: "d4", damage: "3", warlockweapongroupmelee: 2}, + "Flail": {abr: "d6", damage: "4", warlockweapongroupmelee: 1}, + "Halberd": {abr: "d10", damage: "5", warlockweapongroupmelee: 3}, + "Mace": {abr: "d6", damage: "4", warlockweapongroupmelee: 1}, + "Morning star": {abr: "d6", damage: "5", warlockweapongroupmelee: 1}, + "Shortsword": {abr: "d8", damage: "3", warlockweapongroupmelee: 2}, + "Spear": {abr: "2d4", damage: "4", warlockweapongroupmelee: 3}, + "Staff": {abr: "d6", damage: "3", warlockweapongroupmelee: 3}, + "Sword": {abr: "d8", damage: "4", warlockweapongroupmelee: 2}, + "Two-handed sword": {abr: "d10", damage: "5", warlockweapongroupmelee: 4}, + "Unarmed combat": {abr: "d3", damage: "2", warlockweapongroupmelee: 8}, + "Footman’s Flail": {abr: "d6", damage: "5", warlockweapongroupmelee: 3}, + "Holy Water Sprinkler": {abr: "d6", damage: "5", warlockweapongroupmelee: 1}, + "Longsword": {abr: "2d4", damage: "4", warlockweapongroupmelee: 4}, + "Pollaxe": {abr: "d12", damage: "4", warlockweapongroupmelee: 3}, + "Scourge": {abr: "d2", damage: "3", warlockweapongroupmelee: 3}, + "War Axe": {abr: "d6", damage: "5", warlockweapongroupmelee: 5}, + "Warhammer": {abr: "d10", damage: "3", warlockweapongroupmelee: 5}, + "War Lance": {abr: "2d4", damage: "6", warlockweapongroupmelee: 3}, + }; + + // Override if Unarmed Combat or Oak Fists is selected and active + if ((weaponName === 'Unarmed combat' && unarmed_combatActive === 1) || (weaponName === 'Unarmed combat' && oak_fistsActive === 1)) { + weaponOptions[weaponName] = {abr: "d6", damage: "3", warlockweapongroupmelee: 8, ismaingauchedefenceweapon: 0}; + } + + // Apply the abr, damage, warlockweapongroupmelee, and ismaingauchedefenceweapon dynamically based on the weapon + if (weaponOptions[weaponName]) { + const { abr, damage, warlockweapongroupmelee, ismaingauchedefenceweapon } = weaponOptions[weaponName]; + setAttrs({ + [`repeating_meleeweapons_${id}_meleeabr`]: abr, + [`repeating_meleeweapons_${id}_meleedamage`]: damage, + [`repeating_meleeweapons_${id}_warlockweapongroupmelee`]: warlockweapongroupmelee, + [`repeating_meleeweapons_${id}_ismaingauchedefenceweapon`]: ismaingauchedefenceweapon + }); + } + }); + }); +}); + +on("clicked:repeating_rangedweapons:equippedrangedwep", function(eventInfo) { + // Get the row ID of the clicked button + const rowId = eventInfo.triggerName.split('_')[2]; + + getSectionIDs('repeating_rangedweapons', function(ids) { + const output = {}; // Initialize 'output' here + + ids.forEach(function(id) { + output[`repeating_rangedweapons_${id}_hide`] = (id == rowId) ? 1 : 0; + }); + + // Define the fields to retrieve from the current row + const fields = [ + `repeating_rangedweapons_${rowId}_rangedweapon_name`, + `repeating_rangedweapons_${rowId}_rangedweapon`, + `repeating_rangedweapons_${rowId}_magicrangedweaponbonus`, + `repeating_rangedweapons_${rowId}_rangedabr`, + `repeating_rangedweapons_${rowId}_rangeddamage`, + `repeating_rangedweapons_${rowId}_weaponshortrange`, + `repeating_rangedweapons_${rowId}_weaponmediumrange`, + `repeating_rangedweapons_${rowId}_weaponlongrange` + ]; + + // Get the attributes of the current row + getAttrs(fields, function(values) { + // Add the equipped weapon attributes to the existing 'output' object + output.equippedrangedweaponname = values[`repeating_rangedweapons_${rowId}_rangedweapon_name`] || "Unnamed"; + output.equippedrangedweapontype = values[`repeating_rangedweapons_${rowId}_rangedweapon`] || ""; + output.equippedrangedweaponmagicbonus = values[`repeating_rangedweapons_${rowId}_magicrangedweaponbonus`] || 0; + output.equippedrangedweaponabr = values[`repeating_rangedweapons_${rowId}_rangedabr`] || "0d0"; + output.equippedrangedweapondamage = values[`repeating_rangedweapons_${rowId}_rangeddamage`] || 0; + output.equippedrangedweaponshortrange = values[`repeating_rangedweapons_${rowId}_weaponshortrange`] || 0; + output.equippedrangedweaponmediumrange = values[`repeating_rangedweapons_${rowId}_weaponmediumrange`] || 0; + output.equippedrangedweaponlongrange = values[`repeating_rangedweapons_${rowId}_weaponlongrange`] || 0; + + // Set the output attributes + setAttrs(output); + }); + }); +}); + +on('change:repeating_rangedweapons', function(event) { + if (event.sourceType === 'sheetworker') return; + + const weaponOptions = { + "Arbalest": {abr: "d12", damage: "5", short: "50", medium: "250", long: "450", group: 7}, + "Longbow": {abr: "d8", damage: "4", short: "50", medium: "150", long: "300", group: 6}, + "Bow": {abr: "d6", damage: "4", short: "50", medium: "125", long: "250", group: 6}, + "Crossbow": {abr: "d10", damage: "4", short: "25", medium: "75", long: "250", group: 7}, + "Dagger": {abr: "d3", damage: "3", short: "10", medium: "20", long: "25", group: 2}, + "Javelin": {abr: "d8", damage: "4", short: "15", medium: "25", long: "35", group: 7}, + "Rock": {abr: "d3", damage: "2", short: "10", medium: "15", long: "20", group: 7}, + "Sling": {abr: "d6", damage: "3", short: "25", medium: "75", long: "100", group: 7}, + "Throwing Spike": {abr: "d2", damage: "2", short: "10", medium: "20", long: "25", group: 7} + }; + + const id = event.sourceAttribute.split('_')[2]; + const weaponName = event.newValue; + + if (weaponOptions[weaponName]) { + const { abr, damage, short, medium, long, group } = weaponOptions[weaponName]; + setAttrs({ + [`repeating_rangedweapons_${id}_rangedabr`]: abr, + [`repeating_rangedweapons_${id}_rangeddamage`]: damage, + [`repeating_rangedweapons_${id}_weaponshortrange`]: short, + [`repeating_rangedweapons_${id}_weaponmediumrange`]: medium, + [`repeating_rangedweapons_${id}_weaponlongrange`]: long, + [`repeating_rangedweapons_${id}_warlockweapongroupranged`]: group + }); + } +}); + +// Function to calculate Armour Factor (AF) and penalties based on Armour Type and Profession +on("change:panoply_activate change:armourtype change:baseaf change:profession change:soldier change:magicafbonus change:miscaf change:armour_spell", function() { + getAttrs(['baseaf', 'armourtype', 'profession', 'soldier', 'magicafbonus', 'miscaf', 'armour_spell','panoply_activate'], function(values) { + let af = 0; + let attackPenalty = 0; + let defencePenalty = 0; + let totalaf = 0; + let armourSpell = values.armour_spell === "1"; + let panoplyActivate = values.panoply_activate === "1"; + + const profession = values.profession; + const armourtype = values.armourtype; + const soldierSkill = values.soldier === "1"; + const magicafbonus = parseInt(values.magicafbonus, 10) || 0; + const miscaf = parseInt(values.miscaf, 10) || 0; + + // Determine Armour Factor (AF) - prioritize list values + if (["None"].includes(armourtype)) { + af = 0; + } else if ([ + "Quilted Jacket", + "Heavy Cloth Jacket", + "Gambeson", + "Soft Leather Jacket", + "Padded Armour Coat", + "Padded Armour", + "Thick Leather Jacket", + "Woven Cord Cuirass", + "Boiled Leather Cuirass" + ].includes(armourtype)) { + af = 1; + } else if ([ + "Crown Jacket", + "Ring Jacket", + "Mail Vest" + ].includes(armourtype)) { + af = 2; + } else if ([ + "Mail Hauberk", + "Scale Hauberk", + "Jezeraint" + ].includes(armourtype)) { + af = 3; + } else if ([ + "Lamellar", + "Brigandine", + "Plate Cuirass", + "Mail Armour", + "Scale Coat", + "Double Mail Hauberk" + ].includes(armourtype)) { + af = 4; + } else if ([ + "Plate Armour", + "Banded Armour" + ].includes(armourtype)) { + af = 5; + } else { + // If armourtype is NOT on the list, use the baseaf value + af = parseInt(values.baseaf, 10) || 0; + } + + // ... (rest of your penalty calculations based on profession) ... + + // Calculate total Armour Factor (AF) + totalaf = af + magicafbonus + miscaf; + + // Calculate penalties based on profession + if (profession === "Barbarian" || profession === "Warlock") { + if (af === 5) { + attackPenalty = 2; + defencePenalty = 2; + } + } else if (["Assassin", "Knave", "Hunter", "Priest", "Mystic"].includes(profession)) { + if (af === 4) { + attackPenalty = 2; + defencePenalty = 2; + } else if (af === 5) { + attackPenalty = 4; + defencePenalty = 4; + } + } else if (["Elementalist", "Demonologist", "Sorcerer"].includes(profession)) { + if (af === 3) { + attackPenalty = 1; + defencePenalty = 1; + } else if (af === 4) { + attackPenalty = 3; + defencePenalty = 3; + } else if (af === 5) { + attackPenalty = 4; + defencePenalty = 4; + } + } + + // Adjust penalties for Hunter with Soldier skill + if (profession === "Hunter" && soldierSkill) { + if (af === 5) { + attackPenalty = 2; + defencePenalty = 2; + } + } + + // Set penalties to 0 for Knight + if (profession === "Knight") { + attackPenalty = 0; + defencePenalty = 0; + } + + // Calculate total Armour Factor (AF) + totalaf = af + magicafbonus + miscaf; + + if (panoplyActivate) { + totalaf +=2; + } + + if (armourSpell) { + totalaf = 6; + } + + // Set calculated attributes + setAttrs({ + baseaf: af, + armourattackpenalty: attackPenalty, + armourdefencepenalty: defencePenalty, + totalaf: totalaf + }); + }); +}); + +// Function to calculate encumbrance +on('change:repeating_inventoryitems change:gc change:sf change:cp change:strength', function() { + getSectionIDs('repeating_inventoryitems', function(ids) { + const fields = ['gc', 'sf', 'cp', 'strength']; + + // Include all inventory items' encumbrance values, quantities, and locations in the fields array + ids.forEach(id => { + fields.push(`repeating_inventoryitems_${id}_encumbranceValue`); + fields.push(`repeating_inventoryitems_${id}_inventoryqty`); + fields.push(`repeating_inventoryitems_${id}_itemLocation`); + }); + + getAttrs(fields, function(values) { + // Parse values as floats to handle fractions + const crowns = parseFloat(values.gc) || 0; + const florins = parseFloat(values.sf) || 0; + const pennies = parseFloat(values.cp) || 0; + const strength = parseFloat(values.strength) || 0; + + let totalEncumbrance = 0; + + // Calculate encumbrance from inventory items + ids.forEach(id => { + const location = values[`repeating_inventoryitems_${id}_itemLocation`] || "On person"; + const encumbranceValue = parseFloat(values[`repeating_inventoryitems_${id}_encumbranceValue`]) || 0; + const quantity = parseFloat(values[`repeating_inventoryitems_${id}_inventoryqty`]) || 0; + + // Only add to total encumbrance if the item is "On person" + if (location === "On person") { + totalEncumbrance += encumbranceValue * quantity; + } + }); + + // Calculate encumbrance from coins + const totalCoins = crowns + florins + pennies; + totalEncumbrance += Math.floor(totalCoins / 150); + + // Determine maximum encumbrance based on strength + let maxEncumbrance = 0; + if (strength >= 16) maxEncumbrance = 14; + else if (strength >= 13) maxEncumbrance = 12; + else if (strength >= 9) maxEncumbrance = 10; + else if (strength >= 6) maxEncumbrance = 8; + else if (strength >= 3) maxEncumbrance = 6; + + // Set the calculated values + setAttrs({ + totalencumbrance: totalEncumbrance, + maxenc: maxEncumbrance + }); + }); + }); +}); + +on("clicked:repeating_ammo:equippedammo", function(eventInfo) { + // Get the row ID of the clicked button + const rowId = eventInfo.triggerName.split('_')[2]; + + getSectionIDs('repeating_ammo', function(ids) { + const output = {}; // Initialize 'output' here + + ids.forEach(function(id) { + output[`repeating_ammo_${id}_hide`] = (id == rowId) ? 1 : 0; + }); + + // Define the fields to retrieve from the current row + const fields = [ + `repeating_ammo_${rowId}_ammotype_name`, + `repeating_ammo_${rowId}_ammotype`, + `repeating_ammo_${rowId}_ammoqty`, + `repeating_ammo_${rowId}_magicammobonus`, + `repeating_ammo_${rowId}_specialammomodifier`, + `repeating_ammo_${rowId}_specialammoabrmodifier`, + `repeating_ammo_${rowId}_specialammodmgmodifier`, + `repeating_ammo_${rowId}_specialeffect` + ]; + + // Get the attributes of the current row + getAttrs(fields, function(values) { + // Add the equipped ammo attributes to the existing 'output' object + output.equippedammoname = values[`repeating_ammo_${rowId}_ammotype_name`] || ""; + output.equippedammotype = values[`repeating_ammo_${rowId}_ammotype`] || ""; + output.equippedammoqty = values[`repeating_ammo_${rowId}_ammoqty`] || 0; + output.equippedammomagicbonus = values[`repeating_ammo_${rowId}_magicammobonus`] || 0; + output.equippedammoattackmod = values[`repeating_ammo_${rowId}_specialammomodifier`] || 0; + output.equippedammoabrmod = values[`repeating_ammo_${rowId}_specialammoabrmodifier`] || 0; + output.equippedammodmgmod = values[`repeating_ammo_${rowId}_specialammodmgmodifier`] || 0; + output.equippedammospecialeffect = values[`repeating_ammo_${rowId}_specialeffect`] || "None"; + + // Set the output attributes + setAttrs(output); + }); + }); +}); + +on('change:repeating_ammo change:profession', function(event) { + if (event.sourceType === 'sheetworker') return; + + const id = (event.sourceAttribute.split('_')[2] || '').toLowerCase(); + const fieldName = event.sourceAttribute.split('_')[3]; + + getAttrs([`profession`, `repeating_ammo_${id}_ammotype`], function(values) { + const profession = values.profession || 'None'; + const ammoType = values[`repeating_ammo_${id}_ammotype`] || 'Regular Ammunition'; + + const ammoOptions = { + "Regular Ammunition": { attack: 0, abr: 0, damage: 0, specialeffects: "" }, + "Blunt Arrows": { + attack: -4, abr: -2, damage: -2, + specialeffect: "Non-lethal missile requiring a specially constructed padded arrowhead without any cutting edge. Cost to produce 6 arrows: 4 Florins" + }, + "Forked Arrows": { + attack: -2, abr: -1, damage: 1, + specialeffect: "Flesh cutting missile requiring a specially forged wide bladed and multi-pronged arrowhead. Cost to produce 6 arrows: 8 Florins" + }, + "Bodkin Arrows": { + attack: -1, abr: 1, damage: -1, + specialeffect: "Armour-piercing missile requiring a specially forged narrow hardened-steel arrowhead. Cost to produce 6 arrows: 6 Florins" + }, + "Fire Arrows": { + attack: -3, abr: -2, damage: 0, + specialeffect: "Flammable missile requiring a specially constructed flammable cloth/steel arrowhead. Sets target alight on a successful hit, dealing a further 4HP damage per round until the fire is put out. Cost to produce 6 arrows: 4 Florins" + }, + "Wooden Arrows": { + attack: -2, abr: -1, damage: 0, + specialeffect: "Has a simple fire-hardened point rather than steel. Can be made by a Hunter out in the wilderness without any cost" + }, + "Flint Arrows": { + attack: -1, abr: -1, damage: 0, + specialeffect: "May be made by a Hunter in the wilderness using sharp minerals like obsidian. Requires more time to make than wooden arrows" + } + }; + + let modifiers = ammoOptions[ammoType] || ammoOptions["Regular Ammunition"]; + + if (profession === 'Hunter') { + if (ammoType === "Blunt Arrows") { + modifiers = { + attack: -3, abr: -2, damage: -2, + specialeffect: "Non-lethal missile requiring a specially constructed padded arrowhead without any cutting edge. Cost to produce 6 arrows: 4 Florins" + }; + } else if (ammoType === "Forked Arrows") { + modifiers = { + attack: -1, abr: -1, damage: 1, + specialeffect: "Flesh cutting missile requiring a specially forged wide bladed and multi-pronged arrowhead. Cost to produce 6 arrows: 8 Florins" + }; + } else if (ammoType === "Bodkin Arrows") { + modifiers = { + attack: 0, abr: 1, damage: -1, + specialeffect: "Armour-piercing missile requiring a specially forged narrow hardened-steel arrowhead. Cost to produce 6 arrows: 6 Florins" + }; + } else if (ammoType === "Fire Arrows") { + modifiers = { + attack: -2, abr: -2, damage: 0, + specialeffect: "Flammable missile requiring a specially constructed flammable cloth/steel arrowhead. Sets target alight on a successful hit, dealing a further 4HP damage per round until the fire is put out. Cost to produce 6 arrows: 4 Florins" + }; + } else if (ammoType === "Wooden Arrows") { + modifiers = { + attack: -1, abr: -1, damage: 0, + specialeffect: "Has a simple fire-hardened point rather than steel. Can be made by a Hunter out in the wilderness without any cost" + }; + } else if (ammoType === "Flint Arrows") { + modifiers = { + attack: 0, abr: -1, damage: 0, + specialeffect: "May be made by a Hunter in the wilderness using sharp minerals like obsidian. Requires more time to make than wooden arrows" + }; + } + } + + setAttrs({ + [`repeating_ammo_${id}_specialammomodifier`]: modifiers.attack, + [`repeating_ammo_${id}_specialammoabrmodifier`]: modifiers.abr, + [`repeating_ammo_${id}_specialammodmgmodifier`]: modifiers.damage, + [`repeating_ammo_${id}_specialeffect`]: modifiers.specialeffect + }); + }); +}); + +const woundValues = Array.from({ length: 51 }, (_, i) => i.toString()); +const wtwoundValues = ["0", "1", "2", "3"]; + +// Function to handle wound changes +function handleWoundChange(value) { + on(`clicked:wound_${value}`, function() { + getAttrs(["wtwound", "wound", "maxhp", "input_wounds"], function(v) { + let currentWound = parseInt(v.wound) || 0; + let wnd = parseInt(value); + let wtwnd = parseInt(v.wtwound) || 0; + let maxhp = parseInt(v.maxhp); + let chp = maxhp - wnd - wtwnd; + + // Check if wounds were at or above maxhp and now become equal to or less than maxhp + let wasAtOrAboveMaxhp = currentWound >= maxhp; + let willBeAtOrBelowMaxhp = wnd <= maxhp; + + if (wasAtOrAboveMaxhp && willBeAtOrBelowMaxhp && wtwnd > 0) { + // If conditions are met, reset wtwound to 0 + setAttrs({ + wound: wnd, + wtwound: 0, + currenthp: maxhp - wnd, + currenthp_max: maxhp, + input_wounds: wnd + }); + } else if (currentWound === 0) { + // If current value is 0, set wound to the clicked button's value + setAttrs({ + wound: wnd, + currenthp: chp, + currenthp_max: maxhp, + input_wounds: wnd + }); + } else if (currentWound === 1 && value === "1") { + // If current value is 1 and first button is clicked, reset to 0 + setAttrs({ + wound: 0, + currenthp: maxhp - 0 - wtwnd, + currenthp_max: maxhp, + input_wounds: 0 + }); + } else { + // If current value is greater than 1 or any other button is clicked + setAttrs({ + wound: wnd, + currenthp: chp, + currenthp_max: maxhp, + input_wounds: wnd + }); + } + }); + }); +} + +// Function to handle wound tolerance changes for wtwound +function handleWtWoundChange(value) { + on(`clicked:wtwound_${value}`, function() { + getAttrs(["wtwound", "maxhp", "wound", "input_wounds"], function(v) { + let currentWtWound = parseInt(v.wtwound) || 0; + let maxhp = parseInt(v.maxhp) || 0; + let wtw = parseInt(value) || 0; + let currentWound = parseInt(v.wound) || 0; + + if (currentWound < maxhp && wtw > 0) { + // If wounds are less than maxhp and wtwound is filled + setAttrs({ + wtwound: wtw, + wound: maxhp, // Set wounds to maxhp + currenthp: maxhp - maxhp - wtw, // Adjust for full wounds + currenthp_max: maxhp, + input_wounds: maxhp + wtw + }); + } else if (currentWtWound === 0) { + // If current value is 0, set wtwound to the clicked button's value + setAttrs({ + wtwound: wtw, + currenthp: maxhp - currentWound - wtw, + currenthp_max: maxhp, + input_wounds: currentWound + wtw + }); + } else if (currentWtWound === 1 && value === "1") { + // If current value is 1 and first button is clicked, reset to 0 + setAttrs({ + wtwound: 0, + currenthp: maxhp - currentWound - 0, + currenthp_max: maxhp, + input_wounds: currentWound + }); + } else { + // If current value is greater than 1 or any other button is clicked + setAttrs({ + wtwound: wtw, + currenthp: maxhp - currentWound - wtw, + currenthp_max: maxhp, + input_wounds: currentWound + wtw + }); + } + }); + }); +} + +// Input field change handler +on("change:input_wounds", function(event) { + let inputValue = parseInt(event.newValue) || 0; + getAttrs(["wound", "wtwound", "maxhp"], function(v) { + let currentWound = parseInt(v.wound) || 0; + let currentWtWound = parseInt(v.wtwound) || 0; + let maxhp = parseInt(v.maxhp) || 0; + + if (inputValue > maxhp + 3) { + setAttrs({ + wound: maxhp, + wtwound: inputValue - maxhp, + currenthp: 0, + currenthp_max: maxhp, + input_wounds: inputValue + }); + } else if (inputValue > maxhp) { + setAttrs({ + wound: maxhp, + wtwound: inputValue - maxhp, + currenthp: maxhp - maxhp - (inputValue - maxhp), + currenthp_max: maxhp, + input_wounds: inputValue + }); + } else { + setAttrs({ + wound: inputValue, + wtwound: 0, + currenthp: maxhp - inputValue, + currenthp_max: maxhp, + input_wounds: inputValue + }); + } + }); +}); + +// Wound Reset Handler +on("clicked:wound_reset", function() { + getAttrs(["maxhp"], function(v) { + const maxhp = parseInt(v.maxhp) || 0; // Default to 0 if maxhp is undefined + setAttrs({ + wound: 0, + wtwound: 0, + currenthp: maxhp, + input_wounds: 0 + }); + }); +}); + +// Attach event listeners +woundValues.forEach(handleWoundChange); +wtwoundValues.forEach(handleWtWoundChange); + +// Function to handle primary mana usage changes with enhanced logic +function handlePrimaryManaUsageChange(values) { + values.forEach(function(value) { + on(`clicked:manaused_${value}`, function() { + getAttrs(["maxmp", "currentmp", "manaused"], function(v) { + let used = parseInt(value); + let maxMp = parseInt(v.maxmp); + let currentMp = parseInt(v.currentmp) || maxMp; // Default to maxMp if currentMp is not defined + + // Implementing the new logic based on the current value + if (currentMp === 0) { + // If current value is 0, set mana to the clicked button's value + currentMp = used; + } else if (currentMp === 1 && value === "1") { + // If current value is 1 and first button is clicked, reset to 0 + currentMp = 0; + used = 0; // Update used value to 0 + } else { + // If current value is greater than 1 or any other button is clicked + currentMp = used; + } + + setAttrs({ + currentmp: currentMp, + maxmp: maxMp, + manaused: used + }); + }); + }); + }); +} + +// Define primary mana usage values +const primaryManaValues = Array.from({ length: 51 }, (_, i) => i.toString()); + +// Attach event listeners for primary mana usage +handlePrimaryManaUsageChange(primaryManaValues); + +// Function to handle primary mana input changes +function handlePrimaryManaInputChange() { + on(`change:inputmanaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + getAttrs(["maxmp"], function(v) { + let maxMp = parseInt(v.maxmp) || 0; + let currentMp = maxMp - used; + + setAttrs({ + currentmp: currentMp, + manaused: used + }, {silent: true}); + }); + }); +} + +// Attach event listener for primary mana input +handlePrimaryManaInputChange(); + +// Ensure input box is updated correctly when primary mana radio buttons change +function updatePrimaryInputBox() { + on(`change:manaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + setAttrs({ + inputmanaused: used + }, {silent: true}); + }); +} + +updatePrimaryInputBox(); + +// MP Reset Handler for primary mana +on("clicked:mp_reset", function() { + getAttrs(["maxmp"], function(v) { + const maxmp = parseInt(v.maxmp) || 0; + setAttrs({ + manaused: 0, + currentmp: maxmp, + inputmanaused: 0 + }); + }); +}); + +// Function to handle secondary mana usage changes with enhanced logic +function handleSecondaryManaUsageChange(values) { + values.forEach(function(value) { + on(`clicked:secmanaused_${value}`, function() { + getAttrs(["twomaxmp", "secmanaused", "currentmpelementtwo"], function(v) { + let used = parseInt(value); + let maxMp = parseInt(v.twomaxmp); + let currentMp = parseInt(v.currentmpelementtwo) || maxMp; // Default to maxMp if currentMp is not defined + + // Implementing the new logic based on the current value + if (currentMp === 0) { + // If current value is 0, set mana to the clicked button's value + currentMp = used; + } else if (currentMp === 1 && value === "1") { + // If current value is 1 and first button is clicked, reset to 0 + currentMp = 0; + used = 0; // Update used value to 0 + } else { + // If current value is greater than 1 or any other button is clicked + currentMp = used; + } + + setAttrs({ + currentmpelementtwo: currentMp, + twomaxmp: maxMp, + secmanaused: used + }); + }); + }); + }); +} + +// Define secondary mana usage values +const secondaryManaValues = Array.from({ length: 51 }, (_, i) => i.toString()); + +// Attach event listeners for secondary mana usage +handleSecondaryManaUsageChange(secondaryManaValues); + +// Function to handle secondary mana input changes +function handleSecondaryManaInputChange() { + on(`change:inputsecmanaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + getAttrs(["twomaxmp"], function(v) { + let maxMp = parseInt(v.twomaxmp) || 0; + let currentMp = maxMp - used; + + setAttrs({ + currentmpelementtwo: currentMp, + secmanaused: used + }, {silent: true}); + }); + }); +} + +// Attach event listener for secondary mana input +handleSecondaryManaInputChange(); + +// Ensure input box is updated correctly when secondary mana radio buttons change +function updateSecondaryInputBox() { + on(`change:secmanaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + setAttrs({ + inputsecmanaused: used + }, {silent: true}); + }); +} + +updateSecondaryInputBox(); + +// MP Reset Handler for secondary mana +on("clicked:secmp_reset", function() { + getAttrs(["twomaxmp"], function(v) { + const twomaxmp = parseInt(v.twomaxmp) || 0; + setAttrs({ + secmanaused: 0, + currentmpelementtwo: twomaxmp, + inputsecmanaused: 0 + }); + }); +}); + +// Function to handle tertiary mana usage changes with enhanced logic +function handleTertiaryManaUsageChange(values) { + values.forEach(function(value) { + on(`clicked:termanaused_${value}`, function() { + getAttrs(["threemaxmp", "termanaused", "currentmpelementthree"], function(v) { + let used = parseInt(value); + let maxMp = parseInt(v.threemaxmp); + let currentMp = parseInt(v.currentmpelementthree) || maxMp; // Default to maxMp if currentMp is not defined + + // Implementing the new logic based on the current value + if (currentMp === 0) { + // If current value is 0, set mana to the clicked button's value + currentMp = used; + } else if (currentMp === 1 && value === "1") { + // If current value is 1 and first button is clicked, reset to 0 + currentMp = 0; + used = 0; // Update used value to 0 + } else { + // If current value is greater than 1 or any other button is clicked + currentMp = used; + } + + setAttrs({ + currentmpelementthree: currentMp, + threemaxmp: maxMp, + termanaused: used + }); + }); + }); + }); +} + +// Define tertiary mana usage values +const tertiaryManaValues = Array.from({ length: 51 }, (_, i) => i.toString()); + +// Attach event listeners for tertiary mana usage +handleTertiaryManaUsageChange(tertiaryManaValues); + +// Function to handle tertiary mana input changes +function handleTertiaryManaInputChange() { + on(`change:inputtermanaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + getAttrs(["threemaxmp"], function(v) { + let maxMp = parseInt(v.threemaxmp) || 0; + let currentMp = maxMp - used; + + setAttrs({ + currentmpelementthree: currentMp, + termanaused: used + }, {silent: true}); + }); + }); +} + +// Attach event listener for tertiary mana input +handleTertiaryManaInputChange(); + +// Ensure input box is updated correctly when tertiary mana radio buttons change +function updateTertiaryInputBox() { + on(`change:termanaused`, function(event) { + const used = parseInt(event.newValue) || 0; + + setAttrs({ + inputtermanaused: used + }, {silent: true}); + }); +} + +updateTertiaryInputBox(); + +// MP Reset Handler for tertiary mana +on("clicked:termp_reset", function() { + getAttrs(["threemaxmp"], function(v) { + const threemaxmp = parseInt(v.threemaxmp) || 0; + setAttrs({ + termanaused: 0, + currentmpelementthree: threemaxmp, + inputtermanaused: 0 + }); + }); +}); + +on('change:rank change:profession', function() { + getAttrs(['rank'], function(values) { + const rank = parseInt(values.rank) || 0; // Default to 0 if rank is undefined + const psycfatcheck = rank + 13; + const esp = 5 + (rank * 3); + const prem = 35 + (rank * 2); + + setAttrs({ + pfc: psycfatcheck, + espchance: esp, + premonitionchance: prem + }); + }); +}); + +on('change:guardcurrent change:guardcountered change:expert_parryselect', function() { + getAttrs([ + 'mattackmoda', 'mdefencemoda', 'rattackmoda', 'rdefencemoda', 'evasionmod', 'othermodifications', + 'guardabrmodifier', 'guarddamagemodifier', 'shield', 'expert_parryselect', 'shieldsuccessvalue', + 'shielddievalue', 'guardcountered', 'finalmeleeattack', 'finalmeleedefence', 'finalrangedattack', + 'finalrangeddefence', 'evasion', 'guardcurrent' + ], function(values) { + const forms = { + Hawk: {mattackmoda: 1, mdefencemoda: -2, rattackmoda: 1, rdefencemoda: -2, evasionmod: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "If wielding a two-handed weapon: -1 Evasion and +1 Armour Penetration (please adjust manually)"}, + Snake: {mattackmoda: 1, mdefencemoda: -3, rattackmoda: 1, rdefencemoda: -3, evasionmod: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "Critical Hits do +1 HP damage (please adjust manually)"}, + Wolf: {mattackmoda: 2, mdefencemoda: -3, rattackmoda: 2, rdefencemoda: -3, evasionmod: -1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"}, + Bear: {mattackmoda: -2, mdefencemoda: 1, rattackmoda: -2, rdefencemoda: 1, evasionmod: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "+1 additional Defence for each opponent beyond the first (Please enter in the Miscellaneous Modifiers Section manually)"}, + Cat: {mattackmoda: -2, mdefencemoda: 1, rattackmoda: -2, rdefencemoda: 1, evasionmod: 1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "If using a shield: an additional -1 Attack and Shields block on a roll of 1 on 1d4 (these adjustments have been made for you)"}, + Crab: {mattackmoda: -2, mdefencemoda: 2, rattackmoda: -2, rdefencemoda: 2, evasionmod: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"}, + Neutral: {mattackmoda: 0, mdefencemoda: 0, rattackmoda: 0, rdefencemoda: 0, evasionmod: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"}, + Defensive: {mattackmoda: -2, mdefencemoda: 1, rattackmoda: -2, rdefencemoda: 1, evasionmod: 1, guarddamagemodifier: -1, guardabrmodifier: -1, othermodifications: "-1 Damage and -1 Armour Penetration (these adjustments have been made for you)"}, + Offensive: {mattackmoda: 1, mdefencemoda: -2, rattackmoda: 1, rdefencemoda: -2, evasionmod: -1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"} + }; + // Get current guard setting + let gua = values.guardcurrent || 'Neutral'; + + // Reset all guard modifiers to Neutral + const neutralForm = forms.Neutral; + setAttrs({ + 'mattackmoda': neutralForm.mattackmoda, + 'mdefencemoda': neutralForm.mdefencemoda, + 'rattackmoda': neutralForm.rattackmoda, + 'rdefencemoda': neutralForm.rdefencemoda, + 'evasionmod': neutralForm.evasionmod, + 'guardabrmodifier': neutralForm.guardabrmodifier, + 'guarddamagemodifier': neutralForm.guarddamagemodifier, + 'othermodifications': neutralForm.othermodifications + }, function() { + // Now apply the new guard settings + let output = forms[gua] || neutralForm; + + // Apply evasion modifiers + output.evasionmod += parseInt(values.evasion) || 0; + output.othermodifications = values.othermodifications || "None"; + + // Adjust evasion modifier if the guard is countered + if (values.guardcountered === '1') { + if (['Hawk', 'Snake', 'Wolf'].includes(gua)) { + output.mattackmoda -= 2; // Apply additional -2 to `mattackmoda` + output.rattackmoda -= 2; // Apply additional -2 to `rattackmoda` + } else if (['Crab', 'Cat', 'Bear'].includes(gua)) { + output.mdefencemoda -= 2; // Apply additional -2 to `mdefencemoda` + output.rdefencemoda -= 2; // Apply additional -2 to `rdefencemoda` + } + } + + // Shield settings + let shielddie = values.shielddievalue || '1d6'; + let shieldsuccess = parseInt(values.shieldsuccessvalue) || 1; + + if (values.expert_parryselect === '1') { + shielddie = '1d10'; + shieldsuccess = 2; + } else if (gua === "Cat" && parseInt(values.shield) === 1) { + shielddie = '1d4'; + shieldsuccess = 1; + } + + output.shielddievalue = shielddie; + output.shieldsuccessvalue = shieldsuccess; + + // Apply the new guard settings + setAttrs(output); + }); + }); +}); + +on('change:weaponskillselect change:weapon1 change:weapon2 change:weapon3 change:equippedammoabrmod change:equippedammodmgmod change:master_bowmanselect change:finalstrength change:miscabrmelee change:miscdamagemelee change:miscabrranged change:miscdamageranged change:equippedmeleeweaponmagicbonus change:equippedrangedweaponmagicbonus change:equippedammomagicbonus change:bloodrageselect change:guarddamagemodifier change:guardabrmodifier change:armour_piercing change:deathvowselect change:penetratingshotselect change:penetrating_shot change:cutting_power_of_the_mind_toggle', function(eventinfo) { + getAttrs([ + 'weaponskillselect', 'weapon1', 'weapon2', 'weapon3', + 'miscabrmelee', 'miscdamagemelee', 'miscabrranged', 'miscdamageranged', + 'equippedmeleeweaponmagicbonus', 'equippedrangedweaponmagicbonus', 'equippedammomagicbonus', + 'bloodrageselect', 'guarddamagemodifier', 'guardabrmodifier', 'finalstrength', 'master_bowmanselect', + 'equippedmeleeweapontype', 'equippedmeleeweaponabr', 'equippedmeleeweapondamage', + 'equippedrangedweapontype', 'rangedabr', 'rangeddamage', 'equippedammotype', + 'armour_piercing', 'deathvowselect', 'cutting_power_of_the_mind_toggle', 'primaryelement', + 'penetratingshotselect', 'penetrating_shot', 'equippedammoabrmod', 'equippedammodmgmod' + ], function(v) { + let weaponskillActive = parseInt(v['weaponskillselect']) || 0; + let equippedMeleeWeapon = v['equippedmeleeweapontype'] || ''; + let equippedRangedWeapon = v['equippedrangedweapontype'] || ''; + let equippedAmmoType = v['equippedammotype'] || ''; + let armour_piercingActive = parseInt(v['armour_piercing']) || 0; + let deathvowSelect = parseInt(v['deathvowselect']) || 0; + let penetratingShotActive = parseInt(v['penetratingshotselect']) || 0; + let penetratingShotValue = parseInt(v['penetrating_shot']) || 0; + let cuttingPower = parseInt(v['cutting_power_of_the_mind_toggle']) || 0; + let primaryelement = v['primaryelement'] || ''; + + let selectedWeapons = [ + v['weapon1'] || '', + v['weapon2'] || '', + v['weapon3'] || '' + ]; + + let miscMeleeABR = parseInt(v['miscabrmelee']) || 0; + let miscMeleeDmg = parseInt(v['miscdamagemelee']) || 0; + let miscRangedABR = parseInt(v['miscabrranged']) || 0; + let miscRangedDmg = parseInt(v['miscdamageranged']) || 0; + + let finalStrength = parseInt(v['finalstrength']) || 0; + + let specialAmmoABR = parseInt(v['equippedammoabrmod']) || 0; + let specialAmmoDamage = parseInt(v['equippedammodmgmod']) || 0; + + let magicMeleeABRBonus = parseInt(v['equippedmeleeweaponmagicbonus']) || 0; + let magicMeleeDmgBonus = magicMeleeABRBonus; + let magicRangedABRBonus = parseInt(v['equippedrangedweaponmagicbonus']) || 0; + let magicRangedDmgBonus = magicRangedABRBonus; + let magicAmmoABRBonus = parseInt(v['equippedammomagicbonus']) || 0; + let magicAmmoDmgBonus = magicAmmoABRBonus; + + let guardDamageMod = parseInt(v['guarddamagemodifier']) || 0; + let guardABRMod = parseInt(v['guardabrmodifier']) || 0; + + let bloodrage = parseInt(v['bloodrageselect']) || 0; + + // Calculate final attack and damage bonuses + let finalMeleeABRBonus = miscMeleeABR + magicMeleeABRBonus + guardABRMod; + let finalMeleeDmgBonus = miscMeleeDmg + magicMeleeDmgBonus + guardDamageMod; + let finalRangedABRBonus = miscRangedABR + magicRangedABRBonus + magicAmmoABRBonus + specialAmmoABR; + let finalRangedDmgBonus = miscRangedDmg + magicRangedDmgBonus + magicAmmoDmgBonus + specialAmmoDamage; + + // Apply Bloodrage damage modifier + if (bloodrage === 1) { + finalMeleeDmgBonus += 1; + } + + // Strength modifier for specific values of FinalStrength + if ([16, 17, 18].includes(finalStrength)) { + finalMeleeDmgBonus += 1; + finalMeleeABRBonus += 1; + finalRangedDmgBonus += 1; + finalRangedABRBonus += 1; + } else if (finalStrength > 18) { + finalMeleeDmgBonus += 2; + finalMeleeABRBonus += 2; + finalRangedDmgBonus += 2; + finalRangedABRBonus += 2; + } + + // Weaponskill modifier for melee weapons + if (weaponskillActive && selectedWeapons.includes(equippedMeleeWeapon)) { + finalMeleeABRBonus += 1; + } + + // Apply armour piercing bonus to specific melee and ranged weapons + if (armour_piercingActive === 1) { + const meleearmour_piercingWeapons = ['sword', 'staff', 'dagger', 'shortsword']; + const rangedarmour_piercingWeapon = 'throwing spike'; + + if (meleearmour_piercingWeapons.includes(equippedMeleeWeapon.toLowerCase())) { + finalMeleeABRBonus += 1; + } + + if (equippedRangedWeapon.toLowerCase() === rangedarmour_piercingWeapon) { + finalRangedABRBonus += 1; + } + } + + // Apply Penetrating Shot bonus if activated + if (penetratingShotActive === 1) { + finalRangedABRBonus += penetratingShotValue; + } + + let master_bowmanBonus = 0; + if (eventinfo.sourceType === "player" && (eventinfo.sourceAttribute.includes("master_bowmanselect") || eventinfo.sourceAttribute.includes("rangedweapon"))) { + let ismaster_bowmanActive = parseInt(v['master_bowmanselect']) || 0; + + if (ismaster_bowmanActive) { + let weaponName = equippedRangedWeapon.toLowerCase(); + + // Check if the weapon is "longbow", "bow", or any custom "bow" (but not "cross" in the name) + if ((weaponName === 'longbow' || weaponName === 'bow' || weaponName.includes('bow')) && !weaponName.includes('cross')) { + master_bowmanBonus = 1; + } + + finalRangedABRBonus += master_bowmanBonus; + } + } + + // Apply Death Vow bonus if deathvowselect is 1 + if (deathvowSelect === 1) { + finalMeleeABRBonus += 2; + finalMeleeDmgBonus += 2; + finalRangedABRBonus += 2; + finalRangedDmgBonus += 2; + } + + if (cuttingPower === 1 && primaryelement === "Darkness") { + finalRangedDmgBonus += 1; + } + + // Set final attributes + setAttrs({ + finalmeleeabrbonus: finalMeleeABRBonus, + finalmeleedmgbonus: finalMeleeDmgBonus, + finalrangedabrbonus: finalRangedABRBonus, + finalrangeddmgbonus: finalRangedDmgBonus + }); + }); +}); + +on('change:expert_parryselect', function() { + getAttrs(['expert_parryselect'], function(v) { + // Default values for shield die and success value + let shieldDie = '1d6'; // Default shield die value + let successValue = 1; // Default shield success value + + // Check if Expert Parry is selected + let expert_parryActive = v.expert_parryselect === '1'; + + if (expert_parryActive) { + // Modify shield die and success value based on Expert Parry skill + shieldDie = '1d10'; // Expert Parry changes the die to 1d10 + successValue = 2; // Expert Parry changes the success value to 2 + } + + // Set attributes + setAttrs({ + 'shielddievalue': shieldDie, + 'shieldsuccessvalue': successValue + }); + }); +}); + +on('change:profession change:rank change:warlockweapongroups change:meleeweapon change:equippedrangedweapontype', function() { + getAttrs([ + 'profession', 'rank', 'warlockweapongroups', 'weapon_group_1', 'weapon_group_2', + 'warlockweapongroupmelee', 'warlockweapongroupranged' + ], function(values) { + // Retrieve the values + let profession = values.profession || ''; + let rank = parseInt(values.rank) || 0; + let warlockWeaponGroups = parseInt(values.warlockweapongroups) || 0; + let weaponGroup1 = parseInt(values.weapon_group_1) || 0; + let weaponGroup2 = parseInt(values.weapon_group_2) || 0; + let warlockWeaponGroupMelee = parseInt(values.warlockweapongroupmelee) || 0; + let warlockWeaponGroupRanged = parseInt(values.warlockweapongroupranged) || 0; + + // Set default values to 0 + let nonProfMelee = 0; + let nonProfRanged = 0; + + if ((profession === 'warlock' && rank > 2) || warlockWeaponGroups === 1) { + if (warlockWeaponGroupMelee !== weaponGroup1 && warlockWeaponGroupMelee !== weaponGroup2) { + nonProfMelee = -2; + } + } + + if ((profession === 'warlock' && rank > 2) || warlockWeaponGroups === 1) { + if (warlockWeaponGroupRanged !== weaponGroup1 && warlockWeaponGroupRanged !== weaponGroup2) { + nonProfRanged = -2; + } + } + + // Set the attribute values + setAttrs({ + nonprofmelee: nonProfMelee, + nonprofranged: nonProfRanged + }); + }); +}); + +on("change:stealth change:miscstealth change:perception change:miscperception change:reflexes change:psychic_talent change:humanintuitionselect change:stillnesspos change:rank change:huntersmindactivate change:baseaf change:favoured_language", function() { + getAttrs([ + 'stealth', 'miscstealth', 'perception', 'miscperception', + 'reflexes', 'psychic_talent', 'humanintuitionselect', + 'stillnesspos', 'rank', 'huntersmindactivate', 'baseaf', 'favoured_language' + ], function(values) { + let stealth = parseInt(values.stealth) || 0; + let miscStealth = parseInt(values.miscstealth) || 0; + let perception = parseInt(values.perception) || 0; + let miscPerception = parseInt(values.miscperception) || 0; + let reflexes = parseInt(values.reflexes) || 0; + let psychicTalent = parseInt(values.psychic_talent) || 0; + let humanIntuitionSelect = parseInt(values.humanintuitionselect) || 0; + let stillnessPos = parseInt(values.stillnesspos) || 0; + let rank = parseInt(values.rank) || 0; + let huntersMindActive = values.huntersmindactivate === "1"; + let baseAF = parseInt(values.baseaf) || 0; + let favoured_language = values.favoured_language === "1"; + + // Initial final scores calculation + let finalStealth = stealth + miscStealth + stillnessPos; + let finalPerception = perception + miscPerception; + + // Apply Reflexes modifiers + if (reflexes <= 5) { + finalStealth -= 1; + } else if (reflexes >= 16) { + finalStealth += 1; + } + + // Apply Psychic Talent modifiers + if (psychicTalent <= 5) { + finalPerception -= 1; + } else if (psychicTalent >= 16) { + finalPerception += 1; + } + + // Apply the rule for human intuition perception + if (humanIntuitionSelect === 1 || humanIntuitionSelect === 3) { + finalPerception += 1; + } + + // Apply the favoured language bonus + if (favoured_language) { + finalPerception += 1; + } + + // Apply Hunter's Mind bonus if conditions are met + if (huntersMindActive && baseAF < 3) { + let huntersMindBonus = Math.floor(rank / 3); + finalStealth += huntersMindBonus; + finalPerception += huntersMindBonus; + } + + // Update attributes with final scores + setAttrs({ + 'finalstealth': finalStealth, + 'finalperception': finalPerception + }); + }); +}); + +on('change:finalstrength change:humanintuitionselect change:finalreflexes change:attack change:defence change:evasion change:miscattackmelee change:miscdefencemelee change:miscattackranged change:miscdefenceranged change:miscevasion change:berserkneg change:berserkpos change:berserktoranged change:bloodrageselect change:main_gauche_active change:maingauchedefencebonus change:shield change:magicshield change:equippedmeleeweaponmagicbonus change:magicrangedweaponbonus change:equippedammomagicbonus change:mattackmoda change:mdefencemoda change:rattackmoda change:rdefencemoda change:nonprofranged change:nonprofmelee change:deathvowselect change:preciseneg change:stillnessneg change:equippedammoattackmod change:intelligence change:elemental_resistance_select change:song_of_battle_toggle', function() { + + getAttrs([ + 'finalstrength', 'finalreflexes', 'attack', 'defence', 'evasion', + 'miscattackmelee', 'miscdefencemelee', 'miscattackranged', 'miscdefenceranged', 'miscevasion', + 'berserkpos', 'berserkneg', 'berserktoranged', 'bloodrageselect', 'main_gauche_active', 'maingauchedefencebonus', + 'shield', 'magicshield', 'equippedmeleeweaponmagicbonus', 'magicrangedweaponbonus', 'equippedammomagicbonus', 'song_of_battle_toggle', + 'mattackmoda', 'mdefencemoda', 'rattackmoda', 'rdefencemoda', 'nonprofranged', 'nonprofmelee', 'humanintuitionselect', + 'deathvowselect', 'preciseneg', 'stillnessneg', 'equippedammoattackmod', 'intelligence', 'elemental_resistance_select' + ], function(values) { + + // Retrieve base values + let baseAttack = parseInt(values['attack']) || 0; + let baseDefence = parseInt(values['defence']) || 0; + let baseEvasion = parseInt(values['evasion']) || 0; + + // Retrieve characteristic scores + let strength = parseInt(values['finalstrength']) || 0; + let reflexes = parseInt(values['finalreflexes']) || 0; + let intelligence = parseInt(values['intelligence']) || 0; + + // Retrieve misc values + let miscMeleeAttack = parseInt(values['miscattackmelee']) || 0; + let miscMeleeDefence = parseInt(values['miscdefencemelee']) || 0; + let miscRangedAttack = parseInt(values['miscattackranged']) || 0; + let miscRangedDefence = parseInt(values['miscdefenceranged']) || 0; + let miscEvasion = parseInt(values['miscevasion']) || 0; + + // Retrieve special ammo modifiers + let specialAmmoAttack = parseInt(values['equippedammoattackmod']) || 0; + + // Retrieve guard modifiers + let guardMeleeAttack = parseInt(values['mattackmoda']) || 0; + let guardMeleeDefence = parseInt(values['mdefencemoda']) || 0; + let guardRangedAttack = parseInt(values['rattackmoda']) || 0; + let guardRangedDefence = parseInt(values['rdefencemoda']) || 0; + + // Retrieve magic bonuses + let magicMeleeWeaponBonus = parseInt(values['equippedmeleeweaponmagicbonus']) || 0; + let magicRangedWeaponBonus = parseInt(values['magicrangedweaponbonus']) || 0; + let magicAmmoBonus = parseInt(values['equippedammomagicbonus']) || 0; + + // Knight Skill Modifiers + let main_gauche_active = parseInt(values['main_gauche_active']) || 0; + let maingaucheDefenceBonus = parseInt(values['maingauchedefencebonus']) || 0; + + // Warlock Skill Modifiers + let nonProfRanged = parseInt(values['nonprofranged']) || 0; + let nonProfMelee = parseInt(values['nonprofmelee']) || 0; + + //Elementalist Skill Modifiers + let elemental_resistance_select = parseInt(values['elemental_resistance_select']) || 0; + + // Shield Status and Magic Bonus + let shieldEquipped = parseInt(values['shield']) || 0; + let magicShieldBonus = parseInt(values['magicshield']) || 0; + + // Death Vow Select + let deathvowSelect = parseInt(values['deathvowselect']) || 0; + + let stillnessNeg = parseInt(values['stillnessneg']) || 0; + let humanIntuitionSelect = parseInt(values['humanintuitionselect']) || 0; + + let songOfBattle = values.song_of_battle_toggle ==="1"; + + // Barbarian Skill Modifiers + let berserkNeg = parseInt(values['berserkneg']) || 0; + let berserkToRanged = parseInt(values['berserktoranged']) || 0; + let bloodrage = parseInt(values['bloodrageselect']) || 0; + + // Ensure berserkNeg is a multiple of 3 and negative (if not 0) + if (berserkNeg < 0) { + berserkNeg = Math.floor(berserkNeg / 3) * 3; // Enforce multiple of 3 + } + + // Calculate berserk and precise shot attack bonuses based on defense penalty + let berserkPos = Math.floor(-berserkNeg / 3); + + // Initialize final values + let finalMeleeAttack = baseAttack + miscMeleeAttack + guardMeleeAttack + nonProfMelee + magicMeleeWeaponBonus; + let finalMeleeDefence = baseDefence + miscMeleeDefence + guardMeleeDefence - stillnessNeg + magicMeleeWeaponBonus; + let finalRangedAttack = baseAttack + miscRangedAttack + guardRangedAttack + nonProfRanged + specialAmmoAttack + magicRangedWeaponBonus + magicAmmoBonus; + let finalRangedDefence = baseDefence + miscRangedDefence + guardRangedDefence - stillnessNeg; + let finalEvasion = baseEvasion + miscEvasion; + + // Apply Strength Effects + if (strength <= 5) { + finalMeleeAttack -= 2; + finalMeleeDefence -= 1; + finalRangedAttack -= 2; + finalRangedDefence -= 1; + } else if (strength <= 8) { + finalMeleeAttack -= 1; + finalRangedAttack -= 1; + } else if (strength <= 12) { + // No modifiers for strength between 9 and 12 + } else if (strength <= 15) { + finalMeleeAttack += 1; + finalRangedAttack += 1; + } else { + finalMeleeAttack += 2; + finalRangedAttack += 2; + finalMeleeDefence += 1; + finalRangedDefence += 1; + } + + // Apply Reflexes Effects + if (reflexes <= 5) { + finalMeleeAttack -= 1; + finalMeleeDefence -= 2; + finalRangedAttack -= 1; + finalRangedDefence -= 2; + finalEvasion -= 2; + } else if (reflexes <= 8) { + finalMeleeDefence -= 1; + finalRangedDefence -= 1; + finalEvasion -= 1; + } else if (reflexes <= 12) { + // No modifiers for reflexes between 9 and 12 + } else if (reflexes <= 15) { + finalMeleeDefence += 1; + finalRangedDefence += 1; + finalEvasion += 1; + } else { + finalMeleeAttack += 1; + finalRangedAttack += 1; + finalMeleeDefence += 2; + finalRangedDefence += 2; + finalEvasion += 2; + } + + // Apply Intelligence Effects + if (intelligence <= 5) { + finalMeleeAttack -= 1; + finalMeleeDefence -= 1; + finalRangedAttack -= 1; + finalRangedDefence -= 1; + } else if (intelligence >= 16) { + finalMeleeAttack += 1; + finalMeleeDefence += 1; + finalRangedAttack += 1; + finalRangedDefence += 1; + } + + // Hunter Skill Modifiers + let preciseNeg = parseInt(values['preciseneg']) || 0; + + // Ensure preciseNeg is a multiple of 3 and negative (if not 0) + if (preciseNeg < 0) { + preciseNeg = Math.floor(preciseNeg / 3) * 3; // Enforce multiple of 3 + } + + // Calculate the maximum allowed preciseNeg without going below 0 finalRangedDefence + let maxPreciseNeg = -finalRangedDefence; + + // Ensure preciseNeg doesn't exceed the maximum and is a multiple of 3 + if (preciseNeg < maxPreciseNeg) { + preciseNeg = Math.ceil(maxPreciseNeg / 3) * 3; // Round up to the nearest multiple of 3 + } + + // Calculate precisePos based on the capped preciseNeg + let precisePos = Math.floor(-preciseNeg / 3); + + // Apply the effects + finalMeleeDefence += preciseNeg; + finalRangedAttack += precisePos; + finalRangedDefence += preciseNeg; + + // Apply Bloodrage Effects + if (bloodrage === 1) { + finalMeleeAttack += finalMeleeDefence; + finalMeleeDefence = 0; + finalRangedAttack = 0; + finalRangedDefence = 0; + } else { + // Apply Berserk Effects (with input capping) + + // Calculate the maximum allowed berserkNeg without going below 0 finalMeleeDefence + let maxBerserkNeg = -finalMeleeDefence; + + // Ensure berserkNeg doesn't exceed the maximum and is a multiple of 3 + if (berserkNeg < maxBerserkNeg) { + berserkNeg = Math.ceil(maxBerserkNeg / 3) * 3; // Round up to the nearest multiple of 3 + } + + // Update the 'berserkneg' attribute on the sheet to the capped value + setAttrs({ + berserkneg: berserkNeg + }); + + // Calculate berserkPos based on the capped berserkNeg + let berserkPos = Math.floor(-berserkNeg / 3); + + // Apply the effects + finalMeleeDefence += berserkNeg; + finalMeleeAttack += (berserkToRanged ? 0 : berserkPos); + finalRangedAttack += (berserkToRanged ? berserkPos : 0); + finalRangedDefence += berserkNeg; + } + + // Adjust Melee Defence based on Main Gauche + if (main_gauche_active === 1) { + finalMeleeDefence += 2 + maingaucheDefenceBonus; + } else if (main_gauche_active === 2) { + finalMeleeDefence = 0; + } + + // Add Shield Magic Bonus to Defence + if (shieldEquipped) { + finalMeleeDefence += magicShieldBonus; + finalRangedDefence += magicShieldBonus; + } + + // Apply Death Vow Select Effect + if (deathvowSelect === 1) { + finalMeleeAttack += 10; + finalRangedAttack += 10; // Assuming you want to apply it to both melee and ranged attacks + } + + // Apply Elemental Resistance modifiers (only one can apply at a time) + if (elemental_resistance_select === 1) { + finalEvasion += 4; + } else if (elemental_resistance_select === 2) { + finalEvasion += 2; + } + + // Apply Human Intuition Attack bonus if the checkbox is checked + if (humanIntuitionSelect === 2 || humanIntuitionSelect === 3) { + finalMeleeAttack += 1; + finalRangedAttack += 1; + } + + if (songOfBattle) { + finalMeleeAttack += 8; + finalRangedAttack += 8; + finalMeleeDefence += 4; + finalRangedDefence += 4; + } + + // Set attributes + setAttrs({ + finalmeleeattack: finalMeleeAttack, + finalmeleedefence: finalMeleeDefence, + finalrangedattack: finalRangedAttack, + finalrangeddefence: finalRangedDefence, + finalevasion: finalEvasion, + berserkpos: berserkPos, + precisepos: precisePos, + berserkneg: berserkNeg, + preciseneg: preciseNeg + }); + }); +}); + +on('change:stillnessneg change:favoured_terrain', function() { + getAttrs(['stillnessneg', 'favoured_terrain', 'finalMeleeDefence', 'finalRangedDefence'], function(values) { + // Parse and default values + let stillnessNeg = parseInt(values['stillnessneg'], 10) || 0; + let favoured_terrain = values['favoured_terrain'] === '1'; + let finalMeleeDefence = parseInt(values['finalmeleedefence']); + let finalRangedDefence = parseInt(values['finalrangeddefence']); + + // Ensure stillnessNeg is a multiple of 2 and negative (if not 0) + if (stillnessNeg < 0) { + stillnessNeg = Math.floor(stillnessNeg / 2) * 2; + } + + // Calculate the maximum allowed stillnessNeg without going below 0 finalMeleeDefence or finalRangedDefence + let maxStillnessNeg = Math.max(-finalMeleeDefence, -finalRangedDefence); // Consider both defenses + + // Ensure stillnessNeg doesn't exceed the maximum and is a multiple of 2 + if (stillnessNeg < maxStillnessNeg) { + stillnessNeg = Math.ceil(maxStillnessNeg / 2) * 2; + } + + // Calculate the Stealth bonus + let stillnessPos; + if (favoured_terrain) { + stillnessPos = -stillnessNeg; // Full bonus if favoured terrain (negate to make it positive) + } else { + stillnessPos = Math.floor(-stillnessNeg / 2); // Half bonus otherwise (negate to make it positive) + } + + // Set the attributes + setAttrs({ + stillnesspos: stillnessPos, + stillnessneg: stillnessNeg + }); + }); +}); + +on('change:finalintelligence change:finalpsychictalent change:magicalattack change:magicaldefence change:miscmagicattack change:miscmagicdefence change:activateiron_will change:elemental_resistance_primary change:elemental_resistance_secondary change:demonic_specialism', function() { + getAttrs([ + 'finalintelligence', 'finalpsychictalent', + 'magicalattack', 'magicaldefence', 'miscmagicattack', 'miscmagicdefence', + 'activateiron_will', 'elemental_resistance_primary', 'elemental_resistance_secondary', + 'demonic_specialism', 'rank' + ], function(values) { + // Retrieve base scores and modifiers + let intelligence = parseInt(values.finalintelligence, 10) || 0; + let psychicTalent = parseInt(values.finalpsychictalent, 10) || 0; + let baseMagicalAttack = parseInt(values.magicalattack, 10) || 0; + let baseMagicalDefence = parseInt(values.magicaldefence, 10) || 0; + let miscMagicalAttack = parseInt(values.miscmagicattack, 10) || 0; + let miscMagicalDefence = parseInt(values.miscmagicdefence, 10) || 0; + let activateiron_will = parseInt(values.activateiron_will, 10) || 0; + let elemental_resistance_primary = parseInt(values.elemental_resistance_primary, 10) || 0; + let elemental_resistance_secondary = parseInt(values.elemental_resistance_secondary, 10) || 0; + let demonicSpecialism = parseInt(values.demonic_specialism, 10) || 0; + let rank = parseInt(values.rank, 10) || 0; + + // Initialize modifiers + let magicalAttackModifier = 0; + let magicalDefenceModifier = 0; + + // Calculate Intelligence modifiers + if (intelligence >= 16) { + magicalAttackModifier += 1; + magicalDefenceModifier += 1; + } else if (intelligence <= 5) { + magicalAttackModifier -= 1; + magicalDefenceModifier -= 1; + } + + // Calculate Psychic Talent modifiers + if (psychicTalent >= 16) { + magicalDefenceModifier += 2; + } else if (psychicTalent >= 13) { + magicalDefenceModifier += 1; + } else if (psychicTalent >= 9) { + magicalDefenceModifier += 0; + } else if (psychicTalent >= 6) { + magicalDefenceModifier -= 1; + } else if (psychicTalent <= 5) { + magicalDefenceModifier -= 2; + } + + // Apply Iron Will bonus + if (activateiron_will === 1) { + magicalDefenceModifier += 2; + } + + // Apply Elemental Resistance modifiers (only one can apply at a time) + if (elemental_resistance_primary === 1) { + magicalDefenceModifier += 4; + } else if (elemental_resistance_secondary === 1) { + magicalDefenceModifier += 2; + } + + // Apply Demonic Specialism bonuses + if (demonicSpecialism === 1) { + if (rank >= 12) { + magicalAttackModifier += 5; + magicalDefenceModifier += 5; + } else if (rank >= 7) { + magicalAttackModifier += 3; + magicalDefenceModifier += 3; + } else { + magicalAttackModifier += 1; + magicalDefenceModifier += 1; + } + } + + // Calculate final values + let finalMagicalAttack = baseMagicalAttack + magicalAttackModifier + miscMagicalAttack; + let finalMagicalDefence = baseMagicalDefence + magicalDefenceModifier + miscMagicalDefence; + + // Set attributes + setAttrs({ + 'finalmagicalattack': finalMagicalAttack, + 'finalmagicaldefence': finalMagicalDefence + }); + }); +}); + +on('change:rank change:armour_piercing change:shock_attack change:throwing_spike change:unarmed_combat change:inner_sense change:memorize change:deathvow change:assassins_lotion change:smoke_jar change:flash_pellets change:breakfall change:climbing change:jumping change:disguise change:pilfer change:pick_lock change:track', function() { + getAttrs([ + 'armour_piercing', + 'shock_attack', + 'throwing_spike', + 'unarmed_combat', + 'inner_sense', + 'memorize', + 'deathvow', + 'assassins_lotion', + 'smoke_jar', + 'flash_pellets', + 'breakfall', + 'climbing', + 'jumping', + 'disguise', + 'pilfer', + 'pick_lock', + 'track', + 'rank' + ], function(values) { + const rank = parseInt(values.rank, 10) || 0; + + // Helper function to parse and add values + const parseAndSum = (value) => { + const num = parseInt(value, 10) || 0; + return num > 0 ? num : 0; + }; + + // Calculate max values based on rank + let maxCombatTechniques = rank >= 7 ? 4 : rank >= 5 ? 3 : rank >= 3 ? 2 : rank >= 1 ? 1 : 0; + let maxMentalTechniques = rank >= 12 ? 3 : rank >= 8 ? 2 : rank >= 4 ? 1 : 0; + let maxAlchemicalTechniques = rank >= 1 ? 1 : 0; + let maxAssassinSkills = rank >= 11 ? 5 : rank >= 7 ? 4 : rank >= 5 ? 3 : rank >= 3 ? 2 : rank >= 1 ? 1 : 0; + + // Count selected combat techniques + let combatTechniqueSelectedCount = parseAndSum(values.armour_piercing) + + parseAndSum(values.shock_attack) + + parseAndSum(values.throwing_spike) + + parseAndSum(values.unarmed_combat); + + // Count selected mental techniques + let mentalTechniqueSelectedCount = parseAndSum(values.inner_sense) + + parseAndSum(values.memorize) + + parseAndSum(values.deathvow); + + // Check if any alchemical technique is selected + let alchemicalTechniqueSelectedCount = (values.assassins_lotion === '1' || + values.smoke_jar === '1' || + values.flash_pellets === '1') ? 1 : 0; + + // Count selected assassin skills + let assassinSkillsSelectedCount = parseAndSum(values.breakfall) + + parseAndSum(values.climbing) + + parseAndSum(values.jumping) + + parseAndSum(values.disguise) + + parseAndSum(values.pilfer) + + parseAndSum(values.pick_lock) + + parseAndSum(values.track); + + // Update the attributes + setAttrs({ + 'combattechniques_max': maxCombatTechniques, + 'mentaltechniques_max': maxMentalTechniques, + 'alchemicaltechniques_max': maxAlchemicalTechniques, + 'assassinskills_max': maxAssassinSkills, + 'combattechniques_selected': combatTechniqueSelectedCount, + 'mentaltechniques_selected': mentalTechniqueSelectedCount, + 'alchemicaltechniques_selected': alchemicalTechniqueSelectedCount, + 'assassinskills_selected': assassinSkillsSelectedCount + }); + }); +}); + +// Listen for changes to the rank and Knight skills +on('change:rank change:disarm_technique change:expert_parry change:main_gauche change:master_bowman change:quick_draw change:swordmaster change:weaponskill1 change:weaponskill2 change:weaponskill3 change:fearless change:intimidating change:iron_will change:tireless change:true_grit change:oak_fists', function() { + getAttrs([ + 'disarm_technique', + 'expert_parry', + 'main_gauche', + 'master_bowman', + 'quick_draw', + 'swordmaster', + 'weaponskill1', + 'weaponskill2', + 'weaponskill3', + 'rank', + 'fearless', + 'intimidating', + 'iron_will', + 'tireless', + 'true_grit', + 'oak_fists' + ], function(values) { + const rank = parseInt(values.rank, 10) || 0; + + // Knight calculations + let maxKnightSkills = 0; + let knightsupremacyMax = 0; + let knightSkillsSelectedCount = 0; + let supremacySkillsSelectedCount = 0; + + // Calculate max Knight skills based on rank + if (rank >= 13) { + maxKnightSkills = 6; + } else if (rank >= 12) { + maxKnightSkills = 5; + } else if (rank >= 11) { + maxKnightSkills = 4; + } else if (rank >= 10) { + maxKnightSkills = 3; + } else if (rank >= 9) { + maxKnightSkills = 2; + } else if (rank >= 8) { + maxKnightSkills = 1; + } else { + maxKnightSkills = 0; + } + + // Calculate knightsupremacy_max based on rank + if (rank >= 6) { + knightsupremacyMax++; + } + if (rank >= 3) { + knightsupremacyMax++; + } + + // Count selected Knight skills + if (values.disarm_technique === '1') { + knightSkillsSelectedCount++; + } + if (values.expert_parry === '1') { + knightSkillsSelectedCount++; + } + if (values.main_gauche === '1') { + knightSkillsSelectedCount++; + } + if (values.master_bowman === '1') { + knightSkillsSelectedCount++; + } + if (values.quick_draw === '1') { + knightSkillsSelectedCount++; + } + if (values.swordmaster === '1') { + knightSkillsSelectedCount++; + } + if (values.weaponskill1 === '1') { + knightSkillsSelectedCount++; + } + if (values.weaponskill2 === '1') { + knightSkillsSelectedCount++; + } + if (values.weaponskill3 === '1') { + knightSkillsSelectedCount++; + } + + // Count selected Supremacy Skills + if (values.fearless === '1') { + supremacySkillsSelectedCount++; + } + if (values.intimidating === '1') { + supremacySkillsSelectedCount++; + } + if (values.iron_will === '1') { + supremacySkillsSelectedCount++; + } + if (values.tireless === '1') { + supremacySkillsSelectedCount++; + } + if (values.true_grit === '1') { + supremacySkillsSelectedCount++; + } + if (values.oak_fists === '1') { + supremacySkillsSelectedCount++; + } + + // Update the attributes + setAttrs({ + 'knightproskills_max': maxKnightSkills, + 'knightproskills_selected': knightSkillsSelectedCount, + 'knightsupremacy_max': knightsupremacyMax, + 'knightsupremacy_selected': supremacySkillsSelectedCount + }); + }); +}); + + + +// Listen for changes to the Profession, skills, and rank +on('change:profession change:track change:berserk change:ride_warhorse change:bloodrage change:thesupremacyofthesword change:fearless change:intimidating change:iron_will change:tireless change:true_grit change:oak_fists change:rank', function() { + getAttrs([ + 'profession', + 'track', + 'berserk', + 'ride_warhorse', + 'bloodrage', + 'fearless', + 'intimidating', + 'iron_will', + 'tireless', + 'true_grit', + 'oak_fists', + 'rank' + ], function(values) { + const rank = parseInt(values.rank, 10) || 0; + + // Barbarian calculations + let maxBarbarianSkills = 0; + let barbarianSkillsSelectedCount = 0; + + // Calculate max Barbarian skills based on rank + if (rank >= 13) { + maxBarbarianSkills = 6; + } else if (rank >= 12) { + maxBarbarianSkills = 5; + } else if (rank >= 11) { + maxBarbarianSkills = 4; + } else if (rank >= 10) { + maxBarbarianSkills = 3; + } else if (rank >= 9) { + maxBarbarianSkills = 2; + } else if (rank >= 8) { + maxBarbarianSkills = 1; + } else { + maxBarbarianSkills = 0; + } + + // Count selected Barbarian skills + if (values.fearless === '1') { + barbarianSkillsSelectedCount++; + } + if (values.intimidating === '1') { + barbarianSkillsSelectedCount++; + } + if (values.iron_will === '1') { + barbarianSkillsSelectedCount++; + } + if (values.tireless === '1') { + barbarianSkillsSelectedCount++; + } + if (values.true_grit === '1') { + barbarianSkillsSelectedCount++; + } + if (values.oak_fists === '1') { + barbarianSkillsSelectedCount++; + } + + // Handle automatic checking based on profession and rank + if (values.profession === 'Barbarian') { + // Automatically check the Barbarian skills if not already checked + setAttrs({ + 'track': '1', + 'ride_warhorse': '1', + 'berserk': '1' + }); + + // Check bloodrage if rank is 8 or higher + if (values.profession === 'Barbarian' && rank >= 8) { + setAttrs({ + 'bloodrage': '1' + }); + } + } + + // Update the attributes + setAttrs({ + 'attr_barbariansupremacy_max': maxBarbarianSkills, + 'attr_barbariansupremacy_selected': barbarianSkillsSelectedCount + }); + }); +}); + +on('change:profession change:rank change:hunters_mind change:false_trail change:climb change:sneak_attack change:soldier change:penetrating_shot change:master_fletcher change:fast_shot', function() { + getAttrs([ + 'profession', + 'rank', + 'hunters_mind', + 'false_trail', + 'climb', + 'sneak_attack', + 'soldier', + 'penetrating_shot', + 'master_fletcher', + 'fast_shot', + 'track', + 'bowyer_fletcher', + 'precise_shot', + 'favoured_weapon', + 'favoured_terrain', + 'set_traps', + 'forage', + 'stillness' + ], function(values) { + let rank = parseInt(values.rank, 10) || 1; // Default to 1 if no rank is set + let hunterSkillsSelectedCount = 0; + let hunterSkillsMax = 1; // Initial skills at 3rd Rank + + // Calculate the maximum number of Hunter skills + if (rank >= 3) { + hunterSkillsMax = 1; // 1 skill at 3rd Rank + } + if (rank >= 6) { + hunterSkillsMax += 1; // 1 additional skill at 6th Rank + } + if (rank >= 8) { + hunterSkillsMax += Math.floor((rank - 8) / 1) + 1; // 1 additional skill per rank from 8th Rank onward + } + + // Count selected Hunter skills with their values + hunterSkillsSelectedCount += parseInt(values.hunters_mind, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.false_trail, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.climb, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.sneak_attack, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.soldier, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.penetrating_shot, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.master_fletcher, 10) || 0; + hunterSkillsSelectedCount += parseInt(values.fast_shot, 10) || 0; + + // Automatically check specific Hunter skills if Profession is Hunter + if (values.profession === 'Hunter') { + setAttrs({ + 'track': '1', + 'bowyer_fletcher': '1', + 'precise_shot': '1', + 'favoured_weapon': '1', + 'favoured_terrain': '1', + 'set_traps': '1', + 'forage': '1', + 'stillness': '1' + }); + } + + // Update the attributes + setAttrs({ + 'hunterskills_max': hunterSkillsMax, + 'hunterskills_selected': hunterSkillsSelectedCount + }); + }); +}); + +on('change:disguise change:pilfer change:second_tongue change:favoured_language change:natural_linguist change:human_intuition change:uncanny_intuition change:infuriate_pacify change:distract change:magic_hands change:bodyguard change:gossip change:presence change:sense_falsehood change:hypnotic_suggestion change:network change:words_are_power', function() { + getAttrs([ + 'disguise', + 'pilfer', + 'second_tongue', + 'favoured_language', + 'natural_linguist', + 'human_intuition', + 'uncanny_intuition', + 'infuriate_pacify', + 'distract', + 'magic_hands', + 'bodyguard', + 'gossip', + 'presence', + 'sense_falsehood', + 'hypnotic_suggestion', + 'network', + 'words_are_power', + 'rank' + ], function(values) { + + let maxKnaveSkills = 6; // Default maximum skills at Rank 1 + let knaveSkillsSelectedCount = 0; + const rank = parseInt(values.rank, 10) || 0; + + // Update max skills based on rank + if (rank >= 3) { + maxKnaveSkills += 1; // One more skill at Rank 3 + } + if (rank >= 6) { + maxKnaveSkills += 1; // One more skill at Rank 6 + } + if (rank >= 8) { + maxKnaveSkills += 1; // One more skill at Rank 8 + } + if (rank > 8) { + maxKnaveSkills += Math.floor((rank - 8) / 1); // One more skill per rank above 8 + } + + // Count selected Knave skills with their values + knaveSkillsSelectedCount += parseInt(values.disguise, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.pilfer, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.second_tongue, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.favoured_language, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.natural_linguist, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.human_intuition, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.uncanny_intuition, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.infuriate_pacify, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.distract, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.magic_hands, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.bodyguard, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.gossip, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.presence, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.sense_falsehood, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.hypnotic_suggestion, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.network, 10) || 0; + knaveSkillsSelectedCount += parseInt(values.words_are_power, 10) || 0; + + // Update the attributes + setAttrs({ + 'knaveskills_max': maxKnaveSkills, + 'knaveskills_selected': knaveSkillsSelectedCount + }); + }); +}); + + +// Listen for changes to the Profession and Warlock skills +on('change:profession change:appraise_enemy change:arrow_cutting change:fight_blind change:unarmed_combat change:minor_enchantment_weapons change:minor_enchantment_armour change:major_enchantment_weapons change:major_enchantment_armour change:ride_warhorse change:warlockweapongroups change:simultaneous_casting change:rank', function() { + getAttrs([ + 'profession', + 'appraise_enemy', + 'arrow_cutting', + 'fight_blind', + 'unarmed_combat', + 'minor_enchantment_weapons', + 'minor_enchantment_armour', + 'major_enchantment_weapons', + 'major_enchantment_armour', + 'ride_warhorse', + 'warlockweapongroups', + 'simultaneous_casting', + 'rank' + ], function(values) { + let warlockSkillsSelectedCount = 0; + let maxskills = 0; + + // Check if the profession is Warlock + if (values.profession === 'Warlock') { + // Automatically check the Warlock skills if not already checked + setAttrs({ + 'warlockweapongroups': '1', + 'simultaneous_casting': '1' + }); + } + + // Count selected Warlock skills + if (values.appraise_enemy === '1') { + warlockSkillsSelectedCount++; + } + if (values.arrow_cutting === '1') { + warlockSkillsSelectedCount++; + } + if (values.fight_blind === '1') { + warlockSkillsSelectedCount++; + } + if (values.unarmed_combat === '1') { + warlockSkillsSelectedCount++; + } + if (values.minor_enchantment_weapons === '1') { + warlockSkillsSelectedCount++; + } + if (values.minor_enchantment_armour === '1') { + warlockSkillsSelectedCount++; + } + if (values.major_enchantment_weapons === '1') { + warlockSkillsSelectedCount++; + } + if (values.major_enchantment_armour === '1') { + warlockSkillsSelectedCount++; + } + if (values.ride_warhorse === '1') { + warlockSkillsSelectedCount++; + } + + // Calculate maxskills based on the rank + let rank = parseInt(values.rank, 10); + if (rank >= 8) { + maxskills = Math.floor((rank - 7) / 1); // One talent at 8th rank, another at 9th, etc. + } + + // Update the attributes with the count of selected Warlock skills and maxskills + setAttrs({ + 'warlockskills_selected': warlockSkillsSelectedCount, + 'warlockskills_max': maxskills + }); + }); +}); + + +// Listen for changes to the Rank and Profession +on('change:rank change:profession change:breadth_of_knowledge change:literate change:ancient_script change:linguist change:bulwark change:exorcism change:sermon change:healing_hands change:remove_curse change:depth_of_knowledge change:remove_madness change:words_are_power', function() { + getAttrs([ + 'rank', + 'profession', + 'bulwark', // Corrected from 'bulwark' + 'exorcism', + 'sermon', + 'healing_hands', + 'remove_curse', + 'depth_of_knowledge', + 'remove_madness', + 'words_are_power', + 'ancient_script', + 'literate', + 'linguist', + 'breadth_of_knowledge' + ], function(values) { + + // Check if the profession is Priest + if (values.profession === 'Priest') { + // Automatically check the Priest skills + setAttrs({ + 'breadth_of_knowledge': '1', + 'literate': '1', + 'linguist': '1', + 'ancient_script': '1' + }); + } + + // Update the count of selected Priest skills + let priestSkillsSelectedCount = 0; + if (values.bulwark === '1') { + priestSkillsSelectedCount++; + } + if (values.exorcism === '1') { + priestSkillsSelectedCount++; + } + if (values.sermon === '1') { + priestSkillsSelectedCount++; + } + if (values.healing_hands === '1') { + priestSkillsSelectedCount++; + } + if (values.remove_curse === '1') { + priestSkillsSelectedCount++; + } + if (values.depth_of_knowledge === '1') { + priestSkillsSelectedCount++; + } + if (values.remove_madness === '1') { + priestSkillsSelectedCount++; + } + if (values.words_are_power === '1') { + priestSkillsSelectedCount++; + } + + // Calculate max number of skills based on rank + let rank = parseInt(values.rank) || 0; + let maxPriestSkills = 0; + + if (rank >= 3) { + maxPriestSkills += 1; // One more skill at Rank 3 + } + if (rank >= 6) { + maxPriestSkills += 1; // One more skill at Rank 6 + } + if (rank >= 8) { + maxPriestSkills += 1; // One more skill at Rank 8 + } + if (rank > 8) { + maxPriestSkills += Math.floor((rank - 8) / 1); // One more skill per rank above 8 + } + + // Update attributes with correct syntax + setAttrs({ + 'priestskills_max': maxPriestSkills, + 'priestskills_selected': priestSkillsSelectedCount // No need to set this twice + }); + }); +}); + +// Listen for changes to profession and rank +on('change:profession change:rank change:intelligence', function() { + getAttrs([ + 'profession', + 'rank', + 'intelligence', + 'calligraphy', + 'alchemy', + 'craft_amulets', + 'craft_novel_items', + 'craft_wands', + 'craft_rings', + 'craft_talismans', + 'premonition', + 'esp', + 'enchantment', + 'raw_power', + 'elemental_resistance', + 'demonic_specialism', + 'demonology', + 'demonology_modifier', + 'pentacle_of_protection', + 'ritual_of_summoning', + 'banishing_a_demon', + 'pact_of_the_dark_companion' + ], function(values) { + const profession = values.profession; + const rank = parseInt(values.rank, 10) || 0; + const intelligence = parseInt(values.intelligence, 10) || 0; + + // Default all attributes to unchecked + let updates = { + 'calligraphy': '0', + 'alchemy': '0', + 'craft_amulets': '0', + 'craft_novel_items': '0', + 'craft_wands': '0', + 'craft_rings': '0', + 'craft_talismans': '0', + 'premonition': '0', + 'esp': '0', + 'enchantment': '0', + 'raw_power': '0', + 'elemental_resistance': '0', + 'demonic_specialism': '0', + 'demonology': '0', + 'demonology_modifier': '0', + 'pentacle_of_protection': '0', + 'ritual_of_summoning': '0', + 'banishing_a_demon': '0', + 'pact_of_the_dark_companion': '0' + }; + + // Apply rules based on profession and rank + if (profession === 'Sorcerer') { + if (rank >= 4) { + updates.calligraphy = '1'; + } + if (rank >= 6) { + updates.alchemy = '1'; + } + if (rank >= 8) { + updates.craft_talismans = '1'; + updates.craft_wands = '1'; + } + if (rank >= 10) { + updates.craft_amulets = '1'; + } + if (rank >= 12) { + updates.craft_rings = '1'; + } + if (rank >= 15) { + updates.craft_novel_items = '1'; + } + } + + // Apply rules based on profession and rank for Mystic + if (profession === 'Mystic') { + updates.premonition = '1'; + updates.esp = '1'; + if (rank >= 4) { + updates.enchantment = '1'; + } + } + + // Apply rules based on profession for Elementalist + if (profession === 'Elementalist') { + updates.raw_power = '1'; + updates.elemental_resistance = '1'; + } + + // Apply rules based on profession for Demonologist + if (profession === 'Demonologist') { + // Demonic Specialism + if (rank >= 1) { + updates.demonic_specialism = '1'; + } + if (rank >= 7) { + updates.demonic_specialism = '3'; + } + if (rank >= 12) { + updates.demonic_specialism = '5'; + } + + // Demonology + let demonologyValue = 1; + if (intelligence <= 5) { + demonologyValue -= 2; + } else if (intelligence <= 8) { + demonologyValue -= 1; + } else if (intelligence <= 12) { + demonologyValue += 0; + } else if (intelligence >= 13) { + demonologyValue += 1; + } else if (intelligence >= 16) { + demonologyValue += 2; + } + updates.demonology_modifier = demonologyValue; + + // Pentacle of Protection + if (rank >= 4) { + updates.pentacle_of_protection = '1'; + } + + // Ritual of Summoning + if (rank >= 4) { + updates.ritual_of_summoning = '1'; + } + + // Banishing a Demon + updates.banishing_a_demon = '1'; + + // Pact of the Dark Companion + if (rank >= 7) { + updates.pact_of_the_dark_companion = '1'; + } + } + + // Update the attributes + setAttrs(updates); + }); +}); + +on('change:skillsknown change:profession change:rank change:raw_power change:raw_power_alternate change:elemental_essence change:elemental_resistance change:oak_fists change:track change:berserk change:ride_warhorse change:bloodrage change:armour_expert change:armour_piercing change:shock_attack change:throwing_spike change:unarmed_combat change:inner_sense change:memorize change:deathvow change:light_trance change:darkness_trance change:water_trance change:earth_trance change:void_trance change:fire_trance change:wind_trance change:disarm_technique change:expert_parry change:main_gauche change:master_bowman change:quick_draw change:swordmaster change:weaponskill1 change:weaponskill2 change:weaponskill3 change:calligraphy change:alchemy change:craft_talismans change:craft_amulets change:craft_rings change:craft_novel_items change:craft_wands change:premonition change:esp change:enchantment change:adepthood change:appraise_enemy change:arrow_cutting change:fight_blind change:minor_enchantment_weapons change:minor_enchantment_armour change:major_enchantment_weapons change:major_enchantment_armour change:disguise change:pilfer change:second_tongue change:favoured_language change:natural_linguist change:human_intuition change:uncanny_intuition change:infuriate_pacify change:distract change:magic_hands change:bodyguard change:gossip change:presence change:sense_falsehood change:hypnotic_suggestion change:network change:words_are_power change:literate change:ancient_script change:breadth_of_knowledge change:linguist change:bulwark change:exorcism change:sermon change:healing_hands change:remove_curse change:depth_of_knowledge change:remove_madness change:demonic_specialism change:demonology change:pentacle_of_protection change:ritual_of_summoning change:banishing_a_demon change:pact_of_the_dark_companion change:fearless change:intimidating change:iron_will change:tireless change:true_grit change:breakfall change:climbing change:jumping change:pick_lock change:bowyer_fletcher change:precise_shot change:favoured_weapon change:favoured_terrain change:set_traps change:forage change:stillness change:hunters_mind change:false_trail change:climb change:penetrating_shot change:sneak_attack change:soldier change:master_fletcher change:master_tracker change:fast_shot', function() { + getAttrs([ + 'track', 'berserk', 'ride_warhorse', 'bloodrage', 'armour_expert', 'armour_piercing', 'shock_attack', 'throwing_spike', 'unarmed_combat', + 'inner_sense', 'memorize', 'deathvow', 'light_trance', 'darkness_trance', 'water_trance', 'earth_trance', 'void_trance', + 'fire_trance', 'wind_trance', 'disarm_technique', 'expert_parry', 'main_gauche', 'master_bowman', 'quick_draw', 'swordmaster', + 'weaponskill1', 'weaponskill2', 'weaponskill3', 'calligraphy', 'alchemy', 'craft_talismans', 'craft_amulets', 'craft_rings', 'craft_novel_items', + 'craft_wands', 'premonition', 'esp', 'enchantment', 'adepthood', 'appraise_enemy', 'arrow_cutting', 'fight_blind', + 'minor_enchantment_weapons', 'minor_enchantment_armour', 'major_enchantment_weapons', 'major_enchantment_armour', + 'disguise', 'pilfer', 'second_tongue', 'favoured_language', 'natural_linguist', 'human_intuition', 'uncanny_intuition', + 'infuriate_pacify', 'distract', 'magic_hands', 'bodyguard', 'gossip', 'presence', 'sense_falsehood', 'hypnotic_suggestion', + 'network', 'words_are_power', 'literate', 'ancient_script', 'breadth_of_knowledge', 'linguist', 'bulwark', 'exorcism', + 'sermon', 'healing_hands', 'remove_curse', 'depth_of_knowledge', 'remove_madness', 'demonic_specialism', 'demonology', + 'pentacle_of_protection', 'ritual_of_summoning', 'banishing_a_demon', 'pact_of_the_dark_companion', 'fearless', 'intimidating', + 'iron_will', 'tireless', 'true_grit', 'breakfall', 'climbing', 'jumping', 'pick_lock', 'oak_fists', 'raw_power', 'raw_power_alternate', + 'elemental_essence', 'elemental_resistance', 'bowyer_fletcher', 'precise_shot', 'favoured_weapon', 'favoured_terrain', 'set_traps', 'forage', + 'stillness', 'hunters_mind', 'false_trail', 'climb', 'penetrating_shot', 'sneak_attack', 'soldier', 'master_fletcher', 'master_tracker', 'fast_shot' + ], function(values) { + // Extract and parse values + let skillsList = []; + // Loop through all values and extract non-zero, defined skills + for (let skill in values) { + // Add this line to check for both undefined and 0 values + if (values[skill] && values[skill] != 0) { + let skillName = skill.replace(/_/g, ' ').toUpperCase(); + let skillRank = values[skill]; // Get the rank or value of the skill + + // Determine whether to use "rank" or "ranks" + let rankText = (skillRank == 1) ? 'rank' : 'ranks'; + + // Append the rank, appropriate word, and add a dot-point before each skill + skillsList.push(`• ${skillName} (${skillRank} ${rankText})`); + } + } + // Create a single string for skills + let skillsText = skillsList.join('\n'); + + // Set the skillsKnown attribute to be used in the HTML + setAttrs({ + 'skillsknown': skillsText + }); + }); +}); + +// Central Sheetworker Script for Pick Lock, Presence, Pilfer, Track, and pick_lock Chance Calculation +on("change:rank change:presence change:pick_lock change:finalintelligence change:finalreflexes change:pilfer change:track change:magic_hands", function() { + getAttrs(["rank", "pick_lock", "finalintelligence", "finalreflexes", "presence", "pilfer", "track", "magic_hands"], function(values) { + // Parse attribute values with default 0 + let pick_lock = parseInt(values['pick_lock'], 10) || 0; + let intelligenceBonus = 0; + let reflexesBonus = 0; + let rank = parseInt(values['rank'], 10) || 1; + let magicHands = parseInt(values['magic_hands'], 10) || 0; + + // Fetch finalIntelligence and finalReflexes values + let finalIntelligence = parseInt(values["finalintelligence"], 10) || 0; + let finalReflexes = parseInt(values["finalreflexes"], 10) || 0; + + // Calculate intelligence and reflexes bonuses + if (finalIntelligence >= 16) { + intelligenceBonus = 5; + } + if (finalReflexes >= 16) { + reflexesBonus = 10; + } + + // --- pick_lock Chance Calculation --- + let pick_lockChance = 0; + if (pick_lock === 1) { + pick_lockChance = 30; + } else if (pick_lock === 2) { + pick_lockChance = 60; + } else if (pick_lock === 3) { + pick_lockChance = 90; + } + + // --- Pilfer Modifier Calculation --- + let pilfer = parseInt(values.pilfer, 10) || 0; + let pilferModifier = 0; + + if (pilfer === 1) { + pilferModifier = 4; + } else if (pilfer === 2) { + pilferModifier = 2; + } + + if (magicHands === 1) { + pilferModifier -= 1; + } + + // --- Track Modifier Calculation --- + let track = parseInt(values.track, 10) || 0; + let trackModifier = 0; + + if (track === 1) { + trackModifier = 0; + } else if (track === 2) { + trackModifier = 2; + } + + // Calculate Presence score + let presenceScore = Math.floor(rank / 3); + + // Calculate total pick_lock score + let pick_lockScore = pick_lockChance + intelligenceBonus + reflexesBonus; + + // Set the new attribute values + setAttrs({ + "pick_lockscore": pick_lockScore, + "presencemodifier": presenceScore, + "pilfermodifier": pilferModifier, + "trackmodifier": trackModifier, + "pick_lockchance": pick_lockChance + }); + }); +}); + + +on('clicked:rollbasehpbutton', function() { + // Get the selected profession, the current maxhp, and the custom profession modifier + getAttrs(['profession', 'customprofessionmodifier'], function(values) { + const profession = values.profession; + const customProfessionModifier = parseInt(values.customprofessionmodifier, 10) || 0; // Default to 0 if empty or NaN + + // Roll a d6 + const roll = Math.floor(Math.random() * 6) + 1; + + // Calculate the bonus based on the profession + let bonus = 0; + if (profession === 'Knight') { + bonus = 7; + } else if (profession === 'Barbarian') { + bonus = 9; + } else if (['Sorcerer', 'Elementalist', 'Demonologist', 'Knave', 'Priest'].includes(profession)) { + bonus = 4; + } else if (['Mystic', 'Warlock', 'Assassin', 'Hunter'].includes(profession)) { + bonus = 5; + } else { + // If the profession is custom, use the custom profession modifier + bonus = customProfessionModifier; + } + + // Calculate the final max HP + const base_maxHP = roll + bonus; + + // Output the result to the maxhp attribute field + setAttrs({ + base_maxhp: base_maxHP + }); + }); +}); + +// When the RollBaseStats button is clicked, calculate the stats +on('clicked:rollbasestatsbutton', function() { + // Get the current base attributes + getAttrs(['strength', 'reflexes', 'intelligence', 'psychictalent', 'looks'], function(values) { + // Output the result to the Base Stats attribute fields + setAttrs({ + }); + }); +}); + +// When the Roll Base Characteristics button is clicked, roll 3d6 for each stat +on('clicked:rollbasestatsbutton', function() { + // Function to roll 3d6 and return the result + function roll3d6() { + return Math.floor(Math.random() * 6) + 1 + + Math.floor(Math.random() * 6) + 1 + + Math.floor(Math.random() * 6) + 1; + } + + // Roll 3d6 for each characteristic + const strength = roll3d6(); + const reflexes = roll3d6(); + const intelligence = roll3d6(); + const psychictalent = roll3d6(); + const looks = roll3d6(); + + // Output the result to the Base Stats attribute fields + setAttrs({ + strength: strength, + reflexes: reflexes, + intelligence: intelligence, + psychictalent: psychictalent, + looks: looks + }); +}); + +// Listen for changes to the attr_mastered_spell attribute +on("change:mastered_spell", function(event) { + getAttrs(["mastered_spell"], function(values) { + // Retrieve the updated value of attr_mastered_spell + let mastered_spell = values.mastered_spell; + + // Set the new value for attr_mastered_spell + setAttrs({ + mastered_spell: mastered_spell + }); + }); +}); +on('change:weapon_group_1 change:weapon_group_2', function() { + getAttrs(['weapon_group_1', 'weapon_group_2'], function(values) { + // Define the mapping of values to descriptions + const weaponGroupDescriptions = { + '1': 'Weapon Group I: Flail, Mace, Morningstar, Holy Water Sprinkler, Scourge, Warhammer', + '2': 'Weapon Group II: Dagger, Shortsword, Sword', + '3': 'Weapon Group III: Halberd, Staff, Spear, Footman\'s Flail, Pollaxe, War Lance', + '4': 'Weapon Group IV: Two-handed Sword, Longsword', + '5': 'Weapon Group V: Battleaxe, War Axe', + '6': 'Weapon Group VI: Bow, Longbow', + '7': 'Weapon Group VII: Crossbow, Javelin, Sling, Dagger, Rock, Throwing Spike, Arbalest', + '8': 'Weapon Group VIII: Cudgel, Unarmed combat' + }; + + // Get the selected values + const weaponGroup1 = values.weapon_group_1; + const weaponGroup2 = values.weapon_group_2; + + // Set the descriptions based on the selected values + const weaponGroup1Description = weaponGroupDescriptions[weaponGroup1] || ''; + const weaponGroup2Description = weaponGroupDescriptions[weaponGroup2] || ''; + + // Update the attributes with the descriptions + setAttrs({ + 'weapon_group_1_description': weaponGroup1Description, + 'weapon_group_2_description': weaponGroup2Description + }); + }); +}); + +on("clicked:repeating_meleeweapons:equipoffhand", function(eventInfo) { + const sourceId = eventInfo.sourceAttribute.split('_')[2]; // Extracting the ID of the repeating section row + const prefix = `repeating_meleeweapons_${sourceId}_`; + + // Get the current magic bonus of the selected weapon + getAttrs([`${prefix}magicmeleeweaponbonus`], function(values) { + const magicBonus = values[`${prefix}magicmeleeweaponbonus`] || 0; + + // Set the ismaingauchedefenceweapon to '1' and update maingauchedefencebonus with magic bonus + const update = { + [`${prefix}ismaingauchedefenceweapon`]: '1', // Set the attribute to indicate it's equipped offhand + 'maingauchedefencebonus': magicBonus // Export the magic bonus to the main gauche defence bonus attribute + }; + + setAttrs(update); + }); +}); + +on("change:phantasm_attack change:phantasm_defence", function(eventinfo) { + getAttrs(["phantasm_attack", "phantasm_defence"], function(values) { + let attack = parseInt(values.phantasm_attack) || 0; + let defence = parseInt(values.phantasm_defence) || 0; + // Check which field triggered the change + if (eventinfo.sourceAttribute === "phantasm_attack") { + defence = 28 - attack; // Adjust defence + } else if (eventinfo.sourceAttribute === "phantasm_defence") { + attack = 28 - defence; // Adjust attack + } + setAttrs({ + phantasm_attack: attack, + phantasm_defence: defence + }); + }); +}); + \ No newline at end of file diff --git a/Dragon Warriors/d12.jpg b/Dragon Warriors/d12.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dd59a0a6483f466d21d11d4255db535debc4b48e GIT binary patch literal 2247 zcmV;&2srou*#GVT4nbsZVr2ki000000RP(nLjVj22nYxW3<{9 z009C61O*WQ5+Mc?F(N@x6f$9Pkp~q*ffgf@Bs5ZEbAq9<(f`^22mt^906zfwuBNz_ zSfGujoz^(eWu3@X1LTu{G_Z9HRaq8Vd2U1;cOn8RV1Me#wOjtp+Nu8l#1-!>H1`TB z8DV7ZLlkDVL<~0ta?(TrBa!GD@`mGjc-}-bcW9%K#$Jug54lbqNOqAo4{^9?#J$jo z1QmPerf&&SrXYU-`HjD`9UteBuXQyv1={GA*y4>By;oN+W|9HHl1vskJmFPAW zl2#NDA{La%je$VPCp=?V+hxk*YrE9eOBja1QBxcy9)H-~z!5PX7jYxFqlDZ&^Nqfy zyd(fgI0KSTjU==$^LvcFM<6|rjZ19@$7B#>oDcboydU^L`O|8uN_yB@o~khe_=$5_Y9|SftAf2?}rn0zlxY z2RPGtKa@Ry_th5NJuj&T+Q};T9^{?edz1OlohflL(k;4K9%BSb^pnU6Jw+)cV~~al zcdj_kxvi}DvyHOf@jzh@1*nHdai1EtB+5`M;)?> z<%$@lNet4ZIoRx*T>u$I3JyGJeJ$qf*Sj6>sAwQaYtU0tR#DF|L~4ZGsVr}RbNL*6 zoNHG>Mn9fhZfpi*NGZ_!?1(WV{Y-RqZB$e=lGRS)B#8+wz_O2ENF4b(LmhR_(@{-T zb*nPa*GQI()o{XQic4&iiAoMu8-$Ne^v-t>a;P0~?gz%cg{0j;%R@cB_H(w9 zq*KrF*{drH6Zj9Yzd@mDx+apMS%g*9l=M|nNi9tTQV*w*q{(tOD>CGqkfdr&(Xmxr zsVeGgW_n9>!df~2sF26CRaFTCETeB3=kupF^=`vE@X|=^e+MT%=if_hwKYYhv)@^2 zC1!EmDyWPcu~phQ!C$cR;DgBKtLI|gmWye^TiT%_kUMx0fMNxkCxQV#IMERG8rEFn zp`fQ~h)Xb^dTKE}oYBon~^j&)?z6vp9Jl`K0qT2+PPCvN6I$k_apar3S;!w#o=*mZ9q}P|Lbv8H99^O)PPY05+~ZJ@vHEw@L`^mfEXy-(^%1L{FS=1Oxhm z$kIDcSKF4+OfFL&u8e&xOlq$0^$_|b@G<2{3(RXv~vrjpSmnxKXi75x9V) z@$62zv0tsXx+rRB$&b97)+q;WOnZpop2L6Tx-jfe*r3^G*vWF0bs3Oi*miXbA1ea|e!`6Qf{WA1#N zC%n*HZ*>%vHr9qTqJHdhP91|dD#QRhgSQ)pk0UxBDvPbds^}@MRFTs)x|XJ?ni)+* zZQTN$4oq>8<+vl;TAfWINMf>PaGrcTCEP zNL;xJGI#@@og}~9Y_#yDG>jyvIW+J>@uTH=B$o6d{Ig(xeRo4&cAAbFq=zub#NtqU z%An(rrLqsP8OXuLt(U1NBg_GntBU42P3j&)xF@8Of&o1HkBun1T}`@_U9b4w-|n;- z+M|#+K6wKqaCzhd@GR-RuS=Dpw((YdFjjp$a3YQS!bAi~kGph@=>0}coZ09krAcb) z{Z+NjCa5_CCm2XnkLg9=e4L+sFx1x)#T@apGbni7O0uxZka!@CW$WrJ@lL%pd#sJ4 z?nfmgrd0ZfSaTXm8$UjlU_*Fre6FYI3A%2mR6}f~zEcTRmQp))(SktE!L1~S%8sUct)gRc zNm=ER8iBs76P$qG)(AKw&*1AhNn6$wYz;NyT5uQv8FJ8%K9Hw!fHB~KkAaOm9a;QH zrz*cwO;U%%h84m1Cu*t3AS)yjAF3c!WETUA|EoD8-|82mkZ1J9lt1v=IA>WX zYosVf*%GUCxKc;jRgmy90+WxOI-u!FT0pB&Q8iki^dpsyHT@PazmMBTP}wau)-q92 V#T1SANEb4n)y`P{`a4r!|Jjl7_W}R_ literal 0 HcmV?d00001 diff --git a/Dragon Warriors/d4.jpg b/Dragon Warriors/d4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38a82051368b265249e6e38bc37615c02cec61f7 GIT binary patch literal 1523 zcmV5C8%J1OWpB0|EsF0RR91 z009C600adQAqEmL6G2fFA~Iot6(ci3p$AfNa*?tB+5iXv0000#0R2{!r9`>QV(jiC zw7a~53FiKsQb>sH?Z6}x=B3h$Ib-_{ zNUG_&YQasST_@GaG?EM1qyxI(x*hlMcA)+%;ds}IlZSb+lb)ZxnWieOC4};lWR?I% z(TV(|k9t1kbbe~)l%*+3iImA(Vr<^>=#mtLNY|Mpk&coy9_+_}DlQtr=}TpD!GDQe zE}c~OBoS<~TcP+H`;YfGJ~gSAkr^J{fZ2|4+eQwa3BOJc^%6QkBe-BuLWA!4VX* zGaV=ZY?4obs?6o4xGQPZ4*;4AOMuA(hTK-~_O-}fHz^t;e~OYdvTIC^k|N0&4343d zhaiKygZtIZo!nQ}>vImkZGx;c>cHudhqD4SMSIees>dJ3E*c^? zkGFkEzC`k=J5SXVj(%H@0PezAqnb8`RSz7BRn>;U2Z9Y%bq-Ek4l*fhqKGf84Zn26 z$88EW)m_N^P!Io4PD zH)(HgGup*8R=-a%iJcli>XR&^wTEcY(HbXXkSkXeq%ClnIbjKSZG%DqyYqmg;ovZuXEOqqhY1DSiMw#P5zO2VC`Zso&H1LLTAv zmy>WrNI?vPk@p`P_VMS&a}+v{6)+fk`Cx`116wxlEklw9yIqM;0RZUlek);T*3&_5 zt<)AW+pywEU`LWZ4vY4Y-mCBLuX@pA@|f(jMtp6|cTuSUnkEbZBVZkPIyEY|mMG?p zqL~&*+!bVC8Av`s2ZK~Oex3TINZd}72*Veh_anUB@Q+@N0L=@JI@`2F60YLro{ztJD zO_S;+vd3Opbu1#zZ$?Fl)Vo?-{in1>;C-x59gU{=-5C8%K0Rsa91p)>G0RR91 z009C61Q7rQArccY22mn1L1A$e6$c}Mf`gGlVxhzT+5iXv0000#0QFrO;#p#a46{1M zi^*ppRDMao)j0Qh_GDKT})r+Br!stL4D#HXH#))?e+bf9gLoLc(JY0oD zl1GoEs6HddJxUMbOwsCYHAA6G73WVQ4;v}}0L>$t(|et0=Zj_C4OnGth^LIss2JtI zJ;gs>51(>%_iC}}?YU#yHlQzAqX~%qmN6qJB(o`TgiNvdOARoQH=C#e$h&HuTcj;nss4?qHo9?C-nS0h$s;{_Mn{pl*swM^C-IFq(W6=V8?w>#{@4PEEZgX>S{&o9 zPl%sM8(yA9;p@oq_!DKn-8S&>*&>{DY(T9{ZVn2}|U;hA2GSQ=0 z%CS9dlV;y!jiwt*SnniYyNKPIH<3W{R1BUojOnF+RaD$JTGh747AeXZWU#7wJGf?4 z3~|m7{SJQE)RpA9KF7GV*Y1{*`owtRE~i-6fIKf6YfU?KAdeX6hBe2w6b&W6c46s; zmdwoZPcLN1fmMikieLZ$`FPZugcai4wn|lkM!9Zt9E0atlys3p#=(^MWgvt8wbqRzpp$xPKhW46&9Pa` z7Kbkgb}!K|_64|c#y)I$Hg_$lEzps6zSV0i@z{oSMCtCwf{fTxo(406#-OiK?%nB$ zE8caU)OD;hjUNikde~!u?mn7uhbX7rMw3IZ+I3p@?R8XwZsagRrY0meaZHbr#{~FX z4}9sJ+mv?rjmz^#UNi?X%2fa!NXh(o*NW~*W7J-$ySZ$xL^4=1M_{R3AW(qwhUWz1 zkG?gb*gtwnyE|Qp?K*Ua5fbqNI2~+ARVN+^BaM1S-Y<%&`-ww8Jzc*T`e*5!dB+;F zqf1(anlg8`mI5NhrKKUnO`b`N^V@H?%6*5OcP0APY0kJ|BF03O*kWbK#tP@}!5kl< z)LXBp_DzNrZPwgyF;UYNdZur}46*+JTFt+$H_iPDdQWbaIQp^ryHS&o?u(GW)tmZh ze80o5Q13TIt>bVC2nFPKHl@h=EPXM?gYZcEYePr)b?K^Q8d&7EQv@xCEfz;PD7`3o z=a6-!jyU2$97?E)Fcm;mAAmL1jT$vl{@G7)PMa!vg0if!vqvh17+@JlARnmlrPX~C h>3WtwRO1jT$s-|JjYfpa%c| literal 0 HcmV?d00001 diff --git a/Dragon Warriors/d8.jpg b/Dragon Warriors/d8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0ebf246193dc827eee30909bc566741c5648e618 GIT binary patch literal 1584 zcmV-02G9Bb*#GVT4nbsZVr2ki000000RP(nLjVj22nYxW3bbGKjhy{OGkA} z6B<^dH7=m)XdL7+{+U%oU~2x28Z>K(W{LzdOu-a+o<84QR#~pw&vJ&WU+zjX zDfd+J`nT<`4PSzc%T_aH%VB%TTQARYZEb`fsxyT9z!)Jw$R0jAZ5;3K#_~>AuvUK#B zJD!i&W)w$cRyMF?nuX2GwP_lQ?Mx|Mk zrOK%w^byiVM+9UZG+H!kIYv7V+2Ji^9}`aPw~c(;y0b84&Oez!8hu*CR_n)R6PV>d z>V1zo^5wWF){@nNL~*Gn0J9%p2PEq^f42P*#a^WwP~5vTP*V8FnmA-KkUH`S;3?`L zc4w)S#3Az4;0F=4@FfV0j(yD8e6fBn${E3alQR#k-zs-)reG;>kcAvWQ2NT z<=5;^N3qp@(9@RY+*S}-<8_mu9Cawlvi|_pj+6GoaiO_(a7R)5*{)3rR_>SyW0$B9 z_|8EGkH5Z|?Ykw)*9G0m`(KhcL@<_)I7+Yc7AyIfpFTdCmvLm4$_dC6=%Ke~Adp#k zh{ta9zOb#%)-16Ddec&dXvB(zLD>;%Sxq6kwR};wP{_e zD=IYI-{LUK9CVBVbL26rGFnT!ZryGrRTiyNk%00fhd+KXry4YA4cMlm6}T)HO15k? z@Lh#_#;onq;K;n32Ly&3V}p+!UfTAWlxrfRd_nJCz?p*cB)q$?NC0Oi_tdhwRJGqf z5!mQPVc;Bar2Rq0eYI~?$5q=Ic>^9{6wVp zk@v0mr5C`lPy*wSM~1UAcCgDF75gtyYweV0?^a7JRpn*s>B3-;y+=66W9_E9Z}^v8 zto#=B0I4Pc5-X0ApAVIeLH5bk&I#eO63<=4k+{mboP*{4#-!1z4Yxf~W!juTNy}Gk zn#_Fo9HIALxH{z8hUzxoxJ1=vkYl@(^06F)8;_N_=hxH?KsSXkM?*bV-d3z*$m#_F zEg|Rf^o-|9H~!mD?Cc-I_Qe~XZ*oy1O@y!SF9s>j=3Ey z(#E1z3UZ?d=JDsB+gc5qW{YKj*Mdi6W@jpTLiI7rFaQi^Omt}162%ngW0^yt@m3ic zPTi8*-qiMjgk;fcJBZ*ZMcq)LPeTKTxum9OzW8=~Q literal 0 HcmV?d00001 diff --git a/Dragon Warriors/sheet.json b/Dragon Warriors/sheet.json index 5a7526b060ec..551d560da143 100644 --- a/Dragon Warriors/sheet.json +++ b/Dragon Warriors/sheet.json @@ -5,5 +5,5 @@ "roll20userid": "630718", "preview": "Example - clean.png", "instructions": "", - "legacy": true + "legacy": false } \ No newline at end of file diff --git a/Dragon Warriors/twod10.jpg b/Dragon Warriors/twod10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f420349a410240eda02e3fa9c748b98a891b0e0 GIT binary patch literal 6635 zcmbtYXE+>8v|hbO7OU4qv>-%?9<1KOD#1#$XuEnRf@rJv=%PdmtFBI>mxv&-df7$v zL>Gjc@Amui-upi9oafA$bIzP+X8xSHoxNQEr~vTs{=q*I{~r(%{3D472?+>^iHM2+ zb&!ye5|faT5EGM9kdl%AgTERj1v%wElYf%@TPQve0Ra&?2{FmPy8N%i?MDER6i@^x zBESO!@PT*)K)l<206PE=fR9h`w=}?ifP|EYn2?Md51-)gy3}0&9swaf9>HJW6O#P( z`KuEGh=@r@fiz^aTy$VDkhl`JvLQJ=&(jxS42%*g5F3xbfpq^Z9}aC9>xjpABS?QKc;G?<_4 zX@8}a7$OTS8413Ar9J;dFMZOPW^H5Qo4VH_hIu&?_T20sYrDRHvV?3-CgW{{TRVDN zN^s@C!meS@?#1N2{&;IJkk(pJF!lS)xl|>M*rl1Y>y*qN?OoClhSQGY*fX%tRJFnL zs;cvO-agbOnw7neLC+J#Td$r@_3X@8touona4M-4H)-?3vY$gEgWt1E*FeTpuL2Ju zsHE~J$`RwXo&D2UUH&2*=w%l=t^GKKs#kbRpI$3RZ~WeI5t~%p6dfIZJ7W~TnQ0WcIH21u| zp_mdz|E5?~o{Mn8q=nadzwh#%^F~%7GtS}LUrc`0Z&{T1&MviCv72yPotHCn-b9K; z%NRPjnc)tk@i%)PE0aPf&Wiqw(-a%{hG~^Eo2Cb^W7-c^>dqvo9M=)(_9tX#ROMxF z8MCt1IEM48DI@4SzGQ81wW}2f77S%MW*Vt`GU#}!-?d!Pa%Gg-5|;a*OS-NECVcZ} zazovNXck3%F0qA|bR?kEHkDrV^ncQHz?kkSF9f2W0Yx>_cr^+QdnoWa>_(klp6-0h zqzsVDU^rz-d*_C%#7sDzWMXcgwSGALU)f@?_nu#3TFa`Oiy7ve6?9 zZle83d*gh#RD$7BoPJz*$+~=Nfe@61cjPo0B(H+LDaszuiF@!Fo?}GQ-@1UWTe9;` zzoiioP|obscazKCpg%CZtx1$+gzKSgV#Xyh-AP?@s6N4Z9&EwHWi2z0#uD-_HGr{w z*`D`C4BF{@_3P#s4vyJx0TQfB(Zh<`g@&%=Zj3Dlrg4i3@15d5s0bA-N}v6%zclt} zA)46Ia2p3vmCHqssCQpSl`Qs6ix!+KH9CiQ?Sy(!JxOR|-*#=o^?~=n^EkUH)ypz* zl1OGlpf&x_Q7P|*#mfM!HKVvZoI-zHE~KvB?V-4Jv-_QqvCh^?cGlEavoj)}dvinxv1-FLQQmJ{8)Exs9}xe|9Mfe255gtY1+NGfoCI9X-{>8#pCfVZCg1 z$GEx0_@CAFyOT;?6{ytKABDM(l@6!s{-K!Y#`S0bsF;}54~Hj<<^+!uE4mq+>}* zlc9zngIBV@YrceOJq6e=xKXY)4-! zc71*_aIxE-UsZ_s^CEkFx#n%QRqfQO&2NQ>HkHO@;q!qc@j3q%Sh1F3xm}0TicjVJ zv~V1Pi^pJJhGD#Z9QTkE(`QGu%YhNeN5A_{oCFQ4pOvi|;i_>BtHpo5)zBZ0GHs}-ts z1aet%l6c#lKZs-iB-Ft z@ko{gjwQ@8emL?S-$-=kY=~)zmd!d@()zO}-Ng(^kjAye?|93XzxACpsjbd0Eb+|ZeH1^%Seg3l$y#8+(Ukl3kbR2Hd!_{}p zJIB+iQ_H75k|{dh|J$Mp806E(YYb-cxKVo=KxjxQZWQc#j=; z(Zpxht$p>(krH#EMYY+?*3%=A_`050yW?y|Hn!JqVtZv+lycxQ9C*a(#L8o;kJ=*y z!zO_ss37l%=d#O@)oJ}U1@pG+lZi^EO?y{on5qOY^nyMd>I`PkDmcNO6EWNZGs3q8(#%$o#$wbm+yH)<<5l9$Vt9xL@tPRWlqFc*WNGl9`}mob zas6{^%8{il6+^?<2>$hYqJEWt;r-Ss$Z7-cK6x?9ao%U%M~TqW=ruD%hHM8rj=1T2 z>kL)w&P9?PW-N*~Zm?w-aRnBNpU0Qo1F#5wO8p{Av^6S=Z&hxCHjV5Ey}z9IykC;N z|4m9m#OsY7krzyA{h|*FJn2sE>d$jP**55I0U2r~SA0At473uodFAVy_O$dbZ8orO zdVfTW4&+5NY2Dw&xuOxRHe>vxG4dgADt~p&@P#b|nb>t;9L<_G$6M^)Is_+6B8Wr? z)4W*|+|M}|4d{9t6MC0--*AwV2pbxLOpBUM%J@N6U6Amx+WHS9Ss0dLi(A02&=*Q= zi<>2aE|(Gq`=<1mYkV=O73d8;KWfP8d+Z01AY`aId}i^S3nF3#3%9KFEm_o+>^n6rt;`eQ(HrC_MD zD3o@-p^}Y3!Q(Y13+nC!tWGFMPq*_l-wVLBU+K&);fz(8(adZvHVTNMX|FC&gl%( zM8o2G%(jMw37Lv@-dy3bb|Z6dO(`-ND2Ddo=Sn)YzF)29ctNnl6^);r02Far&ZVUV z`unkPo3n!RM(a)CLKb1iW+0CF9*+fzY7`>$x<9kD43vEfX!~vtGF|rTPho{H-vYMv zM-#=|vlvIgUVQMCN8KN1rG>I&Gnvv|guXmXz&+9Hg!iHEw-)t^7aR&aevj0i@{S>` zwmI<2L#eMT{?1*c`ZClg@$GEn^RD>|Q^|XDFFTHe%2J*^a% z%5qZ=9)=`U_fmDQFn^w&I-G&yu|ia{;0M)D=J|Rh!M)MQ;1Jx6V3OC%a8}8+<$ziy zT-2vlXPush!)3jV6NUAbHbaT3{CZ*v*El09<3Nbx5%jHYbvT~5s}FD+B>3^jC`-;} z$V^l`pc{0=g9&j8ZJLXBgMGoVlxca+$*@5#}oZ>|^1NHbzk z*wWXbopImJx=c4$XqLdeS(k80N5RfRax~FB!r}sHTQmpRD5F*-U zDD(mX`F&6+QnI!wyhEL?d`iB4zoX77LL|j&Qh?~3J0XtMk=17Y7SOOG8g~?o#M%|` zlpb@<6F7oIE+ZXUGCqnaJi^j)Bm^!6d~j8&tnX`%hTnr_`-E=D>KLO2jY6 zwj`Vncd7R4D6(|yIc7cfb?Mec48qIo>g5G0^hclwna+4*ssC2->sp2b`gx!A;uwAy46IxLIGo(gz`J-&|tN3pL=`}anl%vmans%)4kA@yCB=uaz z+lGdr{FTOT(?Jo}rUNY~Fq$m_X4?|_VJUU_^_}^7k2vlDa%n|+S!X1bf9tk@e+(+6 zD)=OwL*o738u6Q9Hq6c2U_i&FpOj%~ZpcUXvsDXb5>1jpRjeCYo-aBp9C%IbSokBO z6aAwi-OT?$by!$C=0*D%LK_j6B9*kHe0Fm0OOQsioE7l^lffa7e=|f*IT24%tJ0U# zV)fa(NATue2MJ##yi9KNYbxZcyQ&I6#jT8?k;5^C7l~g68c1WVh29t?36$Ne@)*Oi zF02b9_0wS){QRLcXz3O|uXcvWOUjy=0H$ul{?VOhqy9Q|WA*U?$xGos-lF@EYuDLi ze_ktts~juo13j%u5Bm_2EuurHubvjvoSu{<^0EH0tT4nq$h4`p&NA+ljoH&!E$EDp z`TS*jO;Rj4qp;JFb0hJso2C`oxLR^*(!5dB_II$7ens@7H|H-jIib9dk6yF`RvBzU zas(M7)h<>D0=$sBceLGL`Ul#?>VDyo*6*g@`&^*lk>=6Ijf1#=)|(O^{vZ+e__khT!e<{UP0L_eYX&moZqsIw znMN6}KMJs%OAdBRQ%jfKYctWu>W^55b=I|^#=Po07k`wabI2~ZW7w7BFdKpgPs2MG zyM!*JQsz>J@|=DgN#0%HrMS`cNEIxqc=weq2~TNT21uu$c)1TXL41641F9AyHM`R> zSZuyGv&t2Tc(W1#=VD^=F5J+F$p{rJt?CgnM;bV?rcS%GolYq=YLI3>3Sa&HldR(| zxTgD%jm*q%L&kuI+y2wdCd^wwuA|}>Ae(^ryo9~8r9>$*$+NkhUYn;fbqG#=aYo)P(|U#P zvOp*e&Gy~Yk{&%d#E{Jl3pLlk!i(u)DG?*jblvuz?`fx{BLOt$Q)d%Nz25o3d;_Mn zY{z%{+NH5yM%E_S(eb)LXyJmJ>9kk9%aJY-!SSDB^p1EB6NFXkk(YwSU3*Q%BvY~$ z1=>w#)Z`arBu+b-HHXhd)|?%DLfW4QOz!y#{Kn6p!NSF#L#QNokyVPq$jT~j@(SSi zMC45w)4lqUfPs#Hn#|q(M!RhP?q{c6IVa!pwC%we)LJ4>~J#a$o{M@zL4_0QiZI_B^53Wbk+A_9tLmJs8J%yeC`9`#C=+HYMa zE@26A1O(3(OMQ*khKR%7CeAU38kLDZJc5E0s>T*;9|+T*A7ISkLvf(AKuB~fA+xKY z@!wZW8iTCr!G?EV+HZOs{+a`FW zcncZhaSjGtV<|smuqv1r^!x$xJkw2k7Wmr?&D%he_Msn1m-&xDncFVQ6_NeH$M!fT z9ch!esqtL5W;MrlV~D9HCLzmc->1=l7GH@6!lj31*KyZQ&!z{Py9u4h|8UySkpLpH zSc#|UgU*}oTm@vOI$Zq%d>>L=dloguNmv}Ng;X_{dRf}to)#JBtIO20_$skc)U`D(Nw&%}jeq_r_dvULI8*Ji655=;gsi`!fk?S8Ka z)>x}dExs|hF}gsBv-;&u^k~+aSo!Kvmo!vwN~haM#qkbQQ<9}Uhh?WuN3e{|*?&Ub z0=^09zfK1KCPyME-c&9i>Q0}Gx4Bgw)=D2%8y)D-47}{+ih}1P*5$QS{zMNGoQ(DhDD45x@Fyl-B`U&Zf0iVSw4_`{Nj|luz!E3!DfOVEGP&3 zs(=oZJ`86gLm!c-IJOj$DhRel0-qQMMx5`C{nLMl*# zM5EZP@Uv;Lcj?i_nA%~8dNZt=py3aThlqv+xuVGL!gjA8>rIr4scdKT^31kiE#=8Z zr