brancalonia v1

This commit is contained in:
Nic Bradley
2022-05-23 22:49:50 -07:00
parent d5aecec241
commit 0525048b2d
166 changed files with 38143 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

+97
View File
@@ -0,0 +1,97 @@
include src/pug/components/components
include src/pug/abstracts/variables
include src/pug/abstracts/hiddenvariables
.compendium-drop-target.monsters
input.npc_toggle(name="attr_npc", type="hidden", value="0")
input.npcspellcastingflag(name="attr_npcspellcastingflag", type="hidden")
input.toggleflag(name="attr_rtype", type="hidden")
input.toggleflag(name="attr_confirm", type="hidden")
input.toggleflag(name="attr_cancel", type="hidden")
each val in ['Category', 'Name', 'data', 'Content']
input(accept=val, name=`attr_drop_${val.toLowerCase()}`, type="hidden")
// Drag and Drop Warning
input.monster_confirm_flag(name='attr_monster_confirm_flag' type='hidden')
.dialog.dialog--confirmnpc
.dialog__wrapper
.dialog__explain
span(data-i18n="replace-sheet-with")
span.dialog__newname(name="attr_drop_name")
.dialog__buttonrow
button.dialog__button(
data-i18n="Confirm",
name="act_confirm_npc",
type="action"
)
button.dialog__button(
data-i18n="Reject",
name="act_reject_npc",
type="action"
)
.dialog.dialog--warning
.dialog__wrapper
.dialog__explain(data-i18n="accept-compendium-drop")
//- NPC
.container.npc
include src/pug/npc.pug
//- PC
.container.pc
include src/pug/layouts/headers/header
include src/pug/layouts/utility/navigation
input.page__switch(name="attr_tab", type="hidden", value="core")
.page.core
include src/pug/layouts/tabs/core
.page.spellmoves
include src/pug/layouts/tabs/spells
.page.bio
include src/pug/layouts/tabs/bio
.page.settings
include src/pug/layouts/tabs/settings
//- .compendium_warning
//- span(data-i18n="accepting-drop-u") ACCEPTING DROP FROM COMPENDIUM
//- include src/pug/layouts/utility/dialogs
//- ROLL TEMPLATES
.rolltemplates
include src/html/attack.html
include src/html/attackdamage.html
include src/html/damage.html
include src/html/description.html
include src/html/dmgaction.html
include src/html/npc.html
include src/html/npcaction.html
include src/html/npcattack.html
include src/html/npcdmg.html
include src/html/npcfullatk.html
include src/html/simple.html
include src/html/simple3d.html
include src/html/skill.html
include src/html/spell.html
include src/html/spelloutput.html
include src/html/traits.html
//- SHEET WORKERS
script(type="text/worker")
include src/js/classes/SheetUtils/SheetUtils.js
include src/js/classes/FlagManager/FlagManager.js
include src/js/helperFunctions.js
include src/js/sheetworkers.js
include src/js/classes/DropClasses/DropClasses.js
include src/js/dragndrop/dropFunctions.js
include src/js/dragndrop/DragAndDrop.js
+183
View File
@@ -0,0 +1,183 @@
@import url("https://fonts.googleapis.com/css?family=Playfair+Display:400|Playfair+Display+SC:400|Libre+Baskerville:400:700|Dancing+Script:400|Quintessential:400&display=swap");
$externalImgsPath: "https://app.roll20.net/images/dndstyling/";
$imgParameters: "";
/* SANITIZATION CHANGE FIXES
============================= */
@import "src/scss/external/sanitization-fixes";
/* GENERIC STYLES
============================= */
@import "src/scss/generic";
/* PLACEHOLDER STYLES
============================= */
@import "src/scss/abstracts/placeholders";
/* ROLLTEMPLATES STYLES
============================= */
@import "src/scss/rolltemplate";
/* Refactor
============================= */
.container {
@import "src/scss/generics/gridsystem";
@import "src/scss/generics/options";
@import "src/scss/generics/hiddenflag";
@import "src/scss/generics/RollButton";
@import "src/scss/generics/StandardInput";
&.pc {
@import "src/scss/pc/Header";
@import "src/scss/pc/Navigation";
@import "src/scss/pc/AbilityScore";
@import "src/scss/pc/Coins";
@import "src/scss/pc/DeathSaves";
@import "src/scss/pc/Features";
@import "src/scss/pc/InsProf";
@import "src/scss/pc/Moves";
@import "src/scss/pc/SavingThrows";
@import "src/scss/pc/Shields";
@import "src/scss/pc/Skills";
@import "src/scss/pc/Spells";
@import "src/scss/pc/SpellStats";
@import "src/scss/pc/ToolsProficiencies";
@import "src/scss/pc/OtherProficiencies";
@import "src/scss/pc/Vitals";
@import "src/scss/pc/AttacksSpellcasting";
@import "src/scss/pc/Bio";
@import "src/scss/pc/Exhaustion";
@import "src/scss/pc/Equipment";
}
&.npc {
@import "src/scss/npc/npc";
* {
font-family: sans-serif;
}
max-width: 800px;
}
button[type="roll"][type="roll"] {
padding: 0;
margin: 0;
line-height: inherit;
}
}
.charsheet {
input[type="number"],
input[type="text"],
textarea,
select {
width: 100%;
color: #c00;
}
input[type="number"] {
font-family: "Dancing Script", serif;
-moz-appearance: textfield;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
}
}
input[type="text"] {
font-family: "Quintessential", serif;
}
}
.container {
width: 100% !important;
}
.pc,
.npc {
display: none;
}
.npc_toggle[value="0"] ~ .pc,
.npc_toggle[value="1"] ~ .npc {
display: block;
}
.page.core,
.page.bio,
.page.spellmoves,
.page.settings {
display: none;
}
.page__switch[value="core"] ~ .page.core,
.page__switch[value="bio"] ~ .page.bio,
.page__switch[value="spells"] ~ .page.spellmoves,
.page__switch[value="settings"] ~ .page.settings {
display: grid;
}
.charsheet .repcontrol {
min-height: 2rem;
margin-top: 0.5rem;
padding: 0 1rem;
button {
min-height: 2rem;
max-height: 2rem;
min-width: 2rem;
max-width: 2rem;
padding: 0;
border: 1px solid rgba(black, 0.5);
border-radius: 0.3rem;
background: none;
font-size: 0;
&.repcontrol_add:before,
&.repcontrol_edit:before {
display: block;
font-family: Pictos;
font-size: 10pt;
text-align: center;
}
&.repcontrol_add:before {
padding-top: 0.1rem;
content: "&";
}
&.repcontrol_edit:before {
padding-top: 0.2rem;
content: "(";
}
}
}
.charsheet .pictos {
font-family: Pictos;
}
.charsheet * {
font-family: "Quintessential", "Baskerville", serif;
font-size: 1.4rem;
line-height: 1.33;
}
.charsheet button[type="roll"]:before {
display: none;
}
* {
box-sizing: border-box;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
{
"name": "brancalonia",
"version": "1.0.0",
"description": "A character sheet for the Brancalonia RPG for use on Roll20",
"main": " ",
"scripts": {
"start": "run-p compile:*",
"compile:sass": "npx sass Brancalonia.scss ./Brancalonia.css --watch --no-source-map",
"compile:pug": "npx pug Brancalonia.pug -o ./ -w -P"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@prettier/plugin-pug": "^1.13.5",
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
"pug": "^3.0.2",
"pug-cli": "^1.0.0-alpha6",
"sass": "^1.32.8"
}
}
+163
View File
@@ -0,0 +1,163 @@
{
"html": "Brancalonia.html",
"css": "Brancalonia.css",
"authors": "Acheron Books, Nic Bradley",
"roll20userid": "",
"preview": "Brancalonia.png",
"compendium": "dnd5e",
"instructions": "Compatible for use with Acheron Books' Brancalonia. \n\n* Drag and Drop compatible with the [Roll20 Compendium](https://app.roll20.net/compendium/dnd5e/BookIndex). Instantly import spells, items, and NPCs into your game.\n* Auto calculations and workers help remove bookkeeping and speed up your game.\n* Built in roll buttons and templates make using your abilities easy and the results pop.\n* Customizable skills, attacks, and spells.\n* Settings for advantage, GM whispered rolls, easy damage output, simple inventory and much more.\n* NPC Sheet with traits and rollable actions.",
"useroptions": [
{
"attribute": "npc",
"displayname": "NPC",
"displaytranslationkey": "npc-u",
"type": "checkbox",
"value": "1",
"description": "The NPC option sets new characters to default to the NPC card style sheet. Useful if the player characters have already been created and all new character sheets added to the game will likely represent none player characters.",
"descriptiontranslationkey": "npc-info"
},
{
"attribute": "rtype",
"displayname": "Roll Queries",
"displaytranslationkey": "roll-queries:-u",
"type": "select",
"options": [
"Always Roll Advantage|{{always=1}} {{r2=[[1d20",
"Advantage Toggle|@{advantagetoggle}",
"Query Advantage|{{query=1}} ?{Advantage?|Normal Roll,&#123&#123normal=1&#125&#125 &#123&#123r2=[[0d20|Advantage,&#123&#123advantage=1&#125&#125 &#123&#123r2=[[1d20|Disadvantage,&#123&#123disadvantage=1&#125&#125 &#123&#123r2=[[1d20}",
"Never Roll Advantage|{{normal=1}} {{r2=[[0d20"
],
"optiontranslationkeys": [
"always-roll-adv",
"toggle-roll-adv",
"query-roll-adv",
"never-roll-adv"
],
"default": "{{always=1}} {{r2=[[1d20",
"description": "D20 Rolls output according to this option. Always Roll Advantage is the default setting and will roll two D20 on every roll in case of advantage. The expectation is that if there is no advantage or disadvantage you use the left most result. The Advantage Toggle option adds three new buttons to the top of the sheet so that you can toggle advantage on a case by case basis. Query Advantage gives you a prompt every roll asking if the roll has advantage. Never Roll Advantage always rolls a single D20 on any given roll, expecting the player to roll a second time in case of advantage or disadvantage.",
"descriptiontranslationkey": "roll-queries-info"
},
{
"attribute": "wtype",
"displayname": "Whisper Rolls to GM",
"displaytranslationkey": "whisp-rolls-gm:-u",
"type": "select",
"options": [
"Never Whisper Rolls|",
"Whisper Toggle|@{whispertoggle}",
"Query Whisper|?{Whisper?|Public Roll,|Whisper Roll,/w gm }",
"Always Whisper Rolls|/w gm "
],
"optiontranslationkeys": [
"never-whisper-roll",
"toggle-roll-whisper",
"query-whisper-roll",
"always-whisper-roll"
],
"default": "",
"description": "All sheet rolls are sent to all players in chat by default. Whisper Toggle gives a set of buttons to quick select your preference on the fly. Query Whisper option gives you a prompt with each roll of whether or not the roll should be sent privately only to yourself and the GM. Always Whisper Rolls will send all rolls only to yourself and the GM.",
"descriptiontranslationkey": "whisp-rolls-gm-info"
},
{
"attribute": "dtype",
"displayname": "Auto Damage Roll",
"displaytranslationkey": "auto-dmg-roll:-u",
"type": "select",
"options": [
"Don't Auto Roll Damage|pick",
"Auto Roll Damage & Crit|full"
],
"optiontranslationkeys": [
"never-roll-dmg",
"always-roll-dmg"
],
"default": "pick",
"description": "By default, attack damage rolls are not rolled until the hit is confirmed. Damage is rolled from the chat roll template by clicking on the name of the attack in the right hand bar, which then displays the damage. The default method is compatible with 3D dice. Optionally, you can choose to have the Auto Roll Damage & Crit option which will roll damage and critical hit dice at the same time of the attack, presenting all possible outcomes at the time of the attack.",
"descriptiontranslationkey": "auto-dmg-roll-info"
},
{
"attribute": "init_tiebreaker",
"displayname": "ADD DEX TIEBREAKER TO INITIATIVE",
"displaytranslationkey": "add-dex-tiebreaker-u",
"type": "checkbox",
"value": "@{dexterity}/100",
"description": "Adds the character's dexterity score as a decimal to the end of the initiative bonus for purposes of breaking ties.",
"descriptiontranslationkey": "init-tiebreaker-info"
},
{
"attribute": "cd_bar1_v",
"displayname": "BAR 1 VALUE:",
"displaytranslationkey": "cd-bar1-value:-u",
"type": "text",
"default": "hp_max",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 1's value to this attribute.",
"descriptiontranslationkey": "cd-bar1-value-desc:-u"
},
{
"attribute": "cd_bar1_m",
"displayname": "BAR 1 MAX:",
"displaytranslationkey": "cd-bar1-max:-u",
"type": "text",
"default": "hp_max",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 1's max to this attribute.",
"descriptiontranslationkey": "cd-bar1-max-desc:-u"
},
{
"attribute": "cd_bar1_l",
"displayname": "BAR 1 LINK:",
"displaytranslationkey": "cd-bar1-link:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, link the Bar 1's value to this attribute. If set this will override all other bar settings.",
"descriptiontranslationkey": "cd-bar1-link-desc:-u"
},
{
"attribute": "cd_bar2_v",
"displayname": "BAR 2 VALUE:",
"displaytranslationkey": "cd-bar2-value:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 2's value to this attribute.",
"descriptiontranslationkey": "cd-bar2-value-desc:-u"
},
{
"attribute": "cd_bar2_m",
"displayname": "BAR 2 MAX:",
"displaytranslationkey": "cd-bar2-max:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 2's max to this attribute.",
"descriptiontranslationkey": "cd-bar2-max-desc:-u"
},
{
"attribute": "cd_bar2_l",
"displayname": "BAR 2 LINK:",
"displaytranslationkey": "cd-bar2-link:-u",
"type": "text",
"default": "npc_ac",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, link the Bar 2's value to this attribute. If set this will override all other bar settings.",
"descriptiontranslationkey": "cd-bar2-link-desc:-u"
},
{
"attribute": "cd_bar3_v",
"displayname": "BAR 3 VALUE:",
"displaytranslationkey": "cd-bar3-value:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 3's value to this attribute.",
"descriptiontranslationkey": "cd-bar3-value-desc:-u"
},
{
"attribute": "cd_bar3_m",
"displayname": "BAR 3 MAX:",
"displaytranslationkey": "cd-bar3-max:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, set the Bar 3's max to this attribute.",
"descriptiontranslationkey": "cd-bar3-max-desc:-u"
},
{
"attribute": "cd_bar3_l",
"displayname": "BAR 3 LINK:",
"displaytranslationkey": "cd-bar3-link:-u",
"type": "text",
"description": "On Default Tokens created by doing a Compendium drop onto the virtual table top, link the Bar 3's value to this attribute. If set this will override all other bar settings.",
"descriptiontranslationkey": "cd-bar3-link-desc:-u"
}
]
}
+124
View File
@@ -0,0 +1,124 @@
<rolltemplate class="sheet-rolltemplate-atk">
<div class="container">
<div class="result">
{{#always}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/always}}
{{#normal}}
<div class="solo">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/normal}}
{{#advantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{#range}}
<div class="sublabel">
<span>{{range}}</span>
</div>
{{/range}}
<div class="label">
{{#normal}}
{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}
{{#^rollWasCrit() r1}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/^rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span>{{rnamec}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollTotal() r1 r2}}{{#^rollWasCrit() r1}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/^rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollLess() r1 r2}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollLess() r1 r2}}
{{#rollGreater() r1 r2}}<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}} <span>({{mod}})</span></span>{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
{{#spelldesc_link}}
<div class="spelldesc-link">
<span>{{spelldesc_link}}</span>
</div>
{{/spelldesc_link}}
</div>
{{#desc}}
<div class="desc info">
<span>
<span class="top"></span><span class="middle">{{desc}}</span><span class="bottom"></span>
</span>
</div>
{{/desc}}
</rolltemplate>
@@ -0,0 +1,373 @@
<rolltemplate class="sheet-rolltemplate-atkdmg">
{{#attack}}
<div class="container atk">
<div class="result">
{{#always}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/always}}
{{#normal}}
<div class="solo">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/normal}}
{{#advantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#globalattack}} + {{globalattack}}{{/globalattack}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{#range}}
<div class="sublabel">
<span>{{range}}</span>
</div>
{{/range}}
<div class="label">
<span>{{rname}}{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}}{{#attack}} <span>({{mod}})</span>{{/attack}}</span>
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
{{#spelldesc_link}}
<div class="spelldesc-link">
<span>{{spelldesc_link}}</span>
</div>
{{/spelldesc_link}}
</div>
{{/attack}}
{{#save}}
{{#attack}}
<div class="container save">
{{/attack}}
{{^attack}}
<div class="container atk save">
{{/attack}}
<div class="savedc">
<span class="rolltemplate-inline" data-i18n="difficulty-class-abv">DC</span><span class="rolltemplate-inline">{{savedc}}</span>
</div>
{{#savedesc}}
<div class="sublabel">
<span>{{savedesc}}</span>
</div>
{{/savedesc}}
<div class="label">
<span class="rolltemplate-inline">{{saveattr}}</span> <span class="rolltemplate-inline" data-i18n="save">Save</span>
</div>
</div>
{{/save}}
{{#desc}}
<div class="desc info">
<span>
<span class="top"></span><span class="middle">{{desc}}</span><span class="bottom"></span>
</span>
</div>
{{/desc}}
{{#globaldamage}}
{{#^rollTotal() globaldamage 0}}
<div class="desc">
<span>
{{globaldamage}}
{{#normal}}
{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/^rollTotal() globaldamage 0}}
{{#rollTotal() globaldamage 0}}
{{#^rollTotal() globaldamagecrit 0}}
{{#rollWasCrit() r1}}
<div class="desc">
<span>
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{globaldamagecrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{globaldamagecrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/rollWasCrit() r1}}
{{#rollWasCrit() r2}}
{{#^rollWasCrit() r1}}
<div class="desc">
<span>
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{globaldamagecrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{globaldamagecrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{globaldamagecrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/^rollWasCrit() r1}}
{{/rollWasCrit() r2}}
{{/^rollTotal() globaldamagecrit 0}}
{{/rollTotal() globaldamage 0}}
{{/globaldamage}}
{{#hldmg}}
{{#^rollTotal() hldmg 0}}
<div class="hldmg">
<span>
{{hldmg}}
<!-- {{#hldmgcrit}} + {{hldmgcrit}}{{/hldmgcrit}} -->
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="plus"> + </span>{{hldmgcrit}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<div class="label">
<span data-i18n="higher-lvl-cast">Higher Level Cast</span>
</div>
</div>
{{/^rollTotal() hldmg 0}}
{{/hldmg}}
{{#damage}}
<div class="container damagetemplate">
<div class="result">
{{#dmg1flag}}
{{^dmg2flag}}
<div class="solo">
<span class="damage">
{{dmg1}}
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{dmg1type}}</span>
</div>
{{/dmg2flag}}
{{/dmg1flag}}
{{#dmg2flag}}
{{^dmg1flag}}
<div class="solo">
<span class="damage">
{{dmg2}}
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{dmg2type}}</span>
</div>
{{/dmg1flag}}
{{/dmg2flag}}
{{#dmg1flag}}
{{#dmg2flag}}
<div class="adv">
<span class="damage">
{{dmg1}}
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{dmg1type}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>
{{dmg2}}
{{#attack}}
{{#normal}}
{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}+ {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}+ {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{/attack}}
</span>
<span class="damagetype">{{dmg2type}}</span>
</div>
{{/dmg2flag}}
{{/dmg1flag}}
</div>
{{^attack}}
{{#range}}
<div class="sublabel">
<span>{{range}}</span>
</div>
{{/range}}
<div class="label">
<span>{{rname}}</span>{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}}
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
{{#spelldesc_link}}
<div class="spelldesc-link">
<span>{{spelldesc_link}}</span>
</div>
{{/spelldesc_link}}
{{/attack}}
</div>
{{/damage}}
</rolltemplate>
+127
View File
@@ -0,0 +1,127 @@
<rolltemplate class="sheet-rolltemplate-dmg">
{{#save}}
{{#attack}}
<div class="save">
{{/attack}}
{{^attack}}
<div class="atk save">
{{/attack}}
<div class="savedc">
<span class="rolltemplate-inline" data-i18n="difficulty-class-abv">DC</span>
<span class="rolltemplate-inline">{{savedc}}</span>
</div>
{{#savedesc}}
<div class="sublabel">
<span>{{savedesc}}</span>
</div>
{{/savedesc}}
<div class="label">
<span class="rolltemplate-inline">{{saveattr}}</span>
<span class="rolltemplate-inline" data-i18n="save">Save</span>
</div>
</div>
{{/save}}
{{^attack}}
{{#desc}}
<div class="desc info">
<span>
<span class="top"></span><span class="middle">{{desc}}</span><span class="bottom"></span>
</span>
</div>
{{/desc}}
{{/attack}}
{{#globaldamage}}
{{#^rollTotal() globaldamage 0}}
<div class="desc">
<span>{{globaldamage}}{{#globaldamagecrit}}{{#^rollTotal() globaldamagecrit 0}}<span class="plus"> + </span>{{globaldamagecrit}}{{/^rollTotal() globaldamagecrit 0}}{{/globaldamagecrit}}</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/^rollTotal() globaldamage 0}}
{{/globaldamage}}
{{#globaldamage}}
{{#rollTotal() globaldamage 0}}
{{#globaldamagecrit}}
{{#^rollTotal() globaldamagecrit 0}}
<div class="desc">
<span>{{globaldamagecrit}}</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/^rollTotal() globaldamagecrit 0}}
{{/globaldamagecrit}}
{{/rollTotal() globaldamage 0}}
{{/globaldamage}}
{{^globaldamage}}
{{#globaldamagecrit}}
{{#^rollTotal() globaldamagecrit 0}}
<div class="desc">
<span>{{globaldamagecrit}}</span>
<span class="damagetype">{{globaldamagetype}}</span>
</div>
{{/^rollTotal() globaldamagecrit 0}}
{{/globaldamagecrit}}
{{/globaldamage}}
{{#hldmg}}
{{#^rollTotal() hldmg 0}}
<div class="desc">
<span>{{hldmg}}{{#hldmgcrit}}<span class="plus"> + </span>{{hldmgcrit}}{{/hldmgcrit}}</span>
<span class="damagetype">{{dmg1type}}</span>
<div class="label">
<span data-i18n="higher-lvl-cast">Higher Level Cast</span>
</div>
</div>
{{/^rollTotal() hldmg 0}}
{{/hldmg}}
<div class="container damagetemplate">
<div class="result">
{{#dmg1flag}}
{{^dmg2flag}}
<div class="solo">
<span class="damage">{{dmg1}}{{#crit}} + {{crit1}}{{/crit}}</span>
<span class="damagetype">{{dmg1type}}</span>
</div>
{{/dmg2flag}}
{{/dmg1flag}}
{{#dmg2flag}}
{{^dmg1flag}}
<div class="solo">
<span class="damage">{{dmg2}}{{#crit}} + {{crit2}}{{/crit}}</span>
<span class="damagetype">{{dmg2type}}</span>
</div>
{{/dmg1flag}}
{{/dmg2flag}}
{{#dmg1flag}}
{{#dmg2flag}}
<div class="adv">
<span class="damage">{{dmg1}}{{#crit}} + {{crit1}}{{/crit}}</span>
<span class="damagetype">{{dmg1type}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="damage">{{dmg2}}{{#crit}} + {{crit2}}{{/crit}}</span>
<span class="damagetype">{{dmg2type}}</span>
</div>
{{/dmg2flag}}
{{/dmg1flag}}
</div>
{{^attack}}
{{#range}}
<div class="sublabel" style="color: black;">
<span>{{range}}</span>
</div>
{{/range}}
<div class="label">
<span>{{rname}}</span>{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}}
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
{{#spelldesc_link}}
<div class="spelldesc-link">
<span>{{spelldesc_link}}</span>
</div>
{{/spelldesc_link}}
{{/attack}}
</div>
</rolltemplate>
@@ -0,0 +1,9 @@
<rolltemplate class="sheet-rolltemplate-desc">
<div class="desc info">
<span>
<span class="top"></span>
<span class="middle">{{desc}}</span>
<span class="bottom"></span>
</span>
</div>
</rolltemplate>
@@ -0,0 +1,28 @@
<rolltemplate class="sheet-rolltemplate-dmgaction">
<div class="container dmgcontainer damagetemplate">
<div class="row header">
<span>{{rname}}</span>
</div>
{{#name}}
<div class="row subheader">
<span class="italics">{{name}}</span>
</div>
{{/name}}
<div class="arrow-right"></div>
<span class="italics translated" data-i18n="dmg:-u">Damage: </span>
<span>
{{#dmg1flag}}
{{dmg1}}{{#crit}} + {{crit1}}{{/crit}}{{dmg1type}}
{{/dmg1flag}}
{{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
{{#dmg2flag}}
{{dmg2}}{{#crit}} + {{crit2}}{{/crit}}{{dmg2type}}
{{/dmg2flag}}
</span>
</div>
{{#description}}
<div class="row">
<span class="desc">{{description}}</span>
</div>
{{/description}}
</rolltemplate>
+41
View File
@@ -0,0 +1,41 @@
<rolltemplate class="sheet-rolltemplate-npc">
<div class="row header">
<span>{{rname}}</span>
</div>
{{#name}}
<div class="row subheader">
<span class="italics">{{name}}</span>
</div>
{{/name}}
<div class="arrow-right"></div>
<div class="row">
{{#normal}}
<span class="italics">{{type}}: </span><span>{{r1}}</span>
{{/normal}}
{{#always}}
<span class="italics">{{type}}: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}
<span class="italics">{{type}}: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics">{{type}}: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics">{{type}}: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<span class="italics">{{type}}: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics">{{type}}: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics">{{type}}: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
</rolltemplate>
@@ -0,0 +1,96 @@
<rolltemplate class="sheet-rolltemplate-npcaction">
<div class="container">
<div class="row header">
<span>{{rname}}</span>
</div>
{{#name}}
<div class="row subheader">
<span class="italics">{{name}}</span>
</div>
{{/name}}
<div class="arrow-right"></div>
{{#attack}}
<div class="row">
{{#normal}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span>
{{/normal}}
{{#always}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{/attack}}
{{#description}}
<span class="desc">{{description}}</span>
{{/description}}
</div>
{{#damage}}
<div class="container dmgcontainer damagetemplate">
<span class="italics sheet-translated" data-i18n="dmg:-u">Damage: </span>
<span>
{{#dmg1flag}}
{{dmg1}}
{{#normal}}
{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{dmg1type}}
{{/dmg1flag}}
{{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
{{#dmg2flag}}
{{dmg2}}
{{#normal}}
{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{dmg2type}}
{{/dmg2flag}}
</span>
</div>
{{/damage}}
</rolltemplate>
@@ -0,0 +1,93 @@
<rolltemplate class="sheet-rolltemplate-npcatk">
<div class="row header">
{{#normal}}
{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}
{{#^rollWasCrit() r1}}{{rname}}{{/^rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{rnamec}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}{{rname}}{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}{{rnamec}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}{{rname}}{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollTotal() r1 r2}}{{#^rollWasCrit() r1}}{{rname}}{{/^rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r1}}{{rnamec}}{{/rollWasCrit() r1}}{{/rollLess() r1 r2}}
{{#rollLess() r1 r2}}{{#^rollWasCrit() r1}}{{rname}}{{/^rollWasCrit() r1}}{{/rollLess() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r2}}{{rnamec}}{{/rollWasCrit() r2}}{{/rollGreater() r1 r2}}
{{#rollGreater() r1 r2}}{{#^rollWasCrit() r2}}{{rname}}{{/^rollWasCrit() r2}}{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{#name}}
<div class="row subheader">
<span class="italics">{{name}}</span>
</div>
{{/name}}
<div class="arrow-right"></div>
<div class="row">
{{#normal}}
{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}
{{#^rollWasCrit() r1}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}}<span class="italics sheet-translated">[{{typec}}: </span>{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{#^rollWasCrit() r1}}{{#^rollWasCrit() r2}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r2}}{{/^rollWasCrit() r1}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollTotal() r1 r2}}{{#^rollWasCrit() r1}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r1}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r1}}{{/rollLess() r1 r2}}
{{#rollLess() r1 r2}}{{#^rollWasCrit() r1}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r1}}{{/rollLess() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r2}}<span class="italics sheet-translated">{{typec}}: </span>{{/rollWasCrit() r2}}{{/rollGreater() r1 r2}}
{{#rollGreater() r1 r2}}{{#^rollWasCrit() r2}}<span class="italics sheet-translated">{{type}}: </span>{{/^rollWasCrit() r2}}{{/rollGreater() r1 r2}}
{{/disadvantage}}
{{#normal}}
<span>{{r1}}</span>
{{/normal}}
{{#always}}
<span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}
<span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{#description}}
<div class="row">
<span class="desc">{{description}}</span>
</div>
{{/description}}
</rolltemplate>
+19
View File
@@ -0,0 +1,19 @@
<rolltemplate class="sheet-rolltemplate-npcdmg">
<div class="container dmgcontainer damagetemplate">
<span class="italics translated" data-i18n="dmg:-u">Damage: </span>
<span>
{{#dmg1flag}}
{{dmg1}}{{#crit}} + {{crit1}}{{/crit}}{{dmg1type}}
{{/dmg1flag}}
{{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
{{#dmg2flag}}
{{dmg2}}{{#crit}} + {{crit2}}{{/crit}}{{dmg2type}}
{{/dmg2flag}}
</span>
</div>
{{#description}}
<div class="row">
<span class="desc">{{description}}</span>
</div>
{{/description}}
</rolltemplate>
@@ -0,0 +1,98 @@
<rolltemplate class="sheet-rolltemplate-npcfullatk">
<div class="container">
<div class="row header">
<span>{{rname}}</span>
</div>
{{#name}}
<div class="row subheader">
<span class="italics">{{name}}</span>
</div>
{{/name}}
<div class="arrow-right"></div>
{{#attack}}
<div class="row">
{{#normal}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span>
{{/normal}}
{{#always}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span class="grey">{{r2}}</span>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span>{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<span class="italics sheet-translated" data-i18n="attack:-u">Attack: </span><span class="grey">{{r1}}</span><span> | </span><span>{{r2}}</span>
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
{{/attack}}
</div>
<div class="container dmgcontainer damagetemplate">
<span class="italics sheet-translated" data-i18n="dmg:-u">Damage: </span>
{{#damage}}
<span>
{{#dmg1flag}}
{{dmg1}}
{{#normal}}
{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit1}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit1}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{dmg1type}}
{{/dmg1flag}}
{{#dmg1flag}}{{#dmg2flag}}+{{/dmg2flag}}{{/dmg1flag}}
{{#dmg2flag}}
{{dmg2}}
{{#normal}}
{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}
{{/normal}}
{{#always}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/always}}
{{#advantage}}
{{#rollLess() r1 r2}}{{#rollWasCrit() r2}} + {{crit2}}{{/rollWasCrit() r2}}{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollTotal() r1 r2}}{{#rollWasCrit() r1}} + {{crit2}}{{/rollWasCrit() r1}}{{/rollTotal() r1 r2}}
{{/disadvantage}}
{{dmg2type}}
{{/dmg2flag}}
</span>
{{/damage}}
{{#description}}
<div class="row">
<span class="desc">{{description}}</span>
</div>
{{/description}}
</div>
</rolltemplate>
+91
View File
@@ -0,0 +1,91 @@
<rolltemplate class="sheet-rolltemplate-simple">
<div class="container">
<div class="result">
{{#always}}
<div class="adv">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/always}}
{{#normal}}
<div class="solo">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/normal}}
{{#advantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollGreater() r1 r2}}
{{#imposed}}
<div class="label">
<span style="color: red">{{imposed}}</span>
</div>
{{/imposed}}
{{/disadvantage}}
</div>
<div class="label">
<span>{{rname}}{{#mod}} <span>({{mod}})</span>{{/mod}}</span>
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
</div>
</rolltemplate>
@@ -0,0 +1,91 @@
<rolltemplate class="sheet-rolltemplate-simple3D">
<div class="container">
<div class="result">
{{#always}}
<div class="adv">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/always}}
{{#normal}}
<div class="solo">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/normal}}
{{#advantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollGreater() r1 r2}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<div class="adv">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span class="grey">{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="adv">
<span>{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="adv">
<span class="grey">{{r1}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="advspacer"></div>
<div class="adv">
<span>{{r2}}{{r3}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollGreater() r1 r2}}
{{#imposed}}
<div class="label">
<span style="color: red">{{imposed}}</span>
</div>
{{/imposed}}
{{/disadvantage}}
</div>
<div class="label">
<span>{{rname}}{{#mod}} <span>({{mod}})</span>{{/mod}}</span>
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
</div>
</rolltemplate>
+125
View File
@@ -0,0 +1,125 @@
<rolltemplate class="sheet-rolltemplate-skill">
<div class="container">
<div class="result">
{{#always}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r1 reliableroll}}
{{#rollLess() r2 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r2 reliableroll}}
{{/rollLess() r1 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/always}}
{{#normal}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r1 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/normal}}
{{#advantage}}
{{#rollLess() r1 r2}}
<div class="roll">
<span class="grey">{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span class="grey">{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollGreater() r1 r2}}
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r1 reliableroll}}
{{#rollLess() r2 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r2 reliableroll}}
{{/rollLess() r1 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/advantage}}
{{#disadvantage}}
{{#rollLess() r1 r2}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span class="grey">{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r1 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/rollLess() r1 r2}}
{{#rollTotal() r1 r2}}
<div class="roll">
<span>{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r1 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r1 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/rollTotal() r1 r2}}
{{#rollGreater() r1 r2}}
<div class="roll">
<span class="grey">{{r1}}{{#global}} + {{global}}{{/global}}</span>
</div>
<div class="roll">
<span>{{r2}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{#rollGreater() reliablecheck 0}}
{{#rollLess() r2 reliableroll}}
<div class="roll reliableroll">
<span class=>{{reliableroll}}{{#global}} + {{global}}{{/global}}</span>
</div>
{{/rollLess() r2 reliableroll}}
{{/rollGreater() reliablecheck 0}}
{{/rollGreater() r1 r2}}
{{/disadvantage}}
</div>
<div class="label">
<span>{{rname}}{{#mod}} <span>({{mod}})</span>{{/mod}}</span>
</div>
{{#charname}}
<div class="charname">
<span>{{charname}}</span>
</div>
{{/charname}}
</div>
</rolltemplate>
+56
View File
@@ -0,0 +1,56 @@
<rolltemplate class="sheet-rolltemplate-spell">
<div class="container">
<div class="title row">
<span>{{name}}</span>{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}}
</div>
<div class="italics row">
{{#level}}<span class="level">{{level}} </span>{{/level}}
{{#ritual}} (<span data-i18n="ritual-l"></span>){{/ritual}}
</div>
<div class="spacer"></div>
{{#castingtime}}
<div class="row">
<span class="bold" data-i18n="casting-time:">Casting Time:</span> <span>{{castingtime}}</span>
</div>
{{/castingtime}}
{{#range}}
<div class="row">
<span class="bold" data-i18n="range:">Range:</span> <span>{{range}}</span>
</div>
{{/range}}
{{#target}}
<div class="row">
<span class="bold" data-i18n="target:">Target:</span> <span>{{target}}</span>
</div>
{{/target}}
<div class="row">
<span class="bold" data-i18n="components:">Components:</span>
<span>
{{#v}}V{{#s}}, {{/s}}{{^s}}{{#m}}, {{/m}}{{/s}}{{/v}}
{{#s}}S{{#m}}, {{/m}}{{/s}}
{{#m}}M {{#material}}({{material}}){{/material}}{{/m}}
</span>
</div>
{{#duration}}
<div class="row">
<span class="bold" data-i18n="duration:">Duration:</span> <span>{{#concentration}}<span data-i18n="concentration">Concentration</span> {{/concentration}}{{duration}}</span>
</div>
{{/duration}}
<div class="spacer"></div>
{{#description}}
<div class="row">
<span class="description">{{description}}</span>
</div>
{{/description}}
{{#athigherlevels}}
<div class="row">
<span class="bold italics" data-i18n="at-higher-lvl">At Higher Levels</span>. <span class="description">{{athigherlevels}}</span>
</div>
{{/athigherlevels}}
{{#savedc}}
<div class="row spellsavedc">
<span class="sheet-label" data-i18n="spell-save-dc-u">SPELL SAVE DC</span><span>: {{savedc}}</span>
</div>
{{/savedc}}
</div>
</rolltemplate>
@@ -0,0 +1,59 @@
<rolltemplate class="sheet-rolltemplate-spelloutput">
<div class="container">
<div class="title desconly row">
<span data-i18n="desconly">For Description Only</span>
</div>
<div class="title row">
<span>{{name}}</span>{{#innate}}<span class="grey">, {{innate}}</span>{{/innate}}
</div>
<div class="italics row">
{{#level}}<span class="level">{{level}} </span>{{/level}}
{{#ritual}} (<span data-i18n="ritual-l"></span>){{/ritual}}
</div>
<div class="spacer"></div>
{{#castingtime}}
<div class="row">
<span class="bold" data-i18n="casting-time:">Casting Time:</span> <span>{{castingtime}}</span>
</div>
{{/castingtime}}
{{#range}}
<div class="row">
<span class="bold" data-i18n="range:">Range:</span> <span>{{range}}</span>
</div>
{{/range}}
{{#target}}
<div class="row">
<span class="bold" data-i18n="target:">Target:</span> <span>{{target}}</span>
</div>
{{/target}}
<div class="row">
<span class="bold" data-i18n="components:">Components:</span>
<span>
{{#v}}V{{#s}}, {{/s}}{{^s}}{{#m}}, {{/m}}{{/s}}{{/v}}
{{#s}}S{{#m}}, {{/m}}{{/s}}
{{#m}}M {{#material}}({{material}}){{/material}}{{/m}}
</span>
</div>
{{#duration}}
<div class="row">
<span class="bold" data-i18n="duration:">Duration:</span> <span>{{#concentration}}<span data-i18n="concentration">Concentration</span> {{/concentration}}{{duration}}</span>
</div>
{{/duration}}
<div class="spacer"></div>
{{#description}}
<div class="row">
<span class="description">{{description}}</span>
</div>
{{/description}}
{{#athigherlevels}}
<div class="row">
<span class="bold italics" data-i18n="at-higher-lvl">At Higher Levels</span>. <span class="description">{{athigherlevels}}</span>
</div>
{{/athigherlevels}}
{{#savedc}}
<div class="row spellsavedc">
<span class="sheet-label" data-i18n="spell-save-dc-u">SPELL SAVE DC</span><span>: {{savedc}}</span>
</div>
{{/savedc}}
</div>
</rolltemplate>
+15
View File
@@ -0,0 +1,15 @@
<rolltemplate class="sheet-rolltemplate-traits">
<div class="row header">
<span>{{name}}</span>
</div>
{{#source}}
<div class="row subheader">
<span class="italics">{{#charname}}{{charname}} {{/charname}}{{source}}</span>
</div>
{{/source}}
{{#description}}
<div class="row">
<span class="desc">{{description}}</span>
</div>
{{/description}}
</rolltemplate>
@@ -0,0 +1,488 @@
class RepeatingFieldset {
constructor(groupname, id) {
this.groupname = groupname;
this.reprowid = id || generateRowID();
}
buildRowName() {
return `repeating_${this.groupname}_${this.reprowid}`
}
addAttribute(attributesibuteName) {
return `${this.buildRowName()}_${attributesibuteName}`
}
}
class Attack extends RepeatingFieldset {
constructor(name, id) {
super('attack', id)
this.attributes = {
atkname: name,
atkbonus: '', //Part of button display
atkdmgtype: '', //Part of button display
atkflag: '{{attack=1}}',
atkattr_base: '@{strength_mod}',
atkrange: '',
atkmagic: '',
atkcritrange: 20,
dmgflag: '{{damage=1}} {{dmg1flag=1}}',
dmgbase: '',
dmgattr: '@{strength_mod}',
dmgmod: '',
dmgtype: '',
dmgcustcrit: '',
dmg2flag: 0,
dmg2base: '',
dmg2attr: 0,
dmg2mod: '',
dmg2type: '',
dmg2custcrit: '',
saveflag: 0,
saveattr: 'Strength',
savedc: '(@{spell_save_dc})',
saveflat: '',
saveeffect: '',
atk_desc: '',
"options-flag": 0,
}
}
addSaveFlag() {
this.attributes.saveflag = '{{save=1}} {{saveattr=@{saveattr}}} {{savedesc=@{saveeffect}}} {{savedc=[[[[@{savedc}]][SAVE]]]}}'
}
checkFinesse(strenght, dexterity) {
const strengthGreaterThanDex = strenght > dexterity;
this.attributes.dmgattr = strengthGreaterThanDex ? '@{strength_mod}' : '@{dexterity_mod}'
this.attributes.atkattr_base = strengthGreaterThanDex ? '@{strength_mod}' : '@{dexterity_mod}'
}
}
class GlobalACMod extends RepeatingFieldset {
constructor(name, id) {
super('acmod', id)
name,
this.attributes = {
global_ac_name: name,
global_ac_val: '',
global_ac_active_flag: 0,
"options-flag": 0,
}
}
}
class GlobalDamage extends RepeatingFieldset {
constructor(name, id) {
super('damagemod', id)
name,
this.attributes = {
global_damage_name: name,
global_damage_damage: '',
global_damage_type: '',
global_damage_active_flag: 0,
"options-flag": 0
}
}
}
class GlobalSave extends RepeatingFieldset {
constructor(name, id) {
super('savemod', id)
name,
this.attributes = {
global_save_name: name,
global_save_roll: '',
global_save_active_flag: 0,
"options-flag": 0
}
}
}
class GlobalAttack extends RepeatingFieldset {
constructor(name, id) {
super('tohitmod', id)
name,
this.attributes = {
global_attack_name: name,
global_attack_roll: '',
global_attack_rollstring: '',
global_attack_active_flag: 0,
"options-flag": 0
}
}
addRoll(roll) {
this.attributes.global_attack_roll = roll;
}
}
class HPMod extends RepeatingFieldset {
constructor(name, id) {
super('hpmod', id)
name,
this.attributes = {
mod: '',
source: '',
levels: 'total'
}
}
}
class Item extends RepeatingFieldset {
constructor(name, id) {
super('inventory', id);
name,
this.attributes = {
itemname: name,
itemcount: 1,
itemproperties: '',
itemweight: 0,
itemcontent: '',
itemmodifiers: '',
hasattack: 0,
useasresource: 0
}
}
}
class Proficiency extends RepeatingFieldset {
constructor(name, id) {
super('proficiencies', id);
this.attributes = {
name,
prof_type: 'OTHER',
'options-flag': 0
}
}
}
class Resource extends RepeatingFieldset {
constructor(name, id, side) {
super('resource', id);
this.side = side || 'left',
this.attributes = {
[`resource_${this.side}`]: '',
[`resource_${this.side}_name`]: name,
[`resource_${this.side}_max`]: '',
}
}
}
class Spell extends RepeatingFieldset {
constructor(name, section, id) {
super(section, id);
this.attributes = {
'details-flag': 0,
'options-flag': 0,
rollcontent: '',
spell_ability: 'spell',
innate: '',
spell_damage_progression: '',
spellathigherlevels: '',
spellattack: '',
spellcastingtime: '',
spellclass: '',
spellcomp_m: 0,
spellcomp_materials: '',
spellcomp_s: 0,
spellcomp_v: 0,
spellconcentration: '',
spelldamage2: '',
spelldamage: '',
spelldamagetype2: '',
spelldamagetype: '',
spelldescription: '',
spelldmgmod: '',
spellduration: '',
spellhealing: '',
spellhlbonus: '',
spellhldie: '',
spellhldietype: '',
spelllevel: 'cantrip',
spellname: name,
spelloutput: 'SPELLCARD',
spellrange: '',
spellritual: '',
spellsave: '',
spellsavesuccess: '',
spellschool: 'abjuration',
spellsource: '',
spelltarget: ''
}
}
}
class Trait extends RepeatingFieldset {
constructor(name, id) {
super('traits', id);
this.attributes = {
name,
description: '',
source_type: '',
source: '',
edit: "0",
display_flag: 'on'
};
}
determineSource(category) {
switch (category) {
case "Backgrounds":
case "Feats":
return category.slice(0, -1)
break;
case "Races":
case "Subraces":
return "Racial"
break;
case "Classes":
case "Subclasses":
return "Class"
break;
default:
return "Other"
}
}
}
class ToolProficiency extends RepeatingFieldset {
constructor(name, id) {
super('tool', id);
this.attributes = {
toolname: name,
toolbonus_base: '(@{pb})',
toolattr_base: '?{Attribute?|Strength,@{strength_mod}|Dexterity,@{dexterity_mod}|Constitution,@{constitution_mod}|Intelligence,@{intelligence_mod}|Wisdom,@{wisdom_mod}|Charisma,@{charisma_mod}}',
'options-flag': 0
}
}
}
//========== Non-Repeating
class Class {
constructor(name) {
name,
this.attributes = {
class: this.validateClassName(name) ? name : '',
base_level: 1,
hit_dice_max: 1,
hit_dice: 1,
hitdietype: 4,
spellcasting_ability: '0*'
}
}
validateClassName(name) {
return globalAttributesByCategory.classes.includes(name.toLowerCase()) ? true : false;
}
buildSpellcastingAbility(attributeName) {
return `@{${attributeName}_mod}+`
}
}
class CustomAC {
constructor(name) {
name,
this.attributes = {
custom_ac_flag: 1,
custom_ac_base: 10,
custom_ac_part1: 'none',
custom_ac_part2: 'none',
custom_ac_shield: 'yes'
}
}
}
class Race {
constructor(name) {
name,
this.attributes = {
race: name,
speed: 30,
size: 'Medium',
halflingluck_flag: this.checkHalfling(name) ? 1 : 0
}
}
checkHalfling(name) {
return name === 'Halfling' ? true : false
}
}
class Subrace {
constructor(name) {
name,
this.attributes = {
subrace: name
}
}
}
class SavingThrow {
constructor(name) {
name,
this.attributes = {
[`${this.attributesName(name)}_save_prof`]: `(@{pb})`
}
}
attributesName(name) {
return name.toLowerCase()
}
}
class Skill {
constructor(name) {
name,
this.attributes = {
[`${this.attributesName(name)}_prof`]: `(@{pb}*@{${this.attributesName(name)}_type})`
}
}
attributesName(name) {
return name.toLowerCase().replace(/ /g, '_')
}
}
class Subclass {
constructor(name) {
name,
this.attributes = {
subclass: name,
arcane_fighter: 0,
arcane_rogue: 0
}
}
checkArcane(className) {
return className === 'fighter' || className === 'rogue' ? true : false
}
buildSpellcastingAbility(attributeName) {
return `@{${attributeName}_mod}+`
}
}
//========== NPC AKA MONSTERS
class Npc {
constructor(name) {
name,
this.attributes = {
npc_name: name,
strength_base: 10,
dexterity_base: 10,
constitution_base: 10,
intelligence_base: 10,
wisdom_base: 10,
charisma_base: 10,
npc_condition_immunities: '',
npc_immunities: '',
npc_resistances: '',
npc_languages: '',
npc_speed: '',
token_size: 1,
npc_vulnerabilities: '',
npc_challenge: '',
npc_senses: '',
npc_type: '',
npc_ac: '',
npc_actype: '',
hp_max: '',
npc_hpformula: '',
npc_xp: '',
npc_legendary_actions: 0,
npc_legendary_actions_desc: '',
npc_mythic_actions: 0,
npc_mythic_actions_desc: '',
npc: 1,
'npc_options-flag': 0,
npcreactionsflag: 0,
npcspellcastingflag: 0,
spellcasting_ability: '0*',
globalmagicmod: 0,
caster_level: 0,
spell_dc_mod: 0
}
}
addSkills(list) {
list.forEach(value => this.attributes[`npc_${value.replace(/ /g, '_')}_base`] = "")
}
addSaves(list) {
list.forEach(value => this.attributes[`npc_${value.slice(0, 3)}_save_base`] = "")
}
addSpellcaster(ability, casterLevels) {
const spellcastrAttributes = {
npcspellcastingflag: 1,
base_level: casterLevels || 1,
caster_level: casterLevels || 1,
class: 'Wizard',
level: casterLevels || 1,
spellcasting_ability: ability
}
Object.assign(this.attributes, spellcastrAttributes);
}
addInnateCaster() {
this.attributes.npcspellcastingflag = 1
}
}
class NpcAction extends RepeatingFieldset {
constructor(name, section, id) {
super(section, id);
name,
this.attributes = {
name,
description: '',
edit: "0",
}
}
addAttack() {
const attackAttributes = {
attack_flag: 'on',
attack_display_flag: '{{attack=1}}',
attack_options: '{{attack=1}}',
attack_type: '',
attack_target: 'one target',
attack_range: '5 ft',
attack_tohit: '',
attack_damage: '',
attack_damagetype: '',
attack_damage2: '',
attack_damagetype2: ''
}
Object.assign(this.attributes, attackAttributes);
}
}
class NpcReaction extends RepeatingFieldset {
constructor(name, id) {
super('npcreaction', id)
name,
this.attributes = {
name,
edit: "0",
description: ''
}
}
}
class NpcTraits extends RepeatingFieldset {
constructor(name, id) {
super('npctrait', id)
name,
this.attributes = {
name,
edit_trait: "0",
description: ''
}
}
}
@@ -0,0 +1,118 @@
class RefereceSet extends Set {
constructor(...args) {
super(...args);
}
toggle(value) {
const toggleLookup = {
true: 'delete',
false: 'add'
};
const hasValue = this.has(value);
return this[toggleLookup[hasValue]](value);
}
}
class FlagManager {
constructor(reference) {
this._reference = reference;
this._delimiter = ' ';
this._delimiterSafe = '_';
}
async getFlags() {
const entries = await this._getReferenceSet();
return entries;
}
async hasFlag(flag) {
const entries = await this._getReferenceSet();
return entries.has(flag);
}
async addFlag(flag) {
const updatedReference = await this._updateReference(flag, 'add');
return updatedReference;
}
async deleteFlag(flag) {
const updatedReference = await this._updateReference(flag, 'delete');
return updatedReference;
}
async toggleFlag(flag) {
const updatedReference = await this._updateReference(flag, 'toggle');
return updatedReference;
}
async _updateReference(flag, method) {
const sanitizedFlag = this._sanitizeFlag(flag);
const updatedReference = await this._setReference(sanitizedFlag, method);
return updatedReference;
}
async syncFlagsWithRepeatingSection(section) {
const flags = await this._syncFlagsWithRepeatingSection(section);
return flags;
}
_syncFlagsWithRepeatingSection(section) {
return new Promise(resolve => {
SheetUtils.getSectionOrder(section, order => {
getAttrs([this._reference], attributes => {
let values = "";
Object.keys(attributes).some(() => {
values += attributes[this._reference];
return true;
});
const flags = (values) ? values.split(' ') : [];
const sectionName = `repeating_${section}`;
const filteredArray = Array.from(flags).filter(flag => flag.includes(sectionName)).filter(flag => order.includes(SheetUtils.getUID(flag).toLowerCase()));
filteredArray.forEach((flag, index) => {
const newIndex = order.indexOf(SheetUtils.getUID(flag).toLowerCase());
filteredArray[index] = flag.replace(this._getFlagIndex(flag), `_${newIndex}_`);
});
const updatedSet = Array.from(flags).filter(flag => !flag.includes(sectionName)).concat(filteredArray);
let update = {};
update[this._reference] = updatedSet.join(' ');
setAttrs(update, () => {
return resolve(new Set(updatedSet));
});
});
});
});
}
_getFlagIndex(flag) {
const regexp = /_[0-9]+_/g;
const valueAsString = String(flag);
const match = valueAsString.match(regexp);
return (match) ? match.join() : "";
}
_getReferenceSet() {
return new Promise(resolve => {
getAttrs([this._reference], attributes => {
let values = "";
Object.keys(attributes).some(() => {
values += attributes[this._reference];
return true;
});
const flags = values.split(this._delimiter).filter(e => {return e});
return resolve(new RefereceSet(flags));
});
});
}
_setReference(sanitizedFlag, method) {
return new Promise(resolve => {
getAttrs([this._reference], attributes => {
let values = "";
Object.keys(attributes).some(() => {
values += attributes[this._reference];
return true;
});
const flags = new RefereceSet(values.split(this._delimiter).filter(e => {return e}));
flags[method](sanitizedFlag);
const flagAsString = Array.from(flags).join(this._delimiter);
let update = {};
update[this._reference] = flagAsString;
setAttrs(update, () => {
return resolve(flags);
});
});
});
}
_sanitizeFlag(flag) {
const regex = new RegExp(`${this._delimiter}`, 'g');
const sanitizedFlag = flag.replace(regex, this._delimiterSafe);
return sanitizedFlag;
}
}
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>FlagManager Component</title>
<script src="mocks.js"></script>
<script src="../FlagManager.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
.lorem {
display: none;
}
label:after {
content: attr(class);
}
input.sheet-toggler {
width: 40px;
height: 20px;
border-radius: 20px;
border: 0;
background-color: #888;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAJZJREFUeNqsk8sNg0AMRN/6jJQWuKYFClia2y6oghRAC7RBBPfJxSslkfLB8CRfVp7R2honSbyRgR7ogKu/zcAEjMDtpVtSrVZSkbTqM6v3tFX3LB70P0M1qQZF+ynVIP/49rdxsvnCGvbTAL35tqN0SdICXIIGd+Mg5iGJMpsnLMpkHs8tIN6A8ZQgnRLl8DGlo+f8GABcQbtK9MWRHwAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: top 3px left 3px;
cursor: pointer;
color: transparent;
font-size: 0;
outline: 0;
}
input.sheet-toggler:valid {
background-color: #49a9e4;
background-position: top 3px right 3px;
}
input.sheet-toggler:valid~.lorem {
display:block;
}
</style>
</head>
<body>
<label class="something"></label>
<input type="text" name="attr_flags">
<div>
<input type="text" name="attr_flags" class="sheet-toggler" pattern=".*toggler_list1.*" required="required">
<div class="lorem">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris hendrerit cursus ex. Pellentesque pulvinar nulla justo, finibus hendrerit magna aliquam vitae.</div>
</div>
<div>
<input type="text" name="attr_flags" class="sheet-toggler" pattern=".*toggler_list2.*" required="required">
<div class="lorem">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris hendrerit cursus ex. Pellentesque pulvinar nulla justo, finibus hendrerit magna aliquam vitae.</div>
</div>
<script>
maxAsyncDelay = 100;
var uiFlagsManager = new UIFlagsManager('flags');
jQuery('input.sheet-toggler').click(b => {
let button = jQuery(b.target);
uiFlagsManager.toggleFlag(button.attr('pattern').replace(/\.\*/g,''));
});
</script>
</body>
</html>
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>FlagManager Tests</title>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.9.2.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-2.9.2.js"></script>
<script src="../../Mocks/Mocks.js"></script>
<script src="../../SheetUtils/SheetUtils.js"></script>
<script src="../FlagManager.js"></script>
<script src="./tests.js"></script>
</body>
</html>
@@ -0,0 +1,117 @@
QUnit.module('Basic Tests', {
before: function() {
maxAsyncDelay = 100; //Sets the mock delay for getAttrs and setAttrs to a maximum of 1000ms.
},
beforeEach: function() {
//Resets attributes before each test
attributes = {};
sectionIDS = {};
this.flagManager = new FlagManager('ui_flags');
}
});
QUnit.test('Flag Manager was initiated with zero entries', function( assert ) {
var done = assert.async();
this.flagManager.getFlags().then(flags => {
assert.equal(flags.size, 0);
done();
});
});
QUnit.test('One flag added to Flag Manager', function( assert ) {
var done = assert.async();
this.flagManager.addFlag('show_traits').then(flags => {
assert.equal(flags.size, 1);
assert.equal(flags.has('show_traits'), true);
assert.strictEqual(attributes.ui_flags, 'show_traits');
done();
});
});
QUnit.test('Two flags added to Flag Manager', function( assert ) {
var done = assert.async();
this.flagManager.addFlag('show_traits').then(() => {
this.flagManager.addFlag('show_spells').then(flags => {
assert.equal(flags.size, 2);
assert.equal(flags.has('show_traits'), true);
assert.equal(flags.has('show_spells'), true);
assert.strictEqual(attributes.ui_flags, 'show_traits show_spells');
done();
});
});
});
QUnit.test('Flag Deleted from Flag Manager', function( assert ) {
//Faking some attributes
attributes['ui_flags'] = 'show_traits show_spells show_skills';
var done = assert.async();
this.flagManager.deleteFlag('show_spells').then(flags => {
assert.equal(flags.size, 2);
assert.equal(flags.has('show_traits'), true);
assert.equal(flags.has('show_spells'), false);
assert.equal(flags.has('show_skills'), true);
assert.strictEqual(attributes.ui_flags, 'show_traits show_skills');
done();
});
});
QUnit.test('Flags correctly detected in Flag Manager', function( assert ) {
//Faking some attributes
attributes['ui_flags'] = 'show_traits show_spells show_skills';
var done1 = assert.async();
var done2 = assert.async();
this.flagManager.hasFlag('show_spells').then(hasFlag => {
assert.equal(hasFlag, true);
done1();
});
this.flagManager.hasFlag('non_existing_flag').then(hasFlag => {
assert.equal(hasFlag, false);
done2();
});
});
QUnit.test('Flags cant be added more than once', function( assert ) {
//Faking some attributes
attributes['ui_flags'] = 'show_traits show_spells show_skills';
var done = assert.async();
this.flagManager.addFlag('show_skills').then(flags => {
assert.equal(flags.size, 3);
assert.strictEqual(attributes.ui_flags, 'show_traits show_spells show_skills');
done();
});
});
QUnit.test('Order of stored flags are synced with source repeating section', function(assert) {
attributes['ui_flags'] = 'a_flag another_flag repeating_traits_0_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_1_name_-MzbTrhcIwpDwRZxfvEn';
attributes['_reporder_repeating_traits'] = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn';
sectionIDS['repeating_traits'] = ['-LzbTrhcIwpDwRZxfvEn', '-MzbTrhcIwpDwRZxfvEn'];
var done = assert.async();
this.flagManager.syncFlagsWithRepeatingSection('traits').then(flags => {
var expectedTags = new Set([
'a_flag',
'another_flag',
'repeating_traits_1_name_-LzbTrhcIwpDwRZxfvEn',
'repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn'
]);
assert.equal(Array.from(flags).join(' '), Array.from(expectedTags).join(' '));
done();
});
});
QUnit.test('Deleted flags are synced with source repeating section', function(assert) {
attributes = {};
attributes['ui_flags'] = 'a_flag another_flag repeating_traits_1_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn';
sectionIDS['repeating_traits'] = ['-MzbTrhcIwpDwRZxfvEn'];
var done = assert.async();
this.flagManager.syncFlagsWithRepeatingSection('traits').then(flags => {
var expectedTags = new Set([
'a_flag',
'another_flag',
'repeating_traits_0_name_-MzbTrhcIwpDwRZxfvEn'
]);
assert.equal(Array.from(flags).join(' '), Array.from(expectedTags).join(' '));
done();
});
});
@@ -0,0 +1,82 @@
class SheetUtils {
static getUID(value) {
const regexp = /-.{19}(?=_)|-.{19}$/g;
const valueAsString = String(value);
const match = valueAsString.match(regexp);
return (match) ? match.join() : "";
}
static aOrAn(value) {
if(['a','e','i','o','u'].indexOf(value.toLowerCase()[0]) > -1) return `an ${value}`;
return `a ${value}`;
}
static toLowerCase(value) {
if(Array.isArray(value)) {
const lowerCaseArray = value.map(item => { return item.toLowerCase(); });
return lowerCaseArray;
}
return String(value).toLowerCase();
}
static toCapitalCase(value) {
if(Array.isArray(value)) {
const capitalCaseArray = value.map(item => { return item[0].toUpperCase() + item.toLowerCase().slice(1); });
return capitalCaseArray;
}
return String(value)[0].toUpperCase() + String(value).toLowerCase().slice(1);
}
static getSectionOrder(section, callback) {
const sectionName = `repeating_${section}`;
const attributeName = `_reporder_${sectionName}`;
getAttrs([attributeName], attributes => {
let values = new Array();
Object.keys(attributes).some(() => {
let results = SheetUtils.toLowerCase(attributes[attributeName].replace(/ /g, '').split(','));
values = values.concat(results);
return true;
});
getSectionIDs(sectionName, ids => {
const filteredOrder = new Set();
const order = values.concat(SheetUtils.toLowerCase(ids)).filter(entry => { return SheetUtils.toLowerCase(ids).indexOf(entry) > -1; });
order.forEach(item => {
filteredOrder.add(item);
});
callback(Array.from(filteredOrder));
});
});
}
static deepReadAttribute(attr, callback, defaultValue) {
if(/^(@{).+}$/.test(String(attr)) === true) {
const regExp = /@\{([^@\{\}]+)\}/;
const reference = regExp.exec(attr)[1];
var self = this;
getAttrs([reference], function(v) {
if(!v[reference]) {
callback(defaultValue);
} else {
self.deepReadAttribute(v[reference], callback, defaultValue);
}
});
}
else {
callback(attr);
}
}
static sanitizeXP(value) {
const trimmedValue = value.trim();
if(!trimmedValue) return [];
const valueWithDecimalsRemoved = trimmedValue.replace(/,|\.| +/g, '');
const regex = /[0-9]+/g;
let xp = valueWithDecimalsRemoved.match(regex);
if(Array.isArray(xp)) xp = xp.map(entry => { return parseInt(entry) });
return xp;
}
static checkPath(obj, path, returnFalseOnEmpty = false) {
const sanitizedPath = path.replace(/\]\[|[\[,\]]/g, '.').replace(/\.+/g, '.').replace(/[",',]|\.$|^\./g, '');
const properties = sanitizedPath.split('.');
let level = obj;
for(let property = 0; property < properties.length; property++) {
if((returnFalseOnEmpty && !level[properties[property]]) || (!returnFalseOnEmpty && !(properties[property] in level))) return false;
level = level[properties[property]];
}
return true;
}
}
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>SheetUtils Tests</title>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.9.2.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-2.9.2.js"></script>
<script src="../../Mocks/Mocks.js"></script>
<script src="../SheetUtils.js"></script>
<script src="tests.js"></script>
</body>
</html>
@@ -0,0 +1,173 @@
QUnit.module('Basic Tests', {
before: function() {
maxAsyncDelay = 100; //Sets the mock delay for getAttrs and setAttrs to a maximum of 1000ms.
},
beforeEach: function() {
//Resets attributes before each test
attributes = {};
sectionIDS = {};
}
});
QUnit.test('Sheet Utils returns correct UID', function( assert ) {
assert.equal(SheetUtils.getUID('repeating_npcreaction_-LzbTrhcIwpDwRZxfvEn_name'), '-LzbTrhcIwpDwRZxfvEn');
assert.equal(SheetUtils.getUID('attr_wisdom'), '');
});
QUnit.test('Sheet Utils returns a blank string when an invalid parameter is used', function( assert ) {
assert.equal(SheetUtils.getUID(12345), '');
assert.equal(SheetUtils.getUID(null), '');
assert.equal(SheetUtils.getUID(undefined), '');
assert.equal(SheetUtils.getUID({}), '');
assert.equal(SheetUtils.getUID(), '');
assert.equal(SheetUtils.getUID([]), '');
});
QUnit.test('Sheet Utils return the order a repeating section.', function(assert) {
attributes['_reporder_repeating_section'] = "-LzbTrhcIwpDwRZxfvEn,-MzbTrhcIwpDwRZxfvEn";
sectionIDS['repeating_section'] = ['-MzbTrhcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn'];
var done = assert.async();
SheetUtils.getSectionOrder('section', ids => {
assert.equal(ids.join(','), attributes['_reporder_repeating_section'].toLowerCase());
done();
});
});
QUnit.test('Sheet Utils section IDs when no ordering is found', function(assert) {
sectionIDS['repeating_section'] = ['-MzbTrhcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn'];
var done = assert.async();
SheetUtils.getSectionOrder('section', ids => {
assert.equal(ids.join(','), sectionIDS['repeating_section'].join(',').toLowerCase());
done();
});
});
QUnit.test('Sheet Utils returns correct lowered case array', function( assert ) {
assert.equal(SheetUtils.toLowerCase(['Something', 'SOMETHINGELSE']).join(' '), 'something somethingelse');
});
QUnit.test('Sheet Utils returns correct capitalized case array', function( assert ) {
assert.equal(SheetUtils.toCapitalCase(['something', 'SOMETHINGELSE']).join(' '), 'Something Somethingelse');
});
QUnit.test('Sheet Utils returns correct deep read attributes', function( assert ) {
attributes['hitdie_1'] = '6';
attributes['hitdie_2'] = '@{hitdie_2A}';
attributes['hitdie_2A'] = '8';
attributes['hitdie_3'] = 3;
attributes['hitdie_4'] = '["something"]';
attributes['hitdie_6'] = '6';
var done_1 = assert.async();
var done_2 = assert.async();
var done_3 = assert.async();
var done_4 = assert.async();
var done_5 = assert.async();
var done_6 = assert.async();
var done_7 = assert.async();
var done_8 = assert.async();
SheetUtils.deepReadAttribute('@{hitdie_1}', value => {
assert.equal(value, '6');
done_1();
}, '2');
SheetUtils.deepReadAttribute('@{hitdie_2}', value => {
assert.equal(value, '8');
done_2();
}, '2');
SheetUtils.deepReadAttribute('@{hitdie_3}', value => {
assert.equal(value, '3');
done_3();
}, '2');
SheetUtils.deepReadAttribute('@{hitdie_4}', value => {
assert.equal(value, '["something"]');
done_4();
}, '2');
SheetUtils.deepReadAttribute('@{hitdie_5}', value => {
assert.equal(value, '2');
done_5();
}, '2');
SheetUtils.deepReadAttribute('@{hitdie_5}', value => {
assert.equal(value, undefined);
done_6();
});
SheetUtils.deepReadAttribute('{hitdie_6}', value => {
assert.equal(value, '{hitdie_6}');
done_7();
});
SheetUtils.deepReadAttribute('something@{hitdie_6}', value => {
assert.equal(value, 'something@{hitdie_6}');
done_8();
});
});
QUnit.test('Invalid ordered itens are removed from result', function(assert) {
attributes['ui_flags'] = 'a_flag another_flag repeating_traits_0_name_-LzbTrhcIwpDwRZxfvEn repeating_traits_1_name_-MzbTrhcIwpDwRZxfvEn';
attributes['_reporder_repeating_traits'] = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn,-InvalidIwpDwRZxfvEn';
sectionIDS['repeating_traits'] = ['-FirsThcIwpDwRZxfvEn', '-LzbTrhcIwpDwRZxfvEn', '-MzbTrhcIwpDwRZxfvEn'];
var done = assert.async();
SheetUtils.getSectionOrder('traits', order => {
console.log(order);
var expected = '-MzbTrhcIwpDwRZxfvEn,-LzbTrhcIwpDwRZxfvEn,-FirsThcIwpDwRZxfvEn';
assert.equal(order.join(','), SheetUtils.toLowerCase(expected));
done();
});
});
QUnit.only('utils return valid experience points', function(assert) {
var xp_char_1 = '10000';
var xp_char_2 = '10,000';
var xp_char_3 = '10.000';
var xp_char_4 = '10000 / 30000';
var xp_char_5 = '10,000 /30.000';
var xp_char_6 = '10.000\\30.000';
var xp_char_7 = '10,000 |30.000';
var xp_char_8 = '10,000 : 30.000';
var xp_char_9 = '1.010,000-2.030.000';
var xp_char_10 = '1 010 000- 2.030.000';
var xp_char_11 = '1 010 000 2.030.000';
var xp_char_12 = 'abcde 10000 / 30000sdse';
var invalidXP = 'abcdef';
var blankXPField = '';
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_1)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_2)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_3)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_4)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_4)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_5)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_5)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_6)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_6)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_7)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_7)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_8)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_8)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_9)[0], 1010000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_9)[1], 2030000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_10)[0], 1010000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_10)[1], 2030000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_11)[0], 10100002030000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_12)[0], 10000);
assert.strictEqual(SheetUtils.sanitizeXP(xp_char_12)[1], 30000);
assert.strictEqual(SheetUtils.sanitizeXP(invalidXP), null);
assert.strictEqual(SheetUtils.sanitizeXP(blankXPField).length, 0);
});
QUnit.test('Sheet Utils checks object path', function( assert ) {
var my_obj = {
["teste teste"]: {
another: {
empty: ""
}
}
};
var path_1 = "['teste teste']['another']['empty']";
var path_2 = "['teste teste'].another.empty";
var path_3 = "['teste teste'].another['empty']";
var path_4 = "['teste teste'].noexisting['empty']";
assert.equal(SheetUtils.checkPath(my_obj, path_1), true);
assert.equal(SheetUtils.checkPath(my_obj, path_1, true), false);
assert.equal(SheetUtils.checkPath(my_obj, path_2), true);
assert.equal(SheetUtils.checkPath(my_obj, path_2, true), false);
assert.equal(SheetUtils.checkPath(my_obj, path_3), true);
assert.equal(SheetUtils.checkPath(my_obj, path_3, true), false);
assert.equal(SheetUtils.checkPath(my_obj, path_4), false);
assert.equal(SheetUtils.checkPath(my_obj, path_4, true), false);
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,268 @@
const dropFunctions = {
validateCantripScaling: scaling => scaling === 'dice' || scaling === 'beam' ? true : false,
buildCantripScaling: scaling => `Cantrip ${scaling.charAt(0).toUpperCase()}${scaling.slice(1)}`,
buildDamage: (page, currentData, alternateDamage) => {
try {
const modifiers = dropFunctions.inferAbilityModifier(page.data["Item Type"], page.data["Properties"], currentData)
let damage = alternateDamage ? alternateDamage : page.data[`Damage`];
damage += modifiers && modifiers != 0 ? `+${modifiers}` : ""
damage += page.data["Modifiers"] ? dropFunctions.inferModifier(page.data["Modifiers"], 'damage') : ""
return damage
} catch (error) {
console.error(error)
return ''
}
},
buildItemModString: page => {
try {
let mods = `Item Type: ${page.data["Item Type"] || page.data["Category"]}`;
//Items with ac or attack related bonuses
["AC", "Damage", "Damage Type", "Secondary Damage", "Secondary Damage Type", "Alternate Damage", "Alternate Damage Type", "Alternate Secondary Damage", "Alternate Secondary Damage Type", "Critical Range", "Range"].forEach(attr => {
mods += page.data[`${attr}`] && page.data[`${attr}`] != "" ? `, ${attr}: ${page.data[`${attr}`]}` : "";
});
//Items with modifiers such as Cloak of Protection
mods += page.data["Modifiers"] && page.data["Modifiers"] != "" ? `, ${page.data["Modifiers"]}` : "";
return mods
} catch (error) {
console.error(error)
return ''
}
},
buildSpellQuery: spellLevel => {
try {
let spellQuery = ""
for(i = 0; i < 10-spellLevel; i++) {
const sum = (parseInt(i, 10) + parseInt(spellLevel, 10))
spellQuery += `|Level ${sum},${sum}`
};
return `@{wtype}&{template:spell} {{level=@{spellschool} ?{Cast at what level?${spellQuery}}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} @{spellconcentration} @{charname_output}`
} catch (error) {
console.error(error)
}
},
buildToHit: (page, currentData) => {
try {
let hit = dropFunctions.inferAbilityModifier(page.data["Item Type"], page.data["Properties"], currentData);
hit += page.data["Modifiers"] ? dropFunctions.inferModifier(page.data["Modifiers"], 'attacks') : "";
return hit
} catch (error) {
console.error(error)
return ''
}
},
buildSenses: (senses, passivePerception) => {
try {
return senses ? `${senses}, passive Perception ${passivePerception}` : `passive Perception ${passivePerception}`;
} catch (error) {
console.log(error)
return ''
}
},
buildSpellList: spells => {
try {
let spellList = []
//Create an array of spells to get from the Comepndium
const spellTypes = ["spells", "innate"]
spellTypes.forEach(type => {
const spellObject = dropFunctions.jsonParse(spells)[type]
if (spellObject) {
for (let [key, value] of Object.entries(spellObject)) {
value.forEach(spell => spellList.push(spell))
}
}
})
return spellList
} catch (error) {
console.log(error)
}
},
buildType: (size, type, aligment) => {
let string = size || "";
type ? string += ` ${type}` : false;
aligment ? string += `, ${aligment}`: false;
return string
},
confirmFinesse: properties => properties.toLowerCase().includes("finesse") ? true : false,
confirmRanged: itemType => itemType.toLowerCase().includes("ranged") ? true : false,
confirmDexGreaterThanStr: (dex, str) => dex > str ? true : false,
convertAbbreviationToAttribute: threeLetterString => {
switch(threeLetterString.toLowerCase()) {
case "str":
return "@{strength_mod}";
break;
case "dex":
return "@{dexterity_mod}";
break;
case "con":
return "@{constitution_mod}";
break;
case "wis":
return "@{wisdom_mod}";
break;
case "int":
return "@{intelligence_mod}";
break;
case "cha":
return "@{charisma_mod}";
break;
default:
errorMessage("convertAbbreviationToAttribute", `${threeLetterString} did not match one of the expected types str, dex, con, wis, int, cha`)
return false
}
},
determineComponent: (componentList, component) => componentList.toLowerCase().includes(component) ? `{{${component}=1}}` : false,
inferAbilityModifier: (type, properties, currentData) => {
try {
const ranged = type ? dropFunctions.confirmRanged(type) : false;
const finesse = properties ? dropFunctions.confirmFinesse(properties) : false;
const dexGreaterThanStr = dropFunctions.confirmDexGreaterThanStr(currentData.dexterity_mod, currentData.strength_mod);
return ranged || (finesse && dexGreaterThanStr) ? currentData.dexterity_mod : currentData.strength_mod
} catch (error) {
console.log(error)
}
},
inferBaseAttribute: attribute => attribute.includes('(') ? attribute.split(" (")[0] : attribute,
inferCasterLevel: description => parseInt(description.substring(description.indexOf("-level")-4, description.indexOf("-level")-2).trim(), 10) || 1,
inferFormulaAttribute: attribute => attribute.includes('(') ? attribute.split(" (")[1].slice(0, -1) : "",
inferModifier: (modifiers, type) => {
try {
let modifier = "";
modifiers = modifiers.split(',');
modifiers.forEach(value => {
modifier += value.toLowerCase().includes(type) ? value.split(' ').pop() : ""
});
return modifier
} catch (error) {
console.log(error)
return ''
}
},
inferSpellcastingAbility: description => {
let ability = description.match(/casting ability is (.*?) /);
ability = ability && ability.length > 1 ? ability[1] : false;
ability = ability ? `@{${ability.toLowerCase()}_mod}+` : "0*";
return ability
},
inferSavingThrows: saves => {
try {
let object = {};
if (saves) {
saves = saves.includes(', ') ? saves.split(", ") : [saves]
saves.forEach(saveValue => {
const split = saveValue.includes(' ') ? saveValue.split(' ') : errorMessage(`inferSavingThrows`, `${saveValue} does no include a space`)
const abbreviation = split[0].toLowerCase();
object[`npc_${abbreviation}_save_base`] = split.pop();
});
}
return object
} catch (error) {
errorMessage('inferSavingThrows', error)
}
},
inferSkills: skills => {
try {
let object = {};
if (skills) {
skills = skills.includes(', ') ? skills.split(", ") : [skills]
skills.forEach(skillValue => {
const split = skillValue.includes(' ') ? skillValue.split(' ') : errorMessage(`inferSkills`, `${skillValue} does no include a space`)
const value = split.pop();
const name = split.length > 2 ? split.join("_").toLowerCase() : split.shift().toLowerCase();
object[`npc_${name}_base`] = value;
});
}
return object
} catch (error) {
errorMessage('inferSkills', error)
}
},
jsonParse: (data, defaultValue) => {
let result = null;
try {
result = JSON.parse(data);
} catch (error) {
switch(typeof defaultValue) {
case 'boolean':
case 'number':
case 'string':
case 'function':
result = (typeof data === typeof defaultValue) ? data : defaultValue;
break;
case 'object':
result = (typeof data === typeof defaultValue && data.constructor.name === defaultValue.constructor.name) ? data : defaultValue;
break;
default:
errorMessage('Invalid JSON', error);
}
}
return result;
},
updateSheetAttributes: newObjectForSheet => {
try {
let update = {};
for (let [key, value] of Object.entries(newObjectForSheet.attributes)) {
//If repeating section, update key needs the repeating information
const updateKey = newObjectForSheet.reprowid ? newObjectForSheet.addAttribute(key) : key;
//This 'update' will be handed to a setAttrs function
update[updateKey] = newObjectForSheet.attributes[key];
}
return update
} catch (error) {
errorMessage(`updateSheetAttributes`, error);
}
}
}
//These functions handle 'repeating' parameter of processDrop
const dropHelpers = {
findToolId: (repeatingTools, toolName) => {
let id = false
for(let [key, value] of Object.entries(repeatingTools)) {
value.toolname === toolName.toLowerCase() ? id = key : false;
}
return id
},
updateRepeatingTools: (newTool, existingTool) => {
existingTool.id = newTool.reprowid
existingTool.toolname = newTool.attributes.toolname.toLowerCase()
existingTool.base = newTool.attributes.toolbonus_base
return existingTool
},
updateRepeatingTraits: (newTrait, existingTrait) => {
existingTrait.id = newTrait.reprowid;
existingTrait.name = newTrait.attributes.name;
existingTrait.source = newTrait.attributes.source;
existingTrait.type = newTrait.attributes.source_type;
return existingTrait
}
}
@@ -0,0 +1,23 @@
const errorMessage = (name, error) => console.error(`%c ${name}: ${error}`, "color: orange; font-weight:14px;");
const warningMessage = (name, error) => console.warn(`%c ${name}: ${error}`, "color: gold; font-weight:14px;");
const checkSourceForSheetworker = eventinfo => eventinfo.sourceType && eventinfo.sourceType != "sheetworker" ? true : false
// Example: -m2jzgfth07mvwp3hhng
const getReprowid = sourceAttribute => sourceAttribute.split('_')[2]
// Example: repeating_tool_-m2jzgfth07mvwp3hhng
const getRepeatingSectionPrefix = sourceAttribute => {
const split = sourceAttribute.split('_');
return `${split[0]}_${split[1]}_${split[2]}`
}
// Example: repeating_tool_-m2jzgfth07mvwp3hhng_attkflag returns attkflag
const getAttrNameAtEndRepeating = sourceAttribute => {
const repeatingSplit = sourceAttribute.split('_')
const repeatingSplice = repeatingSplit.splice(3)
const repeatingAttrName = repeatingSplice.length > 1 ? repeatingSplice.join('_') : repeatingSplice[0]
return repeatingAttrName
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,92 @@
-
const hiddenvariables = [
{ name:"version", value:"4.2" },
{ name:"appliedUpdates", value: "", },
{ name:"monster_confirm_flag", value: "", },
{ name:"mancer_confirm_flag", value: "", },
{ name:"d20", value: "1d20" },
{ name:"level", value: "1" },
{ name:"pb", value: "2" },
{ name:"pbd_safe", value: "" },
{ name:"jack", value: "1" },
{ name:"jack_attr", value: "" },
{ name:"jack_bonus", value: "" },
{ name:"passive_wisdom", value: "10" },
{ name:"hitdie_final", value: "" },
{ name:"globalsavingthrowbonus", value: "" },
{ name:"death_save_bonus", value: "0" },
{ name:"initiative_bonus", value: "0" },
{ name:"spell_save_dc", value: "0" },
{ name:"spell_attack_bonus", value: "0" },
{ name:"spell_attack_mod", value: "0" },
{ name:"npc_legendary_actions_desc", value:"The creature can take 3 legendary actions, choosing from the options below. Only one legendary option can be used at a time and only at the end of another creature's turn. The creature regains spent legendary actions at the start of its turn." },
{ name:"global_damage_mod_crit", value: "0" },
{ name:"global_damage_mod_roll", value: "0" },
{ name:"global_damage_mod_type", value: "" },
{ name:"global_attack_mod", value: "" },
{ name:"global_save_mod", value: "" },
{ name:"global_skill_mod", value: "" },
{ name:"exhaustion_1", value: "" },
{ name:"exhaustion_2", value: "" },
{ name:"exhaustion_3", value: "" },
{ name:"exhaustion_4", value: "" },
{ name:"exhaustion_5", value: "" },
{ name:"exhaustion_6", value: "" },
{ name:"strength_mod", value: "0" },
{ name:"dexterity_mod", value: "0" },
{ name:"constitution_mod", value: "0" },
{ name:"intelligence_mod", value: "0" },
{ name:"wisdom_mod", value: "0" },
{ name:"charisma_mod", value: "0" },
{ name:"honor_mod", value: "0" },
{ name:"sanity_mod", value: "0" },
{ name:"strength_save_bonus", value: "0" },
{ name:"dexterity_save_bonus", value: "0" },
{ name:"constitution_save_bonus", value: "0" },
{ name:"intelligence_save_bonus", value: "0" },
{ name:"wisdom_save_bonus", value: "0" },
{ name:"charisma_save_bonus", value: "0" },
{ name:"honor_save_bonus", value: "0" },
{ name:"sanity_save_bonus", value: "0" },
{ name:"strength_maximum", value: "20" },
{ name:"dexterity_maximum", value: "20" },
{ name:"constitution_maximum", value: "20" },
{ name:"intelligence_maximum", value: "20" },
{ name:"wisdom_maximum", value: "20" },
{ name:"charisma_maximum", value: "20" },
{ name:"honor_maximum", value: "20" },
{ name:"sanity_maximum", value: "20" },
{ name:"acrobatics_bonus", value: "0" },
{ name:"animal_handling_bonus", value: "0" },
{ name:"arcana_bonus", value: "0" },
{ name:"athletics_bonus", value: "0" },
{ name:"deception_bonus", value: "0" },
{ name:"history_bonus", value: "0" },
{ name:"insight_bonus", value: "0" },
{ name:"intimidation_bonus", value: "0" },
{ name:"investigation_bonus", value: "0" },
{ name:"medicine_bonus", value: "0" },
{ name:"nature_bonus", value: "0" },
{ name:"perception_bonus", value: "0" },
{ name:"performance_bonus", value: "0" },
{ name:"persuasion_bonus", value: "0" },
{ name:"religion_bonus", value: "0" },
{ name:"sleight_of_hand_bonus", value: "0" },
{ name:"stealth_bonus", value: "0" },
{ name:"survival_bonus", value: "0" },
{ name:"lvl1_slots_total", value: "0" },
{ name:"lvl2_slots_total", value: "0" },
{ name:"lvl3_slots_total", value: "0" },
{ name:"lvl4_slots_total", value: "0" },
{ name:"lvl5_slots_total", value: "0" },
{ name:"lvl6_slots_total", value: "0" },
{ name:"lvl7_slots_total", value: "0" },
{ name:"lvl8_slots_total", value: "0" },
{ name:"lvl9_slots_total", value: "0" },
{ name:"l1mancer_status", value: "" },
{ name:"lpmancer_status", value: "" },
{ name:"queryadvantage", value: "" },
];
each field in hiddenvariables
input(name=`attr_${field.name}`, type="hidden", value=field.value)
@@ -0,0 +1,84 @@
-
const globalAttributesByCategory = {
abilities: ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma'],
optionalAbilites: ['honor', 'sanity'],
alignments: ['Lawful Good', 'Neutral Good', 'Chaotic Good', 'Lawful Neutral', 'Neutral', 'Chaotic Neutral', 'Lawful Evil', 'Neutral Evil', 'Chaotic Evil'],
classes: ['artificer', 'bard', 'cleric', 'druid', 'paladin', 'ranger', 'sorcerer', 'warlock', 'wizard'],
sizes: ['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Gargantuan'],
diceSizes: ['d4', 'd6', 'd8', 'd10', 'd12'],
skills: [
{
name: "Acrobatics",
ability: "Dexterity"
},
{
name: "Animal Handling",
ability: "Wisdom"
},
{
name: "Arcana",
ability: "Intelligence"
},
{
name: "Athletics",
ability: "Strength"
},
{
name: "Deception",
ability: "Charisma"
},
{
name: "History",
ability: "Intelligence"
},
{
name: "Insight",
ability: "Wisdom"
},
{
name: "Intimidation",
ability: "Charisma"
},
{
name: "Investigation",
ability: "Intelligence"
},
{
name: "Medicine",
ability: "Wisdom"
},
{
name: "Nature",
ability: "Intelligence"
},
{
name: "Perception",
ability: "Wisdom"
},
{
name: "Performance",
ability: "Charisma"
},
{
name: "Persuasion",
ability: "Charisma"
},
{
name: "Religion",
ability: "Intelligence"
},
{
name: "Sleight of Hand",
ability: "Dexterity"
},
{
name: "Stealth",
ability: "Dexterity"
},
{
name: "Survival",
ability: "Wisdom"
},
],
personalityTraits: ["Personality Traits", "Ideals", "Bonds", "Flaws"]
}
@@ -0,0 +1,11 @@
// PC
include pc/AbilityScore
include pc/InsProf
include pc/PersonalityTrait
include pc/SavingThrow
include pc/Skills
include pc/SpellContainer
include pc/SpellLabel
include pc/SpellSection
include utility/SelectClass
include utility/SelectHitDice
@@ -0,0 +1,16 @@
mixin AbilityScore(attr, componentSettings = {})
- const { optional = false } = componentSettings;
- const shortName = attr.slice(0,3).toUpperCase();
- const className = (optional) ? ` toggleVisibilityBy-${attr}` : "";
if (optional)
input.toggleVisibility(type=`hidden` name=`attr_${attr}_toggle`)
.abilityscore(class=`abilityscore--${shortName} ${className}`)
button.abilityscore__rollbutton(type=`roll` name=`roll_${attr}` value=`@{wtype}&{template:simple} {{rname=^{${attr}-u}}} {{mod=@{${attr}_mod}@{jack_bonus}}} {{r1=[[@{d20}+@{${attr}_mod}@{jack_attr}[${shortName}]]]}} @{rtype}+@{${attr}_mod}@{jack_attr}[${shortName}]]]}} @{charname_output}` data-i18n=`${attr}-u`)
span.abilityscore__value(name=`attr_${attr}_mod` title=`@{${attr}_mod}`)
.abilityscore__mod
input.abilityscore__base(type=`text` name=`attr_${attr}_base` title=`@{${attr}}` value=`10`)
input(type=`hidden` name=`attr_${attr}` value=`10`)
input.abilityscore__flag(type=`hidden` name=`attr_${attr}_flag` value=`0`)
span.abilityscore__final(name=`attr_${attr}`)
@@ -0,0 +1,12 @@
mixin InsProf(name)
-
const typebox = (name.toLowerCase() === "inspiration") ? "inspprof--inspiration" :
(name.toLowerCase() === "pass-wis") ? "inspprof--passive"
: "";
.inspprof(class=typebox)
.inspprof__value
if (block)
block
.inspprof__label
span(data-i18n=name)
@@ -0,0 +1,7 @@
mixin PersonalityTrait(name)
- const attr = name.replace(/ /g, '_').replace(/[^a-zA-Z_]/g, "").replace(/__/g, "_").toLowerCase();
- const i18n = `${attr}-s`;
- const flag = attr.split(attr.indexOf('_'))[0];
.personalitytrait
.personalitytrait__label(data-i18n=name)
textarea(name=`attr_${attr}`)
@@ -0,0 +1,15 @@
mixin SavingThrow (name, componentSettings = {})
- const { optional } = componentSettings;
- const attr = name.toLowerCase();
- const className = (optional) ? `toggleVisibilityBy-${attr}` : ``;
if (optional)
input.toggle(type=`hidden` name=`attr_${attr}_toggle`)
.savingthrow(class=className)
input(type=`hidden` name=`attr_${attr}_save_roll`)
.savingthrow__checkbox
input(type=`checkbox` name=`attr_${attr}_save_prof` title=`@{${attr}_save_prof}` value=`(@{pb})`)
span
span.savingthrow__value(name=`attr_${attr}_save_bonus` title=`@{${attr}_save_bonus}`)
button.savingthrow__button(type=`roll` name=`roll_${attr}_save` value=`@{${attr}_save_roll}` data-i18n=attr)
@@ -0,0 +1,13 @@
mixin Skill(name, ability)
- const attr = name.toLowerCase().replace(/ /g, "_");
- const shortName = ability.split(0,3)[0].toUpperCase();
.skill(data-i18n-list-item=`${attr}`)
input(type=`hidden` name=`attr_${attr}_roll`)
.skill__checkbox
input(type=`checkbox` name=`attr_${attr}_prof` title=`@{${attr}_prof}` value=`(@{pb}*@{${attr}_type})`)
span
span.skill__value(name=`attr_${attr}_bonus` title=`@{${attr}_bonus}`) 0
button.skill__button(type=`roll` name=`roll_${attr}` value=`@{${attr}_roll}` data-i18n=`${attr}-core`)
| #{name}
span #{shortName}
@@ -0,0 +1,208 @@
mixin SpellContainer(level, isCantrip=false)
fieldset(class=`repeating_spell-${level}`)
.spell
//input.spell__flag--details(type="hidden" name="attr_details-flag" checked="checked")
input.spell__flag--options(type="hidden" name="attr_options-flag" checked="checked")
.spell__display
input(type="hidden" name="attr_rollcontent" value="@{wtype}&{template:spell} {{level=@{spellschool} @{spelllevel}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} {{savedc=@{spell_save_dc}}} @{spellconcentration} @{charname_output}")
if !isCantrip
.spell__prepped
input.spell__prepped-input(type="checkbox" name="attr_spellprepared" value="1")
span.spell__prepped-mark
button.spell__card-button(type="roll" name="roll_spell" value="@{rollcontent}")
span.spell__name(name="attr_spellname")
span.spell__innate(name="attr_innate")
.spell__indicators
input.spell__flag--innate(type="hidden" name="attr_innate" value="")
input.spell__flag--ritual(type="hidden" name="attr_spellritual" value="0")
input.spell__flag--concentration(type="hidden" name="attr_spellconcentration" value="0")
.spell__casting-details
span.spell__ritual(data-i18n="spell-ritual") R
span.spell__concentration(data-i18n="spell-concentration") C
input.spell__flag--v(type="hidden" name="attr_spellcomp_v" value="{{v=1}}")
input.spell__flag--s(type="hidden" name="attr_spellcomp_s" value="{{s=1}}")
input.spell__flag--m(type="hidden" name="attr_spellcomp_m" value="{{m=1}}")
.spell__components
span.spell__component--v(data-i18n="spell-component-verbal") V
span.spell__component--s(data-i18n="spell-component-somatic") S
span.spell__component--m(data-i18n="spell-component-material") M
input.spell__flag--spellsave(type="hidden" name="attr_roll_output_dc" value="@{spell_save_dc}")
button.spell__chat-button.output.btn.ui-draggable(type="roll" name="roll_output" value="@{wtype}&{template:spelloutput} {{level=@{spellschool} @{spelllevel}}} {{name=@{spellname}}} {{castingtime=@{spellcastingtime}}} {{range=@{spellrange}}} {{target=@{spelltarget}}} @{spellcomp_v} @{spellcomp_s} @{spellcomp_m} {{material=@{spellcomp_materials}}} {{duration=@{spellduration}}} {{description=@{spelldescription}}} {{athigherlevels=@{spellathigherlevels}}} @{spellritual} {{innate=@{innate}}} {{savedc=@{roll_output_dc}}} @{spellconcentration} @{charname_output}") w
//.spell__details-container
input.spell__flag--details(type="checkbox" name="attr_details-flag" checked="checked")
span i
.spell__options-container
input.spell__flag--options(type="checkbox" name="attr_options-flag" checked="checked")
span y
.spell__options.options
.options__row
span.options__label(data-i18n="name:-u") NAME:
input.options__flex(type="text" name="attr_spellname")
.options__row.options__row--noborder
span.options__label(data-i18n="school:-u") SCHOOL:
select.options__flex(name="attr_spellschool")
option(value="abjuration" data-i18n="abjuration") Abjuration
option(value="conjuration" data-i18n="conjuration") Conjuration
option(value="divination" data-i18n="divination") Divination
option(value="enchantment" data-i18n="enchantment") Enchantment
option(value="evocation" data-i18n="evocation") Evocation
option(value="illusion" data-i18n="illusion") Illusion
option(value="necromancy" data-i18n="necromancy") Necromancy
option(value="transmutation" data-i18n="transmutation") Transmutation
input.options__flex(type="checkbox" name="attr_spellritual" value="{{ritual=1}}")
span.options__label(data-i18n="ritual-u") RITUAL
.options__row.options__row--noborder
span.options__label(data-i18n="casting-time:-u") CASTING TIME:
input.options__flex(type="text" name="attr_spellcastingtime")
.options__row.options__row--noborder
span.options__label(data-i18n="range:-u") RANGE:
input.options__flex(type="text" name="attr_spellrange")
.options__row
span.options__label(data-i18n="target:-u") TARGET:
input.options__flex(type="text" name="attr_spelltarget")
input(type="hidden" name="attr_spellcomp")
.options__row.options__row--noborder
span.options__label(data-i18n="components:-u") COMPONENTS:
input.options__flex(type="checkbox" name="attr_spellcomp_v" value="{{v=1}}" checked="checked")
span.options__label(data-i18n="spell-component-verbal") V
input.options__flex(type="checkbox" name="attr_spellcomp_s" value="{{s=1}}" checked="checked")
span.options__label(data-i18n="spell-component-somatic") S
input.options__flex(type="checkbox" name="attr_spellcomp_m" value="{{m=1}}" checked="checked")
span.options__label(data-i18n="spell-component-material") M
.options__row
input.options__flex(type="text" name="attr_spellcomp_materials" placeholder="ruby dust worth 50gp" data-i18n-placeholder="ruby-dust-place")
.options__row
input.options__flex--1(type="checkbox" name="attr_spellconcentration" value="{{concentration=1}}")
span.options__label.options__flex--9(data-i18n="concentration-u") CONCENTRATION
.options__row
span.options__label(data-i18n="duration:-u") DURATION:
input.options__flex(type="text" name="attr_spellduration")
.options__row
span.options__label(data-i18n="spell-ability-u") SPELLCASTING ABILITY
select.options__flex(name="attr_spell_ability")
option(value="0*" data-i18n="none-u") NONE
option(value="spell" data-i18n="spell-u") SPELL
option(value="@{strength_mod}+" data-i18n="strength-u") STRENGTH
option(value="@{dexterity_mod}+" data-i18n="dexterity-u") DEXTERITY
option(value="@{constitution_mod}+" data-i18n="constitution-u") CONSTITUTION
option(value="@{intelligence_mod}+" data-i18n="intelligence-u") INTELLIGENCE
option(value="@{wisdom_mod}+" data-i18n="wisdom-u") WISDOM
option(value="@{charisma_mod}+" data-i18n="charisma-u") CHARISMA
.options__row
span.options__label(data-i18n="innate:-u") INNATE:
input.options__flex(type="text" name="attr_innate" placeholder="1/day" value="")
.options__row
span.options__label(data-i18n="output:-u") OUTPUT:
select.options__flex(name="attr_spelloutput")
option(value="SPELLCARD" data-i18n="spellcard-u") SPELLCARD
option(value="ATTACK" data-i18n="attack-u") ATTACK
input.spell__flag--output(type="hidden" name="attr_spelloutput")
.spell__options--attack
.options__row--noborder
span.options__label(data-i18n="spell-atk:-u") SPELL ATTACK:
select.options__flex(name="attr_spellattack")
option(value="None" data-i18n="none") None
option(value="Melee" data-i18n="melee") Melee
option(value="Ranged" data-i18n="ranged") Ranged
.options__row.options__row--noborder
span.options__label(data-i18n="damage:-u") DAMAGE:
input.options__flex(type="text" name="attr_spelldamage" )
span.options__label(data-i18n="type:-u") TYPE:
input.options__flex(type="text" name="attr_spelldamagetype" )
.options__row.options__row--noborder
span.options__label(data-i18n="damage2:-u") DAMAGE2:
input.options__flex(type="text" name="attr_spelldamage2" )
span.options__label(data-i18n="type:-u") TYPE:
input.options__flex(type="text" name="attr_spelldamagetype2" )
.options__row.options__row--noborder
span.options__label(data-i18n="healing:-u") HEALING:
input(type="text" name="attr_spellhealing" )
.options__row
input.options__flex--1(type="checkbox" name="attr_spelldmgmod" value="Yes")
span.options__label.options__flex--9(data-i18n="add-ability-mod-u") ADD ABILITY MOD TO DAMAGE OR HEALING
if isCantrip
.options__row
span.options__label(data-i18n="cantrip-progression:-u") CANTRIP PROGRESSION
select.options__flex(name="attr_spell_damage_progression")
option(value="" selected="selected" data-i18n="none-u") NONE
option(value="Cantrip Dice" data-i18n="cantrip-dice-u") CANTRIP DICE
option(value="Cantrip Beam" data-i18n="cantrip-beam-u") CANTRIP BEAM
.options__row
span.options__label(data-i18n="saving-throw:-u") SAVING THROW:
select(name="attr_spellsave")
option(value="" selected="selected" data-i18n="none-u") NONE
option(value="Strength" data-i18n="str-u") STR
option(value="Dexterity" data-i18n="dex-u") DEX
option(value="Constitution" data-i18n="con-u") CON
option(value="Intelligence" data-i18n="int-u") INT
option(value="Wisdom" data-i18n="wis-u") WIS
option(value="Charisma" data-i18n="cha-u") CHA
.options__row
span.options__label(data-i18n="effect:-u") EFFECT:
input(type="text" name="attr_spellsavesuccess" placeholder="Half damage" data-i18n-placeholder="half-dmg-place")
.options__row.options__row--noborder
span.options__label(data-i18n="at-higher-lvl-dmg:-u") HIGHER LVL CAST DMG:
.options__row
input.options__flex--3(type="text" name="attr_`spellhldie" placeholder="1" )
select.options__flex--3(name="attr_spellhldietype")
option(value="" selected="selected" data-i18n="none-u") NONE
option(value="d4") d4
option(value="d6") d6
option(value="d8") d8
option(value="d10") d10
option(value="d12") d12
option(value="d20") d20
span.options__flex--1 +
input.options__flex--3(type="text" name="attr_spellhlbonus" placeholder="0" )
.options__row
span.options__label.options__flex--7(data-i18n="include_spell_desc:-u") INCLUDE SPELL DESCRIPTION IN ATTACK:
select.options__flex--3(name="attr_includedesc")
option(value="off" selected="selected" data-i18n="off") Off
option(value="partial" data-i18n="partial") Partial
option(value="on" data-i18n="on") On
.options__row.options__row--topborder
span.options__label(data-i18n="description:-u") DESCRIPTION:
.options__row
textarea(name="attr_spelldescription")
if !isCantrip
.options__row.options__row--noborder
span.options__label(data-i18n="at-higher-lvl:-u") AT HIGHER LEVELS:
.options__row
textarea(name="attr_spellathigherlevels")
.options__row
span.options__label(data-i18n="class:-u") CLASS:
input(type="text" name="attr_spellclass" )
.options__row
span.options__label(data-i18n="type:-u") TYPE:
input(type="text" name="attr_spellsource" )
input(type="hidden" name="attr_spellattackid")
input(type="hidden" name="attr_spelllevel" value=`${level}`)
@@ -0,0 +1,20 @@
mixin SpellLabel(level)
- const label = (level === 0) ? "Cantrips" : level;
- var spellPointCostPerLevel = [0, 2, 3, 5, 6, 7, 9, 10, 11, 13];
- var spellPoinstCost = spellPointCostPerLevel[level];
.spell-label(class=`spell-label--${level}`)
.spell-label__numeral
.spell-label__label
if level !== 0
span(data-i18n="Level")
span #{ label }
if level !== 0
button.pictos(name=`act_spell-reset-${level}`, type="action") 1
button.pictos(name=`act_spell-use-${level}`, type="action") }
if level !== 0
.spell-label__total
.spell-label__title(data-i18n="total")
span(name=`attr_lvl${level}_slots_total`)
.spell-label__expended
.spell-label__title(data-i18n="current")
input(type="number", name=`attr_lvl${level}_slots_expended`, value!="0")
@@ -0,0 +1,5 @@
mixin SpellSection(level, isCantrip=false)
- const label = (level === 0) ? "cantrip" : level;
.spells__container
+SpellLabel(level, isCantrip)
+SpellContainer(label, isCantrip)
@@ -0,0 +1,12 @@
mixin selectClass(attr = "class", defaultOption, mixinSettings )
- const { chooseOption = true, classNames = [] } = mixinSettings;
- const className = classNames.join(" ");
select.hiding.class(name=`attr_${attr}`, class=className)
if (chooseOption)
option(value=`` data-i18n=`choose`) Choose
for classAttr in globalAttributesByCategory.classes
- const name = classAttr.charAt(0).toUpperCase() + classAttr.slice(1);
- const selected = (classAttr === defaultOption) ? "selected" : "";
option(value=name data-i18n=classAttr) #{name}
@@ -0,0 +1,8 @@
mixin selectHitDice(attr = "hitdiceroll", defaultOption, mixinSettings={} )
- const { chooseOption = true, classNames = []} = mixinSettings;
- const className = classNames.join(" ");
select(name=`attr_${attr}`, class=className)
each dieSize in globalAttributesByCategory.diceSizes
- const value = dieSize.split(1);
option(value=value) #{dieSize}
+600
View File
@@ -0,0 +1,600 @@
mixin bottomBar(firstTab, lastTab)
.bottombar
button.prev(data-i18n='back' type='back' value=`l1-${firstTab}`)
button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
button.next(data-i18n='next' type='back' value=`l1-${lastTab}`)
mixin cancelPrompt(slide)
.choice.cancel-prompt
p.label(data-i18n='charmancer-cancel-heading')
button.warning(data-i18n='cancel_charactermancer' type='cancel' value='l1-cancel')
button(data-i18n='save_progress_and_exit' type='cancel' value=`l1-${slide}`)
button(data-i18n='continue-charmancer' name='act_continue' type='action')
p.warning
span(data-i18n='charmancer-discard-warning')
mixin buttonMancerInfo(name)
button.mancer_info(name=`act_info_${name}` type='action' required) i
mixin infoDiv(className, acceptString)
.info
.sheet-compendium-page(accept=acceptString class=`sheet-${className}-info`)
mixin abilitiesOptions()
option(data-i18n='choose' value='')
each val in globalAttributesByCategory.abilities
option(data-i18n=val value=val)
mixin classOptions()
option(data-i18n='choose' value='')
each val in globalAttributesByCategory.classes
option(data-i18n=val value=val)
mixin diceOptions()
option(data-i18n='choose' value='')
each val in globalAttributesByCategory.diceSizes
- const value = val.slice(-1)
option(data-i18n=val value=value)
charmancer.sheet-charmancer-l1-welcome
.charmancer.container
input(type='hidden' name='comp_has_tasha' value='0')
ol.steps
.logos
span.charmancer-logo
span.compendium-logo
p.label(data-i18n='charmancer-welcome')
p(data-i18n='charmancer-what-is')
p.label(data-i18n='charmancer-compendium')
p(data-i18n='charmancer-compendium-detail')
p.label(data-i18n='get-started')
.bottombar
button.prev(data-i18n='opt-out-u' type='cancel' value='l1-cancel')
button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
button.next(data-i18n='next' type='back' value='l1-race')
+cancelPrompt('welcome')
charmancer.sheet-charmancer-l1-race
.charmancer.container
ol.steps
.topbar-holder
.choices
.row
input(type='hidden' name='comp_has_tasha')
.customize-origin
label
span(data-i18n='customize-your-origin')
span(data-i18n='customize-your-origin-info')
.toggle
input(type='checkbox' name='comp_customize_origin' value='1')
.knob
.row
label.hilite
span(data-i18n='charmancer-choose-race')
select(accept='Category:Races' name='comp_race' required)
option(data-i18n='choose' value='')
option.custom(data-i18n='custom' value='Rules:Races')
+buttonMancerInfo('race')
.choice.custom_race
label.hilite(data-i18n='charmancer-custom-race-name')
input(name='comp_race_name' placeholder='Custom Race' type='text' required)
.row.choice.race_possible.custom_race.race_abilities
label
.choice.tasha_race_enabled
input(type='hidden' name='comp_tasha_race_ability_choice1_increase')
span.choice.tasha_race_ability_choice1.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice1(name='comp_tasha_race_ability_choice1')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_race_ability_choice2_increase')
span.choice.tasha_race_ability_choice2.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice2(name='comp_tasha_race_ability_choice2')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_race_ability_choice3_increase')
span.choice.tasha_race_ability_choice3.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice3(name='comp_tasha_race_ability_choice3')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_race_ability_choice4_increase')
span.choice.tasha_race_ability_choice4.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice4(name='comp_tasha_race_ability_choice4')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_race_ability_choice5_increase')
span.choice.tasha_race_ability_choice5.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice5(name='comp_tasha_race_ability_choice5')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_race_ability_choice6_increase')
span.choice.tasha_race_ability_choice6.tasha(data-i18n='ability-score-increase-tasha')
select.choice.race_possible.tasha_race_ability_choice6(name='comp_tasha_race_ability_choice6')
+abilitiesOptions()
.choice.tasha_race_disabled
span(data-i18n='ability-score-increase')
p.race_ability_score.race_text
p.race_ability_choice_rule.race_text
select.choice.race_possible.race_ability_choice1(name='comp_race_ability_choice1')
+abilitiesOptions()
select.choice.race_possible.race_ability_choice2(name='comp_race_ability_choice2')
+abilitiesOptions()
select.choice.race_possible.race_ability_choice3(name='comp_race_ability_choice3')
+abilitiesOptions()
each val in globalAttributesByCategory.abilities
label.choice.custom_race
span(data-i18n=val)
input.choice.custom_race(max='5' min='-5' name=`comp_race_custom_${val}` type='number' value='0')
.row.choice.race_always.custom_race
label
span(data-i18n='alignment')
select(name='comp_alignment')
option(data-i18n='choose' value='')
each val in globalAttributesByCategory.alignments
- const datai18n = val.toLowerCase().replace(' ', '-')
option(data-i18n=datai18n value=val)
.row.choice.race_always.custom_race
label
span(data-i18n='size')
p.race_size.race_text
select.choice.custom_race(name='comp_size')
option(data-i18n='choose' value='')
each val in globalAttributesByCategory.sizes
- const datai18n = val.toLowerCase();
option(data-i18n=datai18n value=val)
.row.choice.race_always.custom_race
label
span(data-i18n='speed')
p.race_speed.race_text
input.choice.custom_race(min='0' name='comp_speed' type='number')
.race_holder.holder
.choice.subrace
.row
label.hilite
span(data-i18n='subrace')
select.choose_subrace(name='comp_subrace' required)
option(data-i18n='choose' value='')
option.custom(data-i18n='custom' value='Rules:Races')
+buttonMancerInfo('subrace')
.choice.custom_subrace
label.hilite
span(data-i18n='charmancer-custom-subrace-name')
input(name='comp_subrace_name' placeholder='Custom Subrace' type='text' required)
.choice.subrace_options
.row.choice.subrace_possible.subrace_abilities.custom_subrace
label
.choice.tasha_subrace_enabled
input(type='hidden' name='comp_tasha_subrace_ability_choice1_increase')
span.choice.tasha_subrace_ability_choice1.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice1(name='comp_tasha_subrace_ability_choice1')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_subrace_ability_choice2_increase')
span.choice.tasha_subrace_ability_choice2.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice2(name='comp_tasha_subrace_ability_choice2')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_subrace_ability_choice3_increase')
span.choice.tasha_subrace_ability_choice3.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice3(name='comp_tasha_subrace_ability_choice3')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_subrace_ability_choice4_increase')
span.choice.tasha_subrace_ability_choice4.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice4(name='comp_tasha_subrace_ability_choice4')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_subrace_ability_choice5_increase')
span.choice.tasha_subrace_ability_choice5.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice5(name='comp_tasha_subrace_ability_choice5')
+abilitiesOptions()
input(type='hidden' name='comp_tasha_subrace_ability_choice6_increase')
span.choice.tasha_subrace_ability_choice6.tasha(data-i18n='ability-score-increase-tasha')
select.choice.subrace_possible.tasha_subrace_ability_choice6(name='comp_tasha_subrace_ability_choice6')
+abilitiesOptions()
.choice.tasha_subrace_disabled
span(data-i18n='subrace-ability-increase')
p.subrace_ability_score.subrace_text
- let subraceChoiceInt = 1;
while subraceChoiceInt <= 3
select(class=`choice subrace_possible subrace_ability_choice${subraceChoiceInt}` name=`comp_subrace_ability_choice${subraceChoiceInt}`)
+abilitiesOptions()
- subraceChoiceInt++
each val in globalAttributesByCategory.abilities
label.choice.custom_subrace
span(data-i18n=val)
input.choice.custom_subrace(max='5' min='-5' name=`comp_subrace_custom_${val}` type='number' value='0')
.row.choice.subrace_possible.subrace_speed_row.custom_subrace
label
span(data-i18n='speed')
p.subrace_speed.subrace_text
input.choice.custom_subrace(name='comp_speed' min='0' type='number')
.subrace_holder.holder
.row.choice.race_possible.custom_race.custom_subrace
label
span(data-i18n='innate-spellcasting:')
label
span(data-i18n='spellcasting-ability')
select(name='comp_custom_race_spell_ability')
+abilitiesOptions()
label.hilite.choice.custom_spellcasting
span(data-i18n='number-of-cantrips')
input(min='1' name='comp_custom_race_spell_number' type='number' value='1' required)
label.hilite.choice.custom_spellcasting
span(data-i18n='spell-list')
select(name='comp_custom_race_spell_list')
+classOptions()
+infoDiv('race','Rules:Races')
+bottomBar('welcome', 'class')
+cancelPrompt('race')
input(name='comp_has_subrace' type='hidden')
//- Class slide is throwing an error when converted to pug
include ../html/charactermancer/class.html
charmancer.sheet-charmancer-l1-abilities
.charmancer.container
ol.steps
.topbar-holder
input(name='comp_pointbuy_points' type='hidden' value='27')
input(name='comp_roll_results' type='hidden' value='0')
.choices
.row
label.hilite
span(data-i18n='ability-score-method')
select(name='comp_abilities' required)
option(data-i18n='choose' value='')
option.custom(data-i18n='custom' value='custom')
.row.choice.abilities_possible.abilities_stdarray
p(data-i18n='select-your-choices')
button(data-i18n='clear-abilities' name='act_clearstats' type='action')
.row.choice.abilities_possible.abilities_rollstats
p(data-i18n='select-your-choices')
p
.rollstats-button
button(data-i18n='standard-roll' type="roll" name="roll_rollstats" value="@{wtype}&{template:mancerroll} {{title=Roll for Stats}} {{r1=[[4d6dl1]]}} {{r2=[[4d6dl1]]}} {{r3=[[4d6dl1]]}} {{r4=[[4d6dl1]]}} {{r5=[[4d6dl1]]}} {{r6=[[4d6dl1]]}}")
button(data-i18n='clear-abilities' name='act_clearstats' type='action')
.row.choice.abilities_possible.abilities_rollstats_rolled
p
span(data-i18n='stats-rolled-hint')
.row.choice.abilities_possible.abilities_pointbuy
p(data-i18n='select-your-choices')
p
span(data-i18n='available-points:')
strong
span(class='points_available_display')
button(data-i18n='clear-abilities' name='act_clearstats' type='action')
.choice.abilities_possible.abilities_selects
.row
.hilite
each val in globalAttributesByCategory.abilities
div
span.label(data-i18n=val)
span(class=`abilities_radio_${val}` name=`comp_${val}` required)
each val in globalAttributesByCategory.optionalAbilites
.sheet-choice(class=`${val}_toggle`)
span.label(data-i18n=val)
span(class=`abilities_radio_${val}` name=`comp_${val}` required)
.row.choice.abilities_possible.abilities_custom
p(data-i18n='input-your-scores')
.abilities_possible.abilities_selects
.hilite
each val in globalAttributesByCategory.abilities
div
span.label(data-i18n=val)
input(max='20' min='0' name=`comp_${val}` type='number' required)
each val in globalAttributesByCategory.optionalAbilites
.sheet-choice(class=`${val}_toggle`)
span.label(data-i18n=val)
input(min="0" max="20" name=`comp_${val}` type="number" required)
+infoDiv('abilscores','Rules:Ability%20Scores')
+bottomBar('class', 'background')
+cancelPrompt('abilities')
mixin backgroundOptions(type)
label
span(data-i18n=type)
br
select.choice.background_possible.background_ideal_choice(name=`comp_background_${type}_choice`)
option(data-i18n='choose' value='')
button.choice.standardbg.bg_roll(data-i18n='roll' name=`roll_background_${type}_choice_roll` type='roll' value='')
input.choice.custom_background(name=`comp_background_${type}_choice` type='text')
charmancer.sheet-charmancer-l1-background
.charmancer.container
ol.steps
.topbar-holder
.choices
.row
label.hilite
span(data-i18n='choose-background')
select(accept='Category:Backgrounds' name='comp_background' required)
option(data-i18n='choose' value='')
option.custom(data-i18n='custom' value='Rules:Backgrounds')
.choice.custom_background
label.hilite
span(data-i18n='name-background')
input(name='comp_background_name' placeholder='Artisan' type='text' required)
.choice.backgrounds_options
.holder.background_holder
.row.choice.background_possible.background_detail_choice_row
label
span.label
span.background_detail_choice_name(data-i18n='option' name='comp_background_detail_choice_name')
br
select.choice.background_possible.background_detail_choice(name='comp_background_detail_choice')
option(data-i18n='choose' value='')
button.choice.standardbg.bg_roll(data-i18n='roll' name='roll_background_detail_choice_roll' type='roll' value='')
.row.choice.background_possible.background_personality_row.custom_background
label
span(data-i18n='personality-traits')
br
- let backgroundChoiceInt = 1;
while backgroundChoiceInt <= 2
select.choice.background_possible.background_personality_choice1(name=`comp_background_personality_choice${backgroundChoiceInt}`)
option(data-i18n='choose' value='')
button.choice.standardbg.bg_roll(data-i18n='roll' name=`roll_background_personality_choice${backgroundChoiceInt}_roll` type='roll' value='')
input.choice.custom_background(name=`comp_background_personality_choice${backgroundChoiceInt}` type='text')
- backgroundChoiceInt++
each val in ['ideal', 'bond', 'flaw']
+backgroundOptions(val)
.row.choice.background_possible.background_equipment_row
p
span.label(data-i18n='equipment')
span.background_standard_equipment
+infoDiv('background','Rules:Backgrounds')
+bottomBar('abilities', 'equipment')
+cancelPrompt('background')
each val in ['detail_choice', 'personality_choice1', 'personality_choice2', 'ideal_choice', 'bond_choice', 'flaw_choice']
input(name=`comp_background_${val}_array` type='hidden')
charmancer.sheet-charmancer-l1-equipment
.charmancer.container
ol.steps
.topbar-holder
.choices
each val in ['equipment_class', 'equipment_background', 'starting_gold_roll', 'background_starting_gold']
input(name=`comp_${val}` type='hidden')
.row
p.choice.no_class
span.label(data-i18n='you-havent-selected-class')
p.choice.eqp_custom_class
span.label(data-i18n='you-have-created-custom-class')
p.choice.no_gold_option
span.label(data-i18n='pick-your-equipment')
span :
span.class_label
.choice.has_class.equipment_type.hilite
p
span.label(data-i18n='equipment-choice-text')
span(data-i18n='class')
span :
span.class_label
select.equipment_type(name='comp_equipment_type' required)
option(data-i18n='choose' value='')
option(data-i18n='class-equipment' value='class')
option(data-i18n='starting-wealth' value='gold')
.row.choice.gold_option
p.choice.custom_class_gold
span.label(data-i18n='equipment-from-class')
span (
span.class_label
span )
p
span.label(data-i18n='starting-gold:')
p
.choice.random_gold_option
button(name='roll_starting_gold' type='roll' value='')
span.starting_gold_btn_label
input(name='comp_starting_gold' type='number' value='0')
.row.choice.class_option
p
span.class_equipment
- let equipmentChoiceInt = 1;
while equipmentChoiceInt <= 4
p.equipment_choice_title
span.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt} class_equipment_choice${equipmentChoiceInt}_title`)
select.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt}` name=`comp_class_equipment_choice${equipmentChoiceInt}`)
option(data-i18n='choose' value='')
select.choice.class_possible(class=`class_equipment_choice${equipmentChoiceInt}_double` name=`comp_class_equipment_choice${equipmentChoiceInt+4}`)
option(data-i18n='choose' value='')
- equipmentChoiceInt++
.row.choice.no_class_warning
span.warning(data-i18n='no_class_warning-u')
.row
p.choice.no_background
span.label(data-i18n='you-havent-chosen-background')
p.choice.has_background.class_option
span.label(data-i18n='equipment-from-background')
span (
span.background_label
span )
p.choice.background_chose_starting_gold.background_gold_option
span.label(data-i18n='you-have-chosen-starting-gold')
p.choice.has_background.class_option
span.background_equipment
.choice.class_option
- let backEquipInt = 1;
while backEquipInt <= 4
p.equipment_choice_title
span.choice.background_possible(class=`background_equipment_choice${backEquipInt} background_equipment_choice${backEquipInt}_title`)
select.choice.background_possible(class=`background_equipment_choice${backEquipInt}` name=`comp_background_equipment_choice${backEquipInt}`)
option(data-i18n='choose' value='')
- backEquipInt++
+infoDiv('background','Rules:Equipment')
+bottomBar('background', 'spells')
+cancelPrompt('equipment')
charmancer.sheet-charmancer-l1-spells
.charmancer.container
ol.steps
.topbar-holder
.choice.no_spells
p.label(data-i18n='arcane-is-mystery')
p(data-i18n='your-character-dont-have-spells-this-lvl')
.choices.spell_holder
.info.choice.spell-info-container
.sheet-compendium-page.sheet-spell-info(accept='Rules:Spells' class=`sheet-spells-info`)
+bottomBar('equipment', 'feat')
+cancelPrompt('spells')
each val in ['race_spells', 'class_spells', 'race_number', 'class_number']
input(name=`comp_${val}` type='hidden')
mixin featChoices(type, acceptString)
.row.choice.feat_possible(class=`feat_${type}_row`)
label
span(data-i18n=`${type}-proficiencies`)
- const typePlural = `${type}s`
p.feat_text(class=`feat_${typePlural}`)
- let choiceInt = 1;
while choiceInt <= 4
if acceptString
select.choice.feat_possible(class=`feat_${type}_choice${choiceInt}` name=`comp_feat_${type}_choice${choiceInt}` accept=acceptString)
option(data-i18n='choose' value='')
else
select.choice.feat_possible(class=`feat_${type}_choice${choiceInt}` name=`comp_feat_${type}_choice${choiceInt}`)
option(data-i18n='choose' value='')
- choiceInt++
charmancer.sheet-charmancer-l1-feat
.charmancer.container
ol.steps
.topbar-holder
.choice.no_feat
p.label(data-i18n='charmancer-a-feat-represents')
p(data-i18n='you-really-havent-done')
.choices.choice.yes_feat
.row
label
span(data-i18n='choose-a-feat:')
select(accept='Category:Feats' name='comp_feat')
option(data-i18n='choose' value='')
.choice.feat_options
.row.choice.feat_prereq.feat_possible
label.warning
span(data-i18n='prerequisite:')
p.feat_prerequisite.feat_text
p.feat_text(data-i18n='feat-pre-check')
.row.choice.feat_ability.feat_possible
label
span(data-i18n='ability-score-increase:')
p.feat_ability_score.feat_text
select.choice.feat_possible.feat_ability_choice(name='comp_feat_ability_choice')
option(data-i18n='choose' value='')
+featChoices('language')
+featChoices('skill', 'Category:Proficiencies Type:Skill')
+featChoices('weapon')
+featChoices('armor')
+featChoices('tool')
.sheet-row.sheet-choice.sheet-feat_possible.sheet-feat_spell_row
label
span(data-i18n='spell-list') Spell List:
span(style='color: red;')
p.sheet-feat_text.sheet-feat_spells
select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice1(name='comp_feat_spell_choice1')
option(data-i18n='choose' value='') Choose
select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice2(name='comp_feat_spell_choice2')
option(data-i18n='choose' value='') Choose
select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice3(name='comp_feat_spell_choice3')
option(data-i18n='choose' value='') Choose
select.sheet-choice.sheet-feat_possible.sheet-feat_spell_choice4(name='comp_feat_spell_choice4')
option(data-i18n='choose' value='') Choose
.row.choice.feat_possible.feat_expertise_row
label
span(data-i18n='expertise')
each val in [1, 2]
select(class=`choice feat_possible feat_expertise_choice${val}` name=`comp_feat_expertise_choice_${val}`)
option(data-i18n='choose' value='')
.row.choice.feat_possible.feat_feature_row_1
h4.feat_feature_name_1
span(class='feat_feature_1')
select.feat_possible.feat_feature_choice_1(name='comp_feat_feature_choice_1')
option(data-i18n='choose' value='')
option.custom(data-i18n='custom')
p.description.feat_feature_description_1
.row.choice.feat_possible.feat_feature_row_1_double
h4.feat_feature_name_1_double
span.feat_feature_1_double
select.feat_possible.feat_feature_choice_1_double(name='comp_feat_feature_choice_3')
option(data-i18n='choose' value='')
option.custom(data-i18n='custom')
p.description.feat_feature_description_1_double
.row.choice.feat_possible.feat_feature_row_2
h4.feat_feature_name_2
span.feat_feature_2
select.feat_possible.feat_feature_choice_2(name='comp_feat_feature_choice_2')
option(data-i18n='choose' value='')
option.custom(data-i18n='custom')
p.description.feat_feature_description_2
.choice.row.feat_possible.other_options_and_features1
label
span.other_options_and_features_title1
select.feat_possible.other_options_and_features_choice1(name='comp_other_options_and_features_choice1')
option(data-i18n='choose' value='')
.choice.row.feat_possible.other_options_and_features2
label
span.other_options_and_features_title2
select.feat_possible.other_options_and_features_choice1(name='comp_other_options_and_features_choice2')
option(data-i18n='choose' value='')
.info.feat-info-container.choice.yes_feat
.sheet-compendium-page.sheet-feat-info(accept='Rules:Feats')
+bottomBar('spells', 'bio')
+cancelPrompt('feat')
charmancer.sheet-charmancer-l1-bio
.charmancer.container
ol.steps
.topbar-holder
.choices
input(name='comp_previous_race' type='hidden' value='')
each val in ['Name', 'Age', 'Height', 'Weight', 'Eyes', 'Hair', 'Skin']
- const attributeName = val === 'Name' ? 'character_name' : val.toLowerCase();
- const datai18n = val === 'Name' ? 'char-name-u' : val === 'Eyes' ? `eye-u` : `${val.toLowerCase()}-u`;
.row
label
div(data-i18n=datai18n)
input(name=`comp_${attributeName}` type='text')
+infoDiv('race','Rules:Races')
+bottomBar('feat', 'summary')
+cancelPrompt('bio')
mixin summaryBlocks(type)
.summary
p.label(data-i18n=type)
div(class=`${type}_info`)
.choice.returnblock(class=`${type}_button`)
span(data-i18n='return-to:')
button.step(data-i18n=`${type}-u` type='back' value=`l1-${type}`)
charmancer.sheet-charmancer-l1-summary
.charmancer
ol.steps
.topbar-holder
p.choice.ready_text(data-i18n='charmancer-only-choice-left-is-on-or')
p.label.ready_message
p.label(data-i18n='review-your-choices')
.summary-container
+summaryBlocks('race')
+summaryBlocks('class')
+summaryBlocks('abilities')
+summaryBlocks('background')
+summaryBlocks('equipment')
+summaryBlocks('spells')
.summary
p.label(data-i18n='feats')
.feat_info
.summary
p.label(data-i18n='bio')
.race_warning
.bio_info
.bottombar
button.prev(data-i18n='back' type='back' value='l1-bio')
button.jump(data-i18n='back-to-top' data-scroll='#top' type='button')
button.next.apply_changes(data-i18n='apply-changes' type='finish' value=`l1-mancer`)
+cancelPrompt('summary')
charmancer.sheet-charmancer-final
.charmancer
div
h1(data-i18n='building-your-character')
.mancer_progress
div(style='width: 0%')
input(name='attr_mancer_category' type='hidden')
input(name='attr_mancer_progress' type='hidden')
@@ -0,0 +1,61 @@
.header
.name-container
img(src='https://app.roll20.net/images/dndstyling/srd5_360.png' style='padding-bottom: 5px;' alt='SRD5 by Roll20')
input(type='text' name='attr_character_name' style='width: 100%;')
span.label(data-i18n='char-name-u') CHARACTER NAME
input.options-flag(type='checkbox' name='attr_options-class-selection' checked='checked')
span y
.header-info.options
.row(style='border-top: 2px dashed gold;')
span(data-i18n='class:-u') CLASS:
input.flag(type='hidden' name='attr_custom_class')
select.hiding.class(name='attr_class')
option(value='' data-i18n='choose') Choose
option(value='Artificer' data-i18n='artificer') Artificer
option(value='Barbarian' data-i18n='barbarian') Barbarian
option(value='Bard' data-i18n='bard') Bard
option(value='Cleric' data-i18n='cleric') Cleric
option(value='Druid' data-i18n='druid') Druid
option(value='Fighter' data-i18n='fighter') Fighter
option(value='Monk' data-i18n='monk') Monk
option(value='Paladin' data-i18n='paladin') Paladin
option(value='Ranger' data-i18n='ranger') Ranger
option(value='Rogue' data-i18n='rogue') Rogue
option(value='Sorcerer' data-i18n='sorcerer') Sorcerer
option(value='Warlock' data-i18n='warlock') Warlock
option(value='Wizard' data-i18n='wizard') Wizard
input.showing(type='text' name='attr_cust_classname' style='width: 90px;')
span(data-i18n='subclass:-u') SUBCLASS:
input(type='text' name='attr_subclass')
span(data-i18n='lvl:-u') LEVEL:
input.class-level(type='number' style='width: 40px' name='attr_base_level' value='1')
.row
span(data-i18n='race:-u') RACE:
input(type='text' name='attr_race')
span(data-i18n='subrace:-u') SUBRACE:
input(type='text' name='attr_subrace')
.header-info.display
.top
.hlabel-container
input.class-display.no_events(type='text' name='attr_class_display')
span.label(data-i18n='class-level-u') CLASS &amp; LEVEL
.hlabel-container
input(type='text' name='attr_background' style='width: 182px;')
span.label(data-i18n='background-u') BACKGROUND
.bottom
.hlabel-container
input.no_events(type='text' name='attr_race_display')
span.label(data-i18n='race-u') RACE
.hlabel-container
input(type='text' name='attr_alignment')
span.label(data-i18n='alignment-u') ALIGNMENT
.hlabel-container(style='position: relative;')
input(type='hidden' name='attr_invalidXP')
input(type='text' name='attr_experience')
span.label(data-i18n='exp-pts-u') EXPERIENCE POINTS
input.showleveler(type='hidden' name='attr_showleveler' value='0')
button.levelerbutton(type='action' name='act_launch_lvl+mancer' style='padding: 0px; position: absolute; top: -10px; right: 0px;' title='Charactermancer Level Up')
img(src='https://s3.amazonaws.com/files.d20.io/images/175804938/qmVmtNHONHhHcd9cxCxm7w/med.png?1604618286' style='height: 18px; width: 18px; max-width: inherit;' alt='Wand & Hammer logo of Charactermancer')
.invalidXP
span.icon !
span.message(data-i18n='invalidxp') Enter a number for Level Up reminder
@@ -0,0 +1,24 @@
.header
.alignment
input.alignment__value(name="attr_alignment", type="text")
.alignment__label(data-i18n="Alignment") Alignment
.playername
input.playername__value(name="attr_playername", type="text")
.playername__label(data-i18n="Player Name") Player Name
.logo
.classlevel
.class
input.class__value(type="text", name="attr_class", title="@{class}")
.class__label(data-i18n="Class") Class
.level
input.level__value(type="text", name="attr_level", title="@{level}")
.level__label(data-i18n="Level") Level
.background
input.background__value(name="attr_background", type="text")
.background__label(data-i18n="Background") Background
.name
input.name__value(name="attr_character_name", type="text")
.name__label(data-i18n="Character Name") Character Name
.race
input.race__value(name="attr_race", type="text")
.race__label(data-i18n="Race") Race
@@ -0,0 +1,181 @@
input.ammoflag(type='hidden' name='attr_ammotracking')
.attacks()
.attacks__header
span(data-i18n='name-u') NAME
span(data-i18n='atk-u') ATK
span(data-i18n='dmg-type-u') DAMAGE/TYPE
fieldset.repeating_attack
.attack
input.options__flag(name='attr_options-flag', type="hidden", value='on')
.attack__display
button.attack__button(type='roll' name='roll_attack' value='@{rollbase}')
span.attack__name(name='attr_atkname')
input.attack__bonus(type='text' name='attr_atkbonus' value='')
input.attack__type(type='text' name='attr_atkdmgtype' value='')
.options__cog
input(type='checkbox' name='attr_options-flag' checked='checked')
span y
.attack__options.options
.options__row
span.options__label(data-i18n='name:-u') NAME:
input(type='text' name='attr_atkname')
.options__row.options__row--noborder
input(type='checkbox' name='attr_atkflag' value='{{attack=1}}' checked='checked')
span.options__label(data-i18n='attack:-u') ATTACK:
select(name='attr_atkattr_base')
option(value='@{strength_mod}' selected='selected' data-i18n='str-u') STR
option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
option(value='@{constitution_mod}' data-i18n='con-u') CON
option(value='@{intelligence_mod}' data-i18n='int-u') INT
option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
option(value='@{charisma_mod}' data-i18n='cha-u') CHA
option(value='spell' data-i18n='spell-u') SPELL
option(value='0') -
span +
input(type='text' name='attr_atkmod' placeholder='0')
span +
input(type='checkbox' name='attr_atkprofflag' value='(@{pb})' checked='checked' )
span(data-i18n='proficient-u') PROFICIENT
.options__row.options__row--noborder
span.options__label(data-i18n='range:-u') RANGE:
input(type='text' name='attr_atkrange' placeholder='Self (60-foot cone)' data-i18n-placeholder='range-place')
.options__row
span.options__label(data-i18n='magic-bonus:-u') MAGIC BONUS:
input.options__flex--2(type='text' name='attr_atkmagic' placeholder='0')
span.options__label(data-i18n='crit-range-u') CRIT RANGE:
input.options__flex--2(type='text' name='attr_atkcritrange' value='20' placeholder='20')
.options__row.options__row--noborder
input(type='checkbox' name='attr_dmgflag' value='{{damage=1}} {{dmg1flag=1}}' checked='checked')
span.options__label(data-i18n='damage:-u') DAMAGE:
input(type='text' name='attr_dmgbase' placeholder='1d6' )
span.options__label +
select(name='attr_dmgattr')
option(value='@{strength_mod}' selected='selected' data-i18n='str-u') STR
option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
option(value='@{constitution_mod}' data-i18n='con-u') CON
option(value='@{intelligence_mod}' data-i18n='int-u') INT
option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
option(value='@{charisma_mod}' data-i18n='cha-u') CHA
option(value='spell' data-i18n='spell-u') SPELL
option(value='0') -
span.options__label +
input(type='text' name='attr_dmgmod' placeholder='0')
.options__row
span.options__label(data-i18n='type:-u') TYPE:
input(type='text' name='attr_dmgtype' placeholder='Slashing' data-i18n-placeholder='dmg-type-place')
span.options__label(data-i18n='crit:-u') CRIT:
input(type='text' name='attr_dmgcustcrit' placeholder='1d6' )
.options__row.options__row--noborder
input(type='checkbox' name='attr_dmg2flag' value='{{damage=1}} {{dmg2flag=1}}')
span.options__label(data-i18n='damage2:-u') DAMAGE2:
input(type='text' name='attr_dmg2base' placeholder='1d6' )
span.options__label +
select(name='attr_dmg2attr')
option(value='@{strength_mod}' data-i18n='str-u') STR
option(value='@{dexterity_mod}' data-i18n='dex-u') DEX
option(value='@{constitution_mod}' data-i18n='con-u') CON
option(value='@{intelligence_mod}' data-i18n='int-u') INT
option(value='@{wisdom_mod}' data-i18n='wis-u') WIS
option(value='@{charisma_mod}' data-i18n='cha-u') CHA
option(value='spell' data-i18n='spell-u') SPELL
option(value='0' selected='selected') -
span.options__label +
input(type='text' name='attr_dmg2mod' placeholder='0')
.options__row
span(data-i18n='type:-u') TYPE:
input(type='text' name='attr_dmg2type' placeholder='Slashing' data-i18n-placeholder='dmg-type-place')
span(data-i18n='crit:-u') CRIT:
input(type='text' name='attr_dmg2custcrit' placeholder='1d6' )
.options__row.options__row--noborder
input(type='checkbox' name='attr_saveflag' value='{{save=1}} {{saveattr=@{saveattr}}} {{savedesc=@{saveeffect}}} {{savedc=[[[[@{savedc}]][SAVE]]]}}')
span.options__label(data-i18n='saving-throw:-u') SAVING THROW:
select.options__flex(name='attr_saveattr')
option(value='Strength' selected='selected' data-i18n='str-u') STR
option(value='Dexterity' data-i18n='dex-u') DEX
option(value='Constitution' data-i18n='con-u') CON
option(value='Intelligence' data-i18n='int-u') INT
option(value='Wisdom' data-i18n='wis-u') WIS
option(value='Charisma' data-i18n='cha-u') CHA
.options__row.options__row--noborder
span.options__label.options__flex--4(data-i18n='vs-dc:-u') VS DC:
select.options__flex(name='attr_savedc')
option(value='(@{spell_save_dc})' selected='selected' data-i18n='spell-u') SPELL
option(value='(@{strength_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='str-u') STR
option(value='(@{dexterity_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='dex-u') DEX
option(value='(@{constitution_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='con-u') CON
option(value='(@{intelligence_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='int-u') INT
option(value='(@{wisdom_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='wis-u') WIS
option(value='(@{charisma_mod}+8+@{spell_dc_mod}+@{pb})' data-i18n='cha-u') CHA
option(value='(@{saveflat})' data-i18n='flat-u') FLAT
input.flatflag(type='hidden' name='attr_savedc')
input.flat(type='text' name='attr_saveflat' placeholder='10' value='10')
.options__row
span.options__label.options__flex--4(data-i18n='save-effect:-u') SAVE EFFECT:
input(type='text' name='attr_saveeffect' placeholder='half damage' data-i18n-placeholder='save-effect-place')
.options__row
span.options__label(data-i18n='ammunition:-u') AMMUNITION:
input(type='text' name='attr_ammo' placeholder='Arrows' data-i18n-placeholder='ammunition-place')
.options__row
span.options__label(data-i18n='description:-u') DESCRIPTION:
textarea(name='attr_atk_desc' placeholder='Up to 2 creatures within 5 feet' data-i18n-placeholder='description-place')
input(type='hidden' name='attr_rollbase')
input(type='hidden' name='attr_rollbase_dmg')
input(type='hidden' name='attr_rollbase_crit')
input(type='hidden' name='attr_hldmg')
input(type='hidden' name='attr_spelllevel')
input(type='hidden' name='attr_itemid')
input(type='hidden' name='attr_spellid')
input(type='hidden' name='attr_spell_innate')
input(type='hidden' name='attr_versatile_alt')
button.hidden(type='roll' name='roll_attack_dmg' value='@{rollbase_dmg}')
button.hidden(type='roll' name='roll_attack_crit' value='@{rollbase_crit}')
input.toggleflag(type='hidden' name='attr_global_attack_mod_flag')
.hidden.textbox.globalattack
span(data-i18n='global-attack-u') GLOBAL ATTACK MODIFIER
fieldset.repeating_tohitmod
.global-mod
input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' )
span y
input.active-flag(type='checkbox' name='attr_global_attack_active_flag' value='1')
.options
.row
span(data-i18n='name:-u') NAME:
input(type='text' name='attr_global_attack_name' value='' placeholder='Bless')
.row
span(data-i18n='roll:-u') ROLL:
input(type='text' name='attr_global_attack_roll' value='' placeholder='1d4')
.globaldisplay
button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_attack_name}}} {{r1=[[@{global_attack_roll}]]}} {{normal=1}} @{charname_output}')
span(name='attr_global_attack_roll')
span(name='attr_global_attack_name')
input.toggleflag(type='hidden' name='attr_global_damage_mod_flag')
.hidden.globalattack.global-dmg
span(data-i18n='global-damage-u') GLOBAL DAMAGE MODIFIER
fieldset.repeating_damagemod
.global-mod
input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' )
span y
input.active-flag(type='checkbox' name='attr_global_damage_active_flag' value='1')
.options
.row
span(data-i18n='name:-u') NAME:
input(type='text' name='attr_global_damage_name' value='' placeholder='Sneak Attack')
.row
span(data-i18n='dmg:-u') DAMAGE:
input(type='text' name='attr_global_damage_damage' value='' placeholder='1d6')
.row
span(data-i18n='critical-dmg:-u') CRITICAL DAMAGE:
input(type='text' name='attr_global_damage_critical_damage' value='' placeholder='1d6')
.row
span(data-i18n='type:-u') TYPE:
input(type='text' name='attr_global_damage_type' value='' placeholder='Sneak')
.display
span.title(name='attr_global_damage_name')
span.subheader
button.ellipsis(type='roll' name='roll_global_save' value='@{wtype}&{template:simple} {{rname=@{global_damage_type}}} {{r1=[[@{global_damage_damage}]]}} {{normal=1}} @{charname_output}')
span(name='attr_global_damage_damage')
span(name='attr_global_damage_critical_damage')
span(name='attr_global_damage_type')
.attacks__label(data-i18n="Attacks & Spellcasting") Attacks & Spellcasting
@@ -0,0 +1,13 @@
.money
.coin
span.coin__label(data-i18n="L")
input(type="number", name="attr_l", placeholder="0")
.coin
span.coin__label(data-i18n="P")
input(type="number", name="attr_p", placeholder="0")
.coin
span.coin__label(data-i18n="S")
input(type="number", name="attr_s", placeholder="0")
.coin
span.coin__label(data-i18n="G")
input(type="number", name="attr_g", placeholder="0")
@@ -0,0 +1,31 @@
.deathsaves
.deathsaves__container
.deathsaves__label
button(
type="roll",
name="roll_death_save",
value="@{wtype}&{template:simple} {{rname=^{death-save-u}}} {{mod=@{death_save_bonus}}} {{r1=[[@{d20}+@{death_save_bonus}[MOD]@{globalsavingthrowbonus}]]}} {{normal=1}} {{global=@{global_save_mod}}} @{charname_output}",
data-i18n="death-saves-u"
) DEATH SAVES
.deathsaves__successes
span.deathsaves__text(data-i18n="successes-u") SUCCESSES
.deathsaves__check
input(type="checkbox", name="attr_deathsave_succ1")
span
.deathsaves__check
input(type="checkbox", name="attr_deathsave_succ2")
span
.deathsaves__check
input(type="checkbox", name="attr_deathsave_succ3")
span
.deathsaves__failures
span.deathsaves__text(data-i18n="failures-u") FAILURES
.deathsaves__check
input(type="checkbox", name="attr_deathsave_fail1")
span
.deathsaves__check
input(type="checkbox", name="attr_deathsave_fail2")
span
.deathsaves__check
input(type="checkbox", name="attr_deathsave_fail3")
span
@@ -0,0 +1,65 @@
.equipment
.equipment__header
span.equipment__count.pictos *
span.equipment__title(data-i18n="item-name-u") ITEM NAME
span.equipment__weighti
img(
src="https://app.roll20.net/images/dndstyling/weight_lbs.png",
alt="Weight symbol"
)
fieldset.repeating_inventory
.item
input.item__optionsflag(type="hidden", name="attr_inventory_options")
.item__titlerow
input.item__equipped(
type="checkbox",
name="attr_equipped",
value="1",
checked="checked"
)
input.item__count(type="text", name="attr_itemcount", value="1")
input.item__name(type="text", name="attr_itemname")
input.item__weight(type="text", name="attr_itemweight")
.item__optionsflag
input.item__optionscheck(
type="checkbox",
name="attr_inventory_options"
)
span.pictos y
.item__options.options
.options__row.options__row--checkbox
input.equipped(
type="checkbox",
name="attr_equipped",
value="1",
checked="checked"
)
span.equippedlabel(data-i18n="equipped-u") EQUIPPED
.options__row.options__row--checkbox
input.equipped(type="checkbox", name="attr_useasresource", value="1")
span.equippedlabel(data-i18n="use-as-resource-u") USE AS A RESOURCE
.options__row.options__row--checkbox
input.equipped(type="checkbox", name="attr_hasattack", value="1")
span.equippedlabel(data-i18n="has-attack-u") HAS AN ATTACK
.options__row
span(data-i18n="prop:-u") PROP:
input(type="text", name="attr_itemproperties")
.options__row
span(data-i18n="mods:-u") MODS:
input(type="text", name="attr_itemmodifiers")
.options__row
textarea.subtextarea(name="attr_itemcontent")
input(type="hidden", name="attr_itemattackid")
input(type="hidden", name="attr_itemresourceid")
.equipment__weighttotal
span.equipment__encumbrancetitle(data-i18n="total-weight-u") TOTAL WEIGHT
input.equipment__encumbrance(
type="number",
name="attr_weighttotal",
value="0"
)
input(type="hidden", name="attr_encumbrance")
.equipment__label(data-i18n="Equipment") Equipment
@@ -0,0 +1,12 @@
.exhaustions
input(type="hidden", name="attr_exhaustion", value="0")
.exhaustions__checks
each i in [0, 1, 2, 3, 4, 5, 6]
.exhaustion
input.exhaustion__radio(type="radio", name="attr_exhaustion", value=i)
span.exhaustion__text= i
.exhaustions__tracker
each url, i in ["https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-0_wulpge.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-1_fzmarb.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-2_prwgr3.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-3_hvsfbn.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-4_bnucar.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-5_ncgzva.png", "https://res.cloudinary.com/dmrhbjudf/image/upload/v1626558383/exhaustion-6_zles7f.png"]
- const className = `exhaustions__level--${i}`;
img.exhaustions__level(class=className, src=url)
span.exhaustions__label(data-i18n="Exhaustion") Exhaustion
@@ -0,0 +1,32 @@
.features
.features__label(data-i18n="feats-traits-u") FEATURES &amp; TRAITS
fieldset.repeating_traits
.feature
input.feature__flag--options(type="hidden" name="attr_options-flag" value="on")
.feature__display
span.feature__title(name="attr_name")
span.feature__subheader
span(name="attr_source")
span :
span(name="attr_source_type")
button.feature__chat-button(type="roll" name="roll_output" value="@{wtype}&{template:traits} @{charname_output} {{name=@{name}}} {{source=@{source}: @{source_type}}} {{description=@{description}}}") w
.feature__options-container
input.feature__flag--options(type="checkbox" name="attr_options-flag" checked="checked")
span y
.feature__options.options
.options__row
span(data-i18n="name:-u") NAME:
input(type="text" name="attr_name")
.options__row
span(data-i18n="source:-u") SOURCE:
select(name="attr_source")
option(selected="selected" data-i18n="racial") Racial
option(data-i18n="class") Class
option(data-i18n="feat") Feat
option(data-i18n="background") Background
option(data-i18n="other") Other
.options__row
span(data-i18n="source-type:-u") SOURCE TYPE:
input(type="text" name="attr_source_type" placeholder="Dwarf/Fighter/4th Level")
.options__row
textarea(name="attr_description")
@@ -0,0 +1,22 @@
input.toggleflag(type='hidden' name='attr_global_ac_mod_flag')
.equipment.hidden
.textarea.globalattack.acmod
fieldset.repeating_acmod
.global-mod
input.options-flag(type='checkbox' name='attr_options-flag' checked='checked' style='top: -15px;')
span y
input.active-flag(type='checkbox' name='attr_global_ac_active_flag' value='1')
.options
label
| Value:
input(type='number' name='attr_global_ac_val' placeholder='1')
label
| Name:
input(type='text' name='attr_global_ac_name' placeholder='Defense')
.display
span.title.ellipsis
span(name='attr_global_ac_val')
| [
span(name='attr_global_ac_name')
| ]
span.label(data-i18n='global-ac-u') GLOBAL AC MODIFIER

Some files were not shown because too many files have changed in this diff Show More