Files
roll20-character-sheets/LandOfEem/landofeem.html
T

1437 lines
71 KiB
HTML

<input type="hidden" name="attr_sheet_type" class="sheet-type-select" value="pc">
<div class="container">
<div class="eem">
<input type="hidden" name="attr_sheet_type" class="sheet-type-select" value="pc">
<!--********* PC HEADER **********-->
<div class="header sheet-type-pc">
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns">
<label for="attr_character_name" data-i18n="name-and-pronouns">Name & Pronouns</label>
<input type="text" id="attr_character_name" name="attr_character_name" />
<label for="attr_class" data-i18n="class">Class</label>
<input type="text" id="attr_class" name="attr_class" list="class-list" data-i18n-dynamic />
<datalist id="class-list">
<option data-i18n="bard">Bard</option>
<option data-i18n="dungeoneer">Dungeoneer</option>
<option data-i18n="gnome">Gnome</option>
<option data-i18n="knight-errant">Knight-Errant</option>
<option data-i18n="loyal-chum">Loyal Chum</option>
<option data-i18n="rascal">Rascal</option>
</datalist>
</div>
</div>
</div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns"><label for="attr_folk" data-i18n="folk">Folk</label><input type="text" id="attr_folk" name="attr_folk" /><label for="attr_homeland" data-i18n="homeland">Homeland</label><input type="text" id="attr_homeland" name="attr_homeland" /></div>
</div>
</div>
<div class="xp-rows">
<div class="xp-background"><img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/xp_bw.png" /></div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns"><label for="attr_lv" data-i18n="lv">LV</label><input type="number" name="attr_lv" /></div>
</div>
</div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns"><label for="attr_xp" data-i18n="xp">XP</label><input type="number" name="attr_xp" /></div>
</div>
</div>
</div>
<div class="logo"><img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/logo-flat.png" alt="Land of Eem Logo" /></div>
<img class="top-avatar" name="attr_character_avatar" />
</div>
<!--********* NPC HEADER **********-->
<div class="header sheet-type-npc">
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns">
<label for="attr_character_name" data-i18n="name">Name</label>
<input type="text" id="attr_character_name" name="attr_character_name" />
<label for="attr_folk" data-i18n="folk">Folk</label>
<input type="text" id="attr_folk" name="attr_folk" />
</div>
</div>
</div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns">
<label for="attr_job" data-i18n="job">Job</label>
<input type="text" id="attr_job" name="attr_job" />
<label for="attr_detail" data-i18n="detail">Detail</label>
<input type="text" id="attr_detail" name="attr_detail" />
</div>
</div>
</div>
<div class="logo"><img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/logo-flat.png" alt="Land of Eem Logo" /></div>
<img class="top-avatar" name="attr_character_avatar" />
</div>
<!--********* ADVERSARY HEADER **********-->
<div class="header sheet-type-adversary">
<input class="adversary-name" name="attr_character_name" type="text" />
<input type="hidden" name="attr_adversary_type" class="adversary-type" value="creature">
<div class="adversary-type-symbol"></div>
<div class="logo"><img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/logo-flat.png" alt="Land of Eem Logo" /></div>
<img class="top-avatar" name="attr_character_avatar" />
</div>
<!--********* NAV BAR **********-->
<input type="hidden" class="sheet-tabstoggle" name="attr_sheetTab" value="attributes" />
<div class="nav-bar">
<input type="hidden" name="attr_sheet_type" class="sheet-type-select" value="pc">
<button type="action" name="act_npc" class="sheet-type-npc sheet-button-npc" data-i18n="npc">NPC</button>
<button type="action" name="act_adversary-preview" class="sheet-type-adversary sheet-button-preview" data-i18n="preview">Preview</button>
<button type="action" name="act_adversary-definition" class="sheet-type-adversary sheet-button-adversary" data-i18n="definition">Definition</button>
<button type="action" name="act_attributes" class="sheet-type-pc sheet-button0" data-i18n="attributes-and-abilities">Attributes</button>
<button type="action" name="act_inventory" class="sheet-type-pc sheet-button1" data-i18n="inventory-and-crafting">Inventory</button>
<button type="action" name="act_background" class="sheet-type-pc sheet-button2" data-i18n="personality-and-backstory">Background</button>
<button type="action" name="act_notes" class="sheet-type-pc sheet-button3" data-i18n="notes-and-portrait">Journal</button>
<button type="action" name="act_portrait" class="sheet-button4" data-i18n="portrait">Portrait</button>
<button type="action" name="act_settings" class="sheet-button5"><span data-i18n="settings">Settings</span><span class="gear-icon" style="font-family:Pictos;">x</span></button>
</div>
<!--********* SHEET - NPC **********-->
<div class="sheet-npc">
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content">
<label class="hint" data-i18n="traits">Traits</label>
<textarea rows="3" name="attr_traits"></textarea>
</div>
</div>
</div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content">
<label class="hint" data-i18n="motivation">Motivation</label>
<textarea rows="3" name="attr_motivation"></textarea>
</div>
</div>
</div>
<div style="grid-column-end: span 2;"></div>
<div class="note-box" style="grid-column-end: span 2;">
<div>
<h2 data-i18n="location" class="hint">Current Location</h2>
<textarea rows="2" name="attr_location"></textarea>
</div>
</div>
<div class="note-box flexible" style="grid-column-end: span 2;">
<div>
<h2 data-i18n="description" class="hint">Description</h2>
<textarea name="attr_description"></textarea>
</div>
</div>
</div>
<!--********* SHEET - ADVERSARY PREVIEW **********-->
<div class="sheet-adversary-preview">
<input type="hidden" name="attr_adversary_type" class="adversary-type" value="creature" />
<div class="adversary-basic-info">
<div class="non-creeper">
<div class="two-columns">
<h2 data-i18n="preview-level">Level</h2>
<input type="hidden" name="attr_max_level" class="max-level" />
<input type="hidden" name="attr_min_level" class="min-level" />
<select name="attr_adversary_level">
<option value="1" class="lt-2 lt-3 lt-4 lt-5 lt-6 lt-7 lt-8 lt-9 lt-10">1</option>
<option value="2" class="lt-3 lt-4 lt-5 lt-6 lt-7 lt-8 lt-9 lt-10 gt-1">2</option>
<option value="3" class="lt-4 lt-5 lt-6 lt-7 lt-8 lt-9 lt-10 gt-1 gt-2">3</option>
<option value="4" class="lt-5 lt-6 lt-7 lt-8 lt-9 lt-10 gt-1 gt-2 gt-3">4</option>
<option value="5" class="lt-6 lt-7 lt-8 lt-9 lt-10 gt-1 gt-2 gt-3 gt-4">5</option>
<option value="6" class="lt-7 lt-8 lt-9 lt-10 gt-1 gt-2 gt-3 gt-4 gt-5">6</option>
<option value="7" class="lt-8 lt-9 lt-10 gt-1 gt-2 gt-3 gt-4 gt-5 gt-6">7</option>
<option value="8" class="lt-9 lt-10 gt-1 gt-2 gt-3 gt-4 gt-5 gt-6 gt-7">8</option>
<option value="9" class="lt-10 gt-1 gt-2 gt-3 gt-4 gt-5 gt-6 gt-7 gt-8">9</option>
<option value="10" class="gt-1 gt-2 gt-3 gt-4 gt-5 gt-6 gt-7 gt-8 gt-9">10</option>
</select>
<h2 data-i18n="preview-size">Size</h2>
<input type="hidden" name="attr_keyword_tiny" class="keyword-tiny" />
<input type="hidden" name="attr_keyword_small" class="keyword-small" />
<input type="hidden" name="attr_keyword_medium" class="keyword-medium" />
<input type="hidden" name="attr_keyword_folk" class="keyword-folk" />
<input type="hidden" name="attr_keyword_large" class="keyword-large" />
<input type="hidden" name="attr_keyword_huge" class="keyword-huge" />
<select name="attr_adversary_size">
<option value="tiny" class="tiny" data-i18n="tiny"></option>
<option value="small" class="small" data-i18n="small"></option>
<option value="medium" class="medium" data-i18n="medium"></option>
<option value="folk" class="folk" data-i18n="folk"></option>
<option value="large" class="large" data-i18n="large"></option>
<option value="huge" class="huge" data-i18n="huge"></option>
</select>
</div>
</div>
<div class="non-creeper">
<div class="two-columns right-border">
<h2 data-i18n="preview-class">Class</h2>
<input type="hidden" name="attr_keyword_goon" class="keyword-goon" />
<input type="hidden" name="attr_keyword_bruiser" class="keyword-bruiser" />
<input type="hidden" name="attr_keyword_champion" class="keyword-champion" />
<select name="attr_adversary_class">
<option value="goon" class="goon" data-i18n="goon_short"></option>
<option value="bruiser" class="bruiser" data-i18n="bruiser_short"></option>
<option value="champion" class="champion" data-i18n="champion_short"></option>
</select>
<h2 style="grid-column-end: span 2;">(<span name="attr_abbreviation">L1-G</span>)</h2>
</div>
</div>
<div class="non-creeper">
<h2 data-i18n="adversary-levels">Levels</h2>
<span><span name="attr_min_level">1</span>-<span name="attr_max_level">10</span></span>
</div>
<div class="non-creeper">
<h2 data-i18n="adversary-classes">Classes</h2>
<span name="attr_classes">G</span>
</div>
<div class="non-creeper">
<h2 data-i18n="adversary-actions">Actions</h2>
<span name="attr_adversary_actions">1</span>
</div>
<div class="keywords"><span name="attr_keywords">-</span></div>
</div>
<div class="stat-box stat-courage">
<h2 data-i18n="courage">Courage</h2>
<input type="number" name="attr_courage_max" class="big" />
<input type="number" name="attr_courage" class="small" />
<label data-i18n="current" class="small">Current</label>
</div>
<input type="hidden" name="attr_adversary_disadvantage" class="adversary-disadvantage" value="false" />
<div class="stat-box stat-wrangle">
<h2><span data-i18n="wrangle">Wrangle</span> <span class="disadvantage-note" data-i18n="disadvantage_short">(D)</span></h2>
<input type="number" name="attr_wrangle_parley_max" class="big" value="1" min="0" max="2" />
<input type="number" name="attr_wrangle_parley" class="small" value="1" min="0" max="2" />
<label data-i18n="current" class="small">Current</label>
</div>
<div class="stat-box stat-parley">
<h2><span data-i18n="parley">Parley</span> <span class="disadvantage-note" data-i18n="disadvantage_short">(D)</span></h2>
<input type="number" name="attr_wrangle_parley_max" class="big" value="1" min="0" max="2" />
<input type="number" name="attr_wrangle_parley" class="small" value="1" min="0" max="2" />
<label data-i18n="current" class="small">Current</label>
</div>
<div class="stat-box stat-attack">
<button type="action" name="act_attack">
<h2 data-i18n="attack">Attack</h2>
</button>
<input type="text" name="attr_attack" class="big" />
<input type="text" name="attr_dread" class="small" />
<label data-i18n="dread" for="attr_dread" class="small">Dread</label>
<div style="display:block; width: 0; height: 0; overflow: visible;"><img style="opacity: 0.2; min-width: 97px ; min-height: 97px;" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/stats_2.png" /></div>
</div>
<div class="stat-box stat-defense">
<h2 data-i18n="defense">Defense</h2>
<input type="text" name="attr_defense" class="big" />
<input type="number" name="attr_block" class="small" />
<label data-i18n="block" for="attr_block" class="small">Block</label>
</div>
<div class="stat-box stat-mettle">
<button type="action" name="act_mettle">
<h2 data-i18n="mettle">Mettle</h2>
</button>
<input type="text" name="attr_mettle" class="big" value="-2" />
</div>
<div style="grid-row-start: 2; grid-column-start: 3; grid-row-end: span 4" class="note-box">
<div class="repeating_skills_container">
<h2 data-i18n="abilities">Abilities</h2>
<fieldset class="repeating_skills">
<input type="hidden" class="skilledit" name="attr_skilledit" value="0" />
<input type="checkbox" name="attr_skilledit" />
<input type="text" name="attr_skillname" value="">
<button type="action" name="act_share" class="btn-share">
<div></div>
</button>
<div class="sheet-auto-expand">
<span name="attr_skilldescription"></span>
<textarea class="skill-description" name="attr_skilldescription" rows="4"></textarea>
</div>
</fieldset>
</div>
</div>
</div>
<!--********* SHEET - ADVERSARY DEFINITION **********-->
<div class="sheet-adversary-definition">
<input type="hidden" name="attr_adversary_type" class="adversary-type" value="creature">
<h2 style="grid-column-end: span 6;" class="hint" data-i18n="adversary-type">Type</h2>
<h2 style="grid-column-end: span 6;" class="hint non-creeper" data-i18n="adversary-classes">Classes</h2>
<input type="radio" name="attr_adversary_type" value="creature" checked /><span data-i18n="creature">Creature</span>
<input type="radio" name="attr_adversary_type" value="critter" /><span data-i18n="critter">Critter</span>
<input type="radio" name="attr_adversary_type" value="creeper" /><span data-i18n="creeper">Creeper</span>
<input class="non-creeper" type="checkbox" name="attr_keyword_goon" checked /><span class="non-creeper" data-i18n="goon">Goon</span>
<input class="non-creeper" type="checkbox" name="attr_keyword_bruiser" /><span class="non-creeper" data-i18n="bruiser">Bruiser</span>
<input class="non-creeper" type="checkbox" name="attr_keyword_champion" /><span class="non-creeper" data-i18n="champion">Champion</span>
<div class="separator non-creeper"></div>
<h2 style="grid-column-end: span 6;" class="hint non-creeper" data-i18n="adversary-levels">Levels</h2>
<h2 style="grid-column-end: span 6;" class="hint non-creeper" data-i18n="adversary-actions">Actions</h2>
<div class="levels non-creeper">
<span data-i18n="min-level">Min Level:</span><input type="number" max="10" min="1" id="attr_min_level" name="attr_min_level" value="1" />
<span data-i18n="max-level">Max Level:</span><input type="number" max="10" min="1" id="attr_max_level" name="attr_max_level" value="10" />
</div>
<div class="levels non-creeper">
<span class="non-creeper" data-i18n="number">Number:</span>
<input class="non-creeper" type="number" id="attr_adversary_actions" name="attr_adversary_actions" max="10" min="1" value="1" />
</div>
<div class="separator non-creeper"></div>
<h2 style="grid-column-end: span 6;" class="hint non-creeper" data-i18n="wrangle-parley-disadvantage">Wrangle/Parley</h2>
<h2 style="grid-column-end: span 6;" class="hint creeper-swap" data-i18n="number-appearing">Number Appearing</h2>
<input class="non-creeper" type="radio" name="attr_adversary_disadvantage" value="false" checked /><span class="non-creeper" data-i18n="check_standard">Standard</span>
<input class="non-creeper" type="radio" name="attr_adversary_disadvantage" value="true" /><span class="non-creeper" data-i18n="check_disadvantage">Disadvantage</span>
<div class="non-creeper" style="grid-column-end: span 2;"></div>
<input type="checkbox" name="attr_keyword_solo" /><span data-i18n="solo">Solo</span>
<input type="checkbox" name="attr_keyword_group" /><span data-i18n="group">Group</span>
<input type="checkbox" name="attr_keyword_horde" /><span data-i18n="horde">Horde</span>
<div class="separator"></div>
<h2 style="grid-column-end: span 12;" class="hint" data-i18n="sizes">Sizes</h2>
<input type="checkbox" name="attr_keyword_tiny" /><span data-i18n="tiny">Tiny</span>
<input type="checkbox" name="attr_keyword_small" /><span data-i18n="small">Small</span>
<input type="checkbox" name="attr_keyword_medium" /><span data-i18n="medium">Medium</span>
<input type="checkbox" name="attr_keyword_folk" /><span data-i18n="folk">Folk</span>
<input type="checkbox" name="attr_keyword_large" /><span data-i18n="large">Large</span>
<input type="checkbox" name="attr_keyword_huge" /><span data-i18n="huge">Huge</span>
<div class="separator"></div>
<h2 style="grid-column-end: span 12;" class="hint" data-i18n="special">Special</h2>
<input type="checkbox" name="attr_keyword_minions" /><span data-i18n="minions">Minions</span>
<input type="checkbox" name="attr_keyword_aquatic" /><span data-i18n="aquatic">Aquatic</span>
<input type="checkbox" name="attr_keyword_flying" /><span data-i18n="flying">Flying</span>
<input type="checkbox" name="attr_keyword_fast" /><span data-i18n="fast">Fast</span>
<input type="checkbox" name="attr_keyword_undead" /><span data-i18n="undead">Undead</span>
<input type="checkbox" name="attr_keyword_dwimmercrafty" /><span data-i18n="dwimmercrafty">Dwimmercrafty</span>
</div>
<!--********* SHEET - ATTRIBUTES & ABILITIES **********-->
<div class="sheet-attributes">
<div class="attribute-box">
<div>
<button type="action" name="act_vim">
<h2 data-i18n="vim">Vim</h2>
</button>
<div class="dice-field"><input type="text" name="attr_vim" /></div>
</div>
<ul>
<li><input type="text" name="attr_charm" /></li>
<li><input type="text" name="attr_inspire" /></li>
<li><input type="text" name="attr_mettle" /></li>
<li><input type="text" name="attr_perception" /></li>
</ul>
<ul>
<li><button type="action" name="act_charm" data-i18n="charm">Charm</button></li>
<li><button type="action" name="act_inspire" data-i18n="inspire">Inspire</button></li>
<li><button type="action" name="act_mettle" data-i18n="mettle">Mettle</button></li>
<li><button type="action" name="act_perception" data-i18n="perception">Perception</button></li>
</ul>
</div>
<div class="stat-box stat-courage">
<h2 data-i18n="courage">Courage</h2>
<input type="number" name="attr_courage_max" class="big" />
<input type="number" name="attr_courage" class="small" />
<label data-i18n="current" class="small">Current</label>
</div>
<div class="corner-box-wrapper side" style="grid-row-end: span 3;">
<label class="corner-box-header" data-i18n="proficiencies">Proficiencies</label>
<div class="corner-box">
<div class=content><textarea name="attr_proficiencies" rows="3"></textarea></div>
</div>
<label class="corner-box-header" data-i18n="conditions">Conditions</label>
<div class="corner-box">
<div class=content><textarea name="attr_conditions" rows="3"></textarea></div>
</div>
</div>
<div class="corner-box-wrapper side" style="grid-row-end: span 3;">
<label class="corner-box-header" data-i18n="deficiencies">Deficiencies</label>
<div class="corner-box">
<div class=content><textarea name="attr_deficiencies" rows="3"></textarea></div>
</div>
<label class="corner-box-header" data-i18n="heroic-titles">Heroic Titles</label>
<div class="corner-box">
<div class=content><textarea name="attr_heroic_titles" rows="3"></textarea></div>
</div>
</div>
<div class="separator"></div>
<div></div>
<div class="attribute-box">
<div>
<button type="action" name="act_vigor">
<h2 data-i18n="vigor">Vigor</h2>
</button>
<div class="dice-field"><input type="text" name="attr_vigor" /></div>
</div>
<ul>
<li><input type="text" name="attr_athletics" /></li>
<li><input type="text" name="attr_intimidate" /></li>
<li><input type="text" name="attr_might" /></li>
<li><input type="text" name="attr_vitality" /></li>
</ul>
<ul>
<li><button type="action" name="act_athletics" data-i18n="athletics">Athletics</button></li>
<li><button type="action" name="act_intimidate" data-i18n="intimidate">Intimidate</button></li>
<li><button type="action" name="act_might" data-i18n="might">Might</button></li>
<li><button type="action" name="act_vitality" data-i18n="vitality">Vitality</button></li>
</ul>
</div>
<div class="stat-box stat-attack">
<button type="action" name="act_attack">
<h2 data-i18n="attack">Attack</h2>
</button>
<input type="text" name="attr_attack" class="big" />
<input type="text" name="attr_dread" class="small" />
<label data-i18n="dread" for="attr_dread" class="small">Dread</label>
<div style="display:block; width: 0; height: 0; overflow: visible;"><img style="opacity: 0.2; min-width: 97px ; min-height: 97px;" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/stats_2.png" /></div>
</div>
<div class="separator"></div>
<div></div>
<div style="grid-column-end: span 2; grid-row-end: span 5;" class="note-box">
<div class="repeating_skills_container">
<h2 data-i18n="abilities">Abilities</h2>
<fieldset class="repeating_skills">
<input type="hidden" class="skilledit" name="attr_skilledit" value="0" />
<input type="checkbox" name="attr_skilledit" />
<input type="text" name="attr_skillname" value="">
<button type="action" name="act_share" class="btn-share">
<div></div>
</button>
<div class="sheet-auto-expand">
<span name="attr_skilldescription"></span>
<textarea class="skill-description" name="attr_skilldescription" rows="4"></textarea>
</div>
</fieldset>
</div>
</div>
<div class="attribute-box">
<div>
<button type="action" name="act_knack">
<h2 data-i18n="knack">Knack</h2>
</button>
<div class="dice-field"><input type="text" name="attr_knack" /></div>
</div>
<ul>
<li><input type="text" name="attr_nimbleness" /></li>
<li><input type="text" name="attr_search" /></li>
<li><input type="text" name="attr_sneak" /></li>
<li><input type="text" name="attr_trickery" /></li>
</ul>
<ul>
<li><button type="action" name="act_nimbleness" data-i18n="nimbleness">Nimbleness</button></li>
<li><button type="action" name="act_search" data-i18n="search">Search</button></li>
<li><button type="action" name="act_sneak" data-i18n="sneak">Sneak</button></li>
<li><button type="action" name="act_trickery" data-i18n="trickery">Trickery</button></li>
</ul>
</div>
<div class="stat-box stat-defense">
<h2 data-i18n="defense">Defense</h2>
<input type="text" name="attr_defense" class="big" />
<input type="number" name="attr_block" class="small" />
<label data-i18n="block" for="attr_block" class="small">Block</label>
</div>
<div class="separator"></div>
<div></div>
<div class="attribute-box">
<div>
<button type="action" name="act_knowhow">
<h2 data-i18n="knowhow">Knowhow</h2>
</button>
<div class="dice-field"><input type="text" name="attr_knowhow" /></div>
</div>
<ul>
<li><input type="text" name="attr_lore" /></li>
<li><input type="text" name="attr_realms" /></li>
<li><input type="text" name="attr_tinker" /></li>
<li><input type="text" name="attr_wilderness" /></li>
</ul>
<ul>
<li><button type="action" name="act_lore" data-i18n="lore">Lore</button></li>
<li><button type="action" name="act_realms" data-i18n="realms">Realms</button></li>
<li><button type="action" name="act_tinker" data-i18n="tinker">Tinker</button></li>
<li><button type="action" name="act_wilderness" data-i18n="wilderness">Wilderness</button></li>
</ul>
</div>
<div class="stat-box stat-quest">
<h2 data-i18n="quest">Quest Pts.</h2>
<input type="number" name="attr_quest_pts" class="big" />
</div>
</div>
<!--********* SHEET - INVENTORY AND CRAFTING **********-->
<div class="sheet-inventory">
<div class="stripe upper">
<section>
<h2 class="inventory" data-i18n="inventory">Inventory</h2>
<h2 data-i18n="slots">Slots:</h2>
<input class="small" type="number" name="attr_inventory_slots" />
<h2 class="small">/</h2><input class="small" type="number" name="attr_inventory_slots_max" />
<div class="checkbox-group">
<input type="checkbox" name="attr_overburdened" />
<label data-i18n="overburdened" for="attr_overburdened">Overburdened</label>
<input type="checkbox" name="attr_tired" />
<label data-i18n="tired" for="attr_tired">Tired</label>
</div>
</section>
<section>
<div class="treasure"><input type="text" name="attr_treasure_hunting" /></div>
<button class="treasure" type="action" name="act_treasure_hunting">
<h2 class="treasure" data-i18n="treasure-hunting">Treasure Hunting:</h2>
</button>
</section>
</div>
<div class="inventory-upper">
<div class="note-box">
<div>
<h2 class="worn" data-i18n="worn">Worn</h2>
<textarea rows="6" name="attr_worn"></textarea>
<div class="watermark worn"><img class="worn" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/worn.png" />
</div>
</div>
</div>
<div class="vertical-line"></div>
<div class="note-box">
<div>
<h2 class="carried" data-i18n="carried">Carried</h2>
<textarea rows="6" name="attr_carried"></textarea>
<div class="watermark carried"><img class="carried" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/carried.png" />
</div>
</div>
</div>
</div>
<div class="stripe lower">
<section>
<img class="crafting" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/crafting.png" />
<h2 data-i18n="crafting">Crafting</h2>
<div class="corner-box-wrapper">
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content two-columns"><label data-i18n="num-materials">No. of
materials</label><input type="number" name="attr_material_number" /></div>
</div>
</div>
</div>
</section>
<section>
<img class="coins" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/coins.png" />
<h2 data-i18n="coins">Coins</h2>
<section class="hint" data-i18n="tradeup">3:1 tradeup</section>
</section>
<section>
<img class="rations" src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/rations.png" />
<h2 data-i18n="rations">Rations</h2>
</section>
</div>
<div class="inventory-lower">
<div class="note-box">
<div>
<div class="crafting fake-textarea">
<textarea rows="2" name="attr_material_elemental"></textarea>
<textarea rows="2" name="attr_material_fish"></textarea>
<textarea rows="2" name="attr_material_beast"></textarea>
<textarea rows="2" name="attr_material_herb"></textarea>
</div>
<div class="crafting-icons">
<img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/material_elemental.png" />
<img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/material_fish.png" />
<img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/material_beast.png" />
<img src="https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/LandOfEem/images/material_herb.png" />
</div>
</div>
</div>
<div class="vertical-line"></div>
<div class="note-box">
<div>
<div class="coins fake-textarea">
<section class="small" data-i18n="copper">Copper</section>
<section class="hint">d6</section><input type="number" name="attr_coins_copper" />
<section class="small" data-i18n="silver">Silver</section>
<section class="hint">d8</section><input type="number" name="attr_coins_silver" />
<section class="small" data-i18n="gold">Gold</section>
<section class="hint">d10</section><input type="number" name="attr_coins_gold" />
<section class="small" data-i18n="ancient">Ancient</section>
<section class="hint">d12</section><input type="number" name="attr_coins_ancient" />
</div>
</div>
</div>
<div class="vertical-line"></div>
<div class="note-box">
<div>
<div class="rations fake-textarea">
<section class="hint">d6</section><input type="number" name="attr_rations_d6" />
<section class="hint">d8</section><input type="number" name="attr_rations_d8" />
<section class="hint">d10</section><input type="number" name="attr_rations_d10" />
</div>
</div>
</div>
</div>
</div>
<!--********* SHEET - BACKGROUND AND NOTES **********-->
<div class="sheet-background">
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content">
<label class="hint" data-i18n="ideals">Ideals</label>
<section class="sparkle"></section>
<section data-i18n="ideals-hint" class="hint">Gain individual XP if you demonstrate your ideals</section>
<textarea rows="3" name="attr_ideals"></textarea>
</div>
</div>
</div>
<div class="corner-box-wrapper">
<div class="corner-box">
<div class="content">
<label class="hint" data-i18n="flaws">Flaws</label>
<section class="sparkle"></section>
<section data-i18n="flaws-hint" class="hint">Gain individual XP if you demonstrate your flaws</section>
<textarea rows="3" name="attr_flaws"></textarea>
</div>
</div>
</div>
<div style="grid-column-end: span 2;"></div>
<div class="note-box">
<div>
<h2 data-i18n="personal-quest" class="hint">Personal Quest</h2>
<section class="sparkle"></section>
<section data-i18n="personal-quest-hint" class="hint">Gain party XP if you pursue your personal quest</section>
<textarea rows="5" name="attr_personal_quest"></textarea>
</div>
</div>
<div class="note-box" style="grid-row-end: span 3;">
<div>
<h2 data-i18n="backstory" class="hint">Backstory</h2>
<section class="sparkle"></section>
<section data-i18n="backstory-hint" class="hint">Gain individual XP if you tell a story about your past</section>
<textarea rows="13" name="attr_backstory"></textarea>
</div>
</div>
<div></div>
<div class="note-box">
<div>
<h2 data-i18n="relationships" class="hint">Relationships</h2>
<section class="sparkle"></section>
<section data-i18n="relationships-hint" class="hint">Gain party XP if you build on a relationship</section>
<textarea rows="6" name="attr_relationships"></textarea>
</div>
</div>
</div>
<!--********* NOTES **********-->
<div class="sheet-notes">
<div class="note-box">
<div>
<h2 data-i18n="other-notes" class="hint">Notes</h2>
<textarea rows="18" name="attr_other_notes"></textarea>
</div>
</div>
</div>
<!--********* PORTRAIT **********-->
<div class="sheet-portrait">
<div></div>
<img name="attr_character_avatar">
<div></div>
</div>
<!--********* SETTINGS **********-->
<div class="sheet-settings">
<div class="settings-dropdown">
<label for="attr_sheet_type" data-i18n="sheet-type">Sheet Type:</label>
<select name="attr_sheet_type" id="attr_sheet_type" value="pc">
<option type="action" value="pc" data-i18n="pc">PC</option>
<option type="action" value="npc" data-i18n="npc">NPC</option>
<option type="action" value="adversary" data-i18n="adversary">Adversary</option>
</select>
<section class="sparkle"> </section> <span class="hint" data-i18n="hint-sheet-type">Changes the sheet type.
</span>
</div>
<div class="separator"></div>
<div class="settings-radio">
<label data-i18n="clamp-modifiers">Clamp Attribute/Skills:</label>
<input type="radio" name="attr_clamp_modifiers" value="true" checked /><span data-i18n="on">On</span>
<input type="radio" name="attr_clamp_modifiers" value="false" /><span data-i18n="off">Off</span>
<section class="sparkle"> </section> <span class="hint" data-i18n="hint-clamp-modifiers">On: keeps Attribute and Skill values between -3 and +3.</span>
</div>
<div class="separator"></div>
<div class="settings-radio">
<label data-i18n="clamp-roll-modifier">Clamp Final Roll Modifier:</label>
<input type="radio" name="attr_clamp_roll_modifier" value="true" checked /><span data-i18n="on">On</span>
<input type="radio" name="attr_clamp_roll_modifier" value="false" /><span data-i18n="off">Off</span>
<section class="sparkle"> </section> <span class="hint" data-i18n="hint-clamp-roll-modifier">On: keeps the final sum of roll modifiers between -3 and +3.</span>
</div>
<div class="separator"></div>
</div>
</div>
<!--********* FOOTER **********-->
<div class="footer">
<span>Character Sheet (v.<span name="attr_version"></span>) by </span><a href="https://ko-fi.com/blazesanecki/">Blaze Sanecki</a>, made with a blessing from <span>by Ben Costa & James Parks</span> - creators of the <a href="https://landofeem.com/"><b>Land of Eem</b></a>.
</div>
</div>
<!--********* HIDDEN ATTRIBUTES **********-->
<input type="hidden" name="attr_version" value="2.1.0" />
<!--********* ROLL TEMPLATES **********-->
<rolltemplate class="sheet-rolltemplate-attack">
<div class="template-container {{sheet_type}}">
<h2><span data-i18n="{{name}}">Name</span><i> ({{character}})</i></h2>
<div class="results attack">
<ul>
<li>
{{#rollGreater() computed::roll 11}}
<span class="critical-hit">
{{/rollGreater() computed::roll 11}}
<h3><span data-i18n="attack">Attack</span>: {{computed::roll}} &nbsp;&nbsp;&nbsp; <span data-i18n="damage">Damage</span>:&nbsp;{{computed::damage}}</h3>
{{#rollGreater() computed::roll 11}}
</span>
{{/rollGreater() computed::roll 11}}
</li>
{{#rollTotal() computed::roll roll}}
<div style="display:none">
{{/rollTotal() computed::roll roll}}
<li>
<h5 data-i18n="modifier-clamped">Modifier clamped to [-3..3] range.</h5>
</li>
{{#rollTotal() computed::roll roll}}
</div>
{{/rollTotal() computed::roll roll}}
{{#rollLess() computed::roll 3}}
<li>
<h4><b>[1-2]: </b></span> <span data-i18n="critical-miss">Critical Miss.</span></h4>
</li>
<li>
<h4><b><span data-i18n="fumble-example">Fumble Example</span>: </b><span data-i18n="fumble_example_{{random_index}}">EXAMPLE</span></h4>
</li>
{{/rollLess() computed::roll 3}}
{{#rollBetween() computed::roll 3 5}}
<li>
<h4><b>[3-5]: </b></span><span data-i18n="miss-with-a-plus">Miss with a Plus.</span></h4>
</li>
<li>
<h4><b><span data-i18n="plus-example">Plus Example</span>: </b><span data-i18n="plus_example_{{random_index}}">EXAMPLE</span></h4>
</li>
{{/rollBetween() computed::roll 3 5}}
{{#rollBetween() computed::roll 6 8}}
<li>
<h4><b>[6-8] (<span data-i18n="melee">Melee</span>): </b></span><span data-i18n="hit-with-a-counterattack">Hit with a Counterattack.</span></h4>
<h4><b>[6-8] (<span data-i18n="ranged">Ranged</span>): </b></span><span data-i18n="grazing-shot">Grazing Shot.</span></h4>
</li>
{{/rollBetween() computed::roll 6 8}}
{{#rollBetween() computed::roll 9 11}}
<li>
<h4><b>[9-11]: </b></span><span data-i18n="hit">Hit.</span></h4>
</li>
{{/rollBetween() computed::roll 9 11}}
{{#rollGreater() computed::roll 11}}
<li>
<h4><b>[12+]: </b></span><span data-i18n="critical-hit">Critical Hit.</span></h4>
</li>
{{/rollGreater() computed::roll 11}}
</ul>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-check">
<div class="template-container {{sheet_type}}">
<h2><span data-i18n="{{name}}">Name</span><i> ({{character}})</i></h2>
<div class="results check">
<ul>
<li>
{{#rollGreater() computed::roll 11}}
<span class="critical-hit">
{{/rollGreater() computed::roll 11}}
<h3><span data-i18n="result">Result</span>:&nbsp;{{computed::roll}}</h3>
{{#rollGreater() computed::roll 11}}
</span>
{{/rollGreater() computed::roll 11}}
</li>
{{#rollTotal() computed::roll roll}}
<div style="display:none">
{{/rollTotal() computed::roll roll}}
<li>
<h5><span data-i18n="modifier-clamped">Modifier clamped to [-3..3] range.</span></h5>
</li>
{{#rollTotal() computed::roll roll}}
</div>
{{/rollTotal() computed::roll roll}}
{{#rollLess() computed::roll 3}}
<li>
<h4><b>[1-2]: </b></span> <span data-i18n="complete-failure">Complete Failure.</span></h4>
</li>
{{/rollLess() computed::roll 3}}
{{#rollBetween() computed::roll 3 5}}
<li>
<h4><b>[3-5]: </b></span><span data-i18n="failure-with-a-plus">Failure with a Plus.</span></h4>
</li>
{{/rollBetween() computed::roll 3 5}}
{{#rollBetween() computed::roll 6 8}}
<li>
<h4><b>[6-8]: </b></span><span data-i18n="success-with-a-twist">Success with a Twist.</span></h4>
</li>
{{/rollBetween() computed::roll 6 8}}
{{#rollBetween() computed::roll 9 11}}
<li>
<h4><b>[9-11]: </b></span><span data-i18n="success">Success.</span></h4>
</li>
{{/rollBetween() computed::roll 9 11}}
{{#rollGreater() computed::roll 11}}
<li>
<h4><b>[12+]: </b></span><span data-i18n="complete-success">Complete Success.</span></h4>
</li>
{{/rollGreater() computed::roll 11}}
</ul>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-description">
<div class="template-container {{sheet_type}}">
<h2><span>{{name}}</span><i> ({{character}})</i></h2>
<div class="results check">
<ul>
<li>
<h4>{{description}}</h4>
</li>
</ul>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-hidden">
<div class="sheet-template-container" style="display: none;"></div>
</rolltemplate>
<!--********* SCRIPTS **********-->
<script type="text/worker">
//********* TAB BUTTONS **********/
const buttonlist = ["npc","adversary-definition","adversary-preview", "attributes", "inventory", "background", "notes", "portrait", "settings"]
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
sheetTab: button
})
})
})
//********* SKILL SHARE **********/
on("clicked:repeating_skills:share", function(eventinfo) {
const rowId = eventinfo.sourceAttribute.split("_")[2]
getAttrs([`repeating_skills_${rowId}_skillname`, `repeating_skills_${rowId}_skilldescription`, "character_name"], async (values) => {
const skillName = values[`repeating_skills_${rowId}_skillname`] || "Unnamed Skill"
const skillDescription = values[`repeating_skills_${rowId}_skilldescription`] || "No description."
const characterName = values["character_name"] || "Unknown Character"
const roll = await startRoll(`&{template:description} {{sheet_type=@{sheet_type}}} {{name=${skillName}}} {{character=${characterName}}} {{description=${skillDescription}}} {{ignore=[[0]]}}`);
finishRoll(roll.rollId);
})
})
//********* DEFINE SIGNED AND UNSIGNED ATTRIBUTES **********/
const signed = ["attack", "defense", "vim", "charm", "inspire", "mettle", "perception", "vigor", "athletics", "intimidate", "might", "vitality", "knack", "nimbleness", "search", "sneak", "trickery", "knowhow", "lore", "realms", "tinker", "wilderness", "treasure_hunting"];
const unsigned = ["courage", "courage_max", "quest_pts", "block", "inventory_slots", "inventory_slots_max", "material_number", "coins_copper", "coins_silver", "coins_gold", "coins_ancient", "rations_d6", "rations_d8", "rations_d10", "lv", "xp"];
const regular = ["vim", "charm", "inspire", "mettle", "perception", "vigor", "athletics", "intimidate", "might", "vitality", "knack", "nimbleness", "search", "sneak", "trickery", "knowhow", "lore", "realms", "tinker", "wilderness", "treasure_hunting"];
const keywords = ["keyword_tiny", "keyword_small", "keyword_medium", "keyword_large", "keyword_huge", "keyword_folk", "keyword_solo", "keyword_group", "keyword_horde", "keyword_minions", "keyword_aquatic", "keyword_flying", "keyword_fast", "keyword_undead", "keyword_dwimmercrafty"];
const keywordsSize = ["tiny", "small", "medium", "large", "huge", "folk"]
const keywordClasses = ["goon", "bruiser", "champion"]
const keywordNumbers = ["solo", "group", "horde"]
const keywordSpecial = ["minions", "aquatic", "flying", "fast", "undead", "dwimmercrafty"]
const courageBruiser = [4, 7, 11, 14, 18, 21, 25, 28, 32, 35]
const courageChampion = [7, 13, 20, 26, 33, 39, 46, 52, 59, 65]
//********* DEFINE CUSTOM FUNCTIONS **********/
const updateStats = (statNames, difference) => {
const result = {}
getAttrs(statNames.concat("clamp_modifiers"), (vals) => {
statNames.forEach(stat => {
let statVal = parseInt(vals[stat]) + difference
const clamp = vals["clamp_modifiers"] === "true"
if(clamp) statVal = (statVal >= 3 ? 3 : (statVal <= -3 ? -3 : statVal))
result[stat] = statVal>=0 ? "+" + statVal : statVal
setAttrs({
[stat]: result[stat]
})
})
})
return result
}
const getCourage = (classType, level, size) => {
let result = level
if(classType === "bruiser") {
result = courageBruiser[level - 1] || 4
}
else if(classType === "champion") {
result = courageChampion[level - 1] || 7
}
if(size === "large")
{
result += level
}
else if(size === "huge")
{
result += 2*level
}
return result
}
//********* HANDLE LVL AND CLASS CHANGE FOR ADVERSARIES **********/
on("change:adversary_level change:adversary_class", (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
getAttrs(["adversary_level", "adversary_class"], (values) => {
let selected_level = parseInt(values["adversary_level"])
if(isNaN(selected_level) || selected_level < 1) {
selected_level = 1
}
else if(selected_level > 10) {
selected_level = 10
}
let selected_class = values["adversary_class"] || "goon"
//TODO: update courage etc.
})
})
//********* VALIDATE MIN MAX LEVEL **********/
on("change:min_level change:max_level", (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
getAttrs(["min_level", "max_level"], (values) => {
let min = parseInt(values["min_level"])
if(isNaN(min) || min < 1) {
min = 1
}
else if(min > 10) {
min = 10
}
let max = parseInt(values["max_level"])
if(isNaN(max) || max < 1) {
max = 1
}
else if(max > 10) {
max = 10
}
if(min>max) {
// Swap values
const temp = min
min = max
max = temp
}
setAttrs({
min_level: min,
max_level: max
})
})
})
//********* VALIDATE WRANGLE PARLEY **********/
on("change:wrangle_parley change:wrangle_parley_max", (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
getAttrs(["wrangle_parley", "wrangle_parley_max"], (values) => {
let wp = parseInt(values["wrangle_parley"])
let wp_max = parseInt(values["wrangle_parley_max"])
if(isNaN(wp)) {
wp = 1
}
if(isNaN(wp_max)) {
wp_max = 1
}
if(wp > 2) {
wp = 2
}
else if(wp<0){
wp = 0
}
if(wp_max > 2) {
wp_max = 2
}
else if(wp_max<0){
wp_max = 0
}
if(wp > wp_max) {
wp = wp_max
}
setAttrs({
wrangle_parley: wp,
wrangle_parley_max: wp_max
})
})
})
on("change:adversary_level change:adversary_class change:adversary_size", (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
getAttrs(["adversary_level", "adversary_class", "adversary_size"], (values) => {
let selected_level = parseInt(values["adversary_level"])
if(isNaN(selected_level) || selected_level < 1) {
selected_level = 1
}
else if(selected_level > 10) {
selected_level = 10
}
let selected_class = values["adversary_class"] || "goon"
let selected_size = values["adversary_size"] || "medium"
let c = getCourage(selected_class, selected_level, selected_size)
let m = "-2"
if(selected_class === "bruiser") {
m = "+0"
}
else if(selected_class === "champion") {
m = "+2"
}
let a = ""
a += getTranslationByKey("level_short")
a += selected_level
a += "-"
a += getTranslationByKey(selected_class+"_short")
setAttrs({
courage_max: c,
courage: c,
mettle: m,
abbreviation: a
})
})
})
//********* UPDATE KEYWORD STRING ON CHANGE **********/
on(keywordClasses.map(field => "change:keyword_" + field).join(" "), (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
// Rebuild the keyword string
getAttrs(keywordClasses.map(field => "keyword_" + field), (values) => {
let classesString = ""
keywordClasses.forEach(s => {
if(values["keyword_" + s] === "on") {
if(classesString !== "") {
classesString += ", "
}
classesString += getTranslationByKey(s+"_short")
}
})
if(classesString == "") {
classesString = "-"
}
setAttrs({
classes: classesString,
})
})
})
on(keywords.map(field => "change:" + field).join(" "), (eventinfo) => {
// Ignore sheetworker events
if(eventinfo.sourceType === "sheetworker") {
return
}
// Fix incompatible keyword selections
if(eventinfo.sourceAttribute==='keyword_folk' && eventinfo.newValue==='on') {
// Automatically uncheck overlaping keywords
setAttrs({
keyword_small: "false",
keyword_medium: "false",
})
}
else if((eventinfo.sourceAttribute==='keyword_small' || eventinfo.sourceAttribute==='keyword_medium') && eventinfo.newValue==='on') {
setAttrs({
keyword_folk: "false",
})
}
// Rebuild the keyword string
getAttrs(keywords, (values) => {
let keywordString = ""
let sizeString = ""
let numberString = ""
let specialString = ""
keywordsSize.forEach(s => {
if(values["keyword_" + s] === "on") {
if(sizeString !== "") {
sizeString += "/"
}
sizeString += getTranslationByKey(s)
}
})
keywordNumbers.forEach(s => {
if(values["keyword_" + s] === "on") {
if(numberString !== "") {
numberString += "/"
}
numberString += getTranslationByKey(s)
}
})
keywordSpecial.forEach(s => {
if(values["keyword_" + s] === "on") {
if(specialString !== "") {
specialString += "/"
}
specialString += getTranslationByKey(s)
}
})
if(sizeString !== "") {
keywordString += sizeString
}
if(numberString !== "") {
if(keywordString !== "") {
keywordString += ", "
}
keywordString += numberString
}
if(specialString !== "") {
if(keywordString !== "") {
keywordString += ", "
}
keywordString += specialString
}
if(keywordString === "") {
keywordString = "-"
}
setAttrs({
keywords: keywordString,
})
})
})
//********* VALIDATE SIGNED NUMBER VALUES ON CHANGE **********/
on(signed.map(field => "change:" + field).join(" "), (eventinfo) => {
const fieldName = eventinfo.sourceAttribute
getAttrs([fieldName, "clamp_modifiers"], (values) => {
//********* IGNORE SHEETWORKER EVENTS **********/
if(eventinfo.sourceType === "sheetworker") {
return
}
const clamp = values["clamp_modifiers"] === "true"
//********* CLAMP TO -3 +3 AND SET THE VALUE **********/
let oldValue = parseInt(eventinfo.previousValue)||0
let val = parseInt(values[fieldName])
if(isNaN(val)) {
val = "+0"
}
else if(clamp && val < -3) {
val = "-3"
}
else if(clamp && val > 3) {
val = "+3"
}
else if(val >= 0) {
val = "+" + val
}
setAttrs({
[fieldName]: val
})
const difference = (parseInt(val) - oldValue)
//********* SYNC ABILITIES AND STATS WITH THEIR ATTRIBUTES **********/
if(fieldName === "vim"){
updateStats(["charm", "inspire", "mettle", "perception"], difference)
getAttrs(["courage", "courage_max"], (vals) => {
setAttrs({
courage_max: parseInt(vals["courage_max"]) + difference,
courage: parseInt(vals["courage"]) + difference
})
})
}
else if(fieldName === "vigor"){
const newVals = updateStats(["athletics", "intimidate", "might", "vitality"], difference)
getAttrs(["might", "vitality"], (vals) => {
setAttrs({
attack: val,
inventory_slots_max: 20 + parseInt(newVals["might"])+parseInt(newVals["vitality"])
})
})
}
else if(fieldName === "knack"){
updateStats(["nimbleness", "search", "sneak", "trickery"], difference)
setAttrs({
defense: parseInt(val)>0 ? -parseInt(val) : "+" +(-parseInt(val)),
})
}
else if(fieldName === "knowhow"){
updateStats(["lore", "realms", "tinker", "wilderness"], difference)
setAttrs({
quest_pts: parseInt(val)+3
})
}
else if(fieldName === "might"){
getAttrs(["vitality"], (vals) => {
setAttrs({
inventory_slots_max: 20 + parseInt(val)+parseInt(vals["vitality"])
})
})
}
else if(fieldName === "vitality"){
getAttrs(["might"], (vals) => {
setAttrs({
inventory_slots_max: 20 + parseInt(val)+parseInt(vals["might"])
})
})
}
})
})
//********* VALIDATE UNSIGNED NUMBER VALUES ON CHANGE (FOR FIREFOX BROWSER) **********/
on(unsigned.map(field => "change:" + field).join(" "), (eventinfo) => {
const fieldName = eventinfo.sourceAttribute
getAttrs([fieldName], (values) => {
let val = parseInt(values[fieldName])
if(isNaN(val)) {
setAttrs({
[fieldName]: 0
})
}
})
})
//********* VALIDATE ALL NUMBER VALUES ON CHARACTER SHEET OPEN **********/
on("sheet:opened", (eventinfo) => {
signed.forEach((fieldName) => {
getAttrs([fieldName, "clamp_modifiers"], (values) => {
let val = parseInt(values[fieldName])
const clamp = values["clamp_modifiers"] === "true"
if(isNaN(val)) {
setAttrs({
[fieldName]: "+0"
})
}
else if(clamp && val < -3) {
setAttrs({
[fieldName]: "-3"
})
}
else if(clamp && val > 3) {
setAttrs({
[fieldName]: "+3"
})
}
else if(val >= 0) {
setAttrs({
[fieldName]: "+" + val
})
}
else {
setAttrs({
[fieldName]: val
})
}
})
})
unsigned.forEach((fieldName) => {
getAttrs([fieldName], (values) => {
if(values[fieldName] === "") {
if(fieldName === "inventory_slots_max") {
setAttrs({
[fieldName]: 20
})
}
else if (fieldName === "courage_max" || fieldName === "courage") {
setAttrs({
[fieldName]: 12
})
}
else if (fieldName === "quest_pts") {
setAttrs({
[fieldName]: 3
})
}
else {
setAttrs({
[fieldName]: 0
})
}
}
})
})
//********* SET DEFAULT VALUE FOR DREAD AND SHEET TYPE **********/
getAttrs(["dread","sheet_type"], (values) => {
let val = values["dread"]
if(val === undefined || val === "") {
setAttrs({
dread: "1d4"
})
}
val = values["sheet_type"]
if(val === undefined || val === "") {
setAttrs({
sheet_type: "pc"
})
}
})
//********* FIX OLD ABILITIES FIELD **********/
getAttrs(["abilities"], (values) => {
let val = values["abilities"]
if(val !== undefined && val !== "") {
let attrs = {}
let newid = generateRowID()
var skillid = "repeating_skills_" + newid
attrs[skillid+"_skilledit"] = "false"
attrs[skillid+"_skillname"] = getTranslationByKey('backup_ability')
attrs[skillid+"_skilldescription"] = val
attrs["abilities"]=""
setAttrs(attrs)
}
})
})
//********* CLASS CHANGE HANDLER **********/
on("change:class", (eventinfo) => {
let key = eventinfo.newValue
if(key === getTranslationByKey('bard')) {
key = "bard";
}
else if(key === getTranslationByKey('dungeoneer')) {
key = "dungeoneer";
}
else if(key === getTranslationByKey('gnome')) {
key = "gnome";
}
else if(key === getTranslationByKey('knight-errant')) {
key = "knight-errant";
}
else if(key === getTranslationByKey('loyal-chum')) {
key = "loyal-chum";
}
else if(key === getTranslationByKey('rascal')) {
key = "rascal";
}
getAttrs(["hidden_class", "vim"], (values) => {
// Same class - no change needed
if(values["hidden_class"] === key) return
const v = parseInt(values["vim"])
let dread = "1d4"
let courage_max = 12+v
if(key === "bard") {dread = "1d4"; courage_max = v+12; }
else if(key === "dungeoneer") { dread = "1d6"; courage_max = v+13; }
else if(key === "gnome") { dread = "1d8"; courage_max = v+14; }
else if(key === "knight-errant") { dread = "1d10"; courage_max = v+15; }
else if(key === "loyal-chum") { dread = "1d6"; courage_max = v+13; }
else if(key === "rascal") { dread = "1d8"; courage_max = v+14; }
else return
setAttrs({
dread: dread,
courage_max: courage_max,
courage: courage_max,
hidden_class: key
})
})
})
//********* SET ROLL EVENT LISTENERS *********/
// Helper function to grab player input
const getRegularQuery = async (v) => {
const strCheckType = getTranslationByKey('check_type')
const strCheckStandard = getTranslationByKey('check_standard')
const strCheckAdvantage = getTranslationByKey('check_advantage')
const strCheckDisadvantage = getTranslationByKey('check_disadvantage')
const strModifier = getTranslationByKey('modifier')
let rollBase = `! {{query1=[[?{${strCheckType}|${strCheckStandard},1d12|${strCheckAdvantage},2d12kh1|${strCheckDisadvantage},2d12kl1};?{${strModifier}|${v}}]]}}`;
queryRoll = await startRoll(rollBase);
finishRoll(queryRoll.rollId); // you can just let this time out if you want - we're done with it
let queryResponse = queryRoll.results.query1.expression.split(";");
let tmp = parseInt(queryResponse[1]);
queryResponse[1] = tmp>=0 ? "+" + tmp : tmp;
return queryResponse;
};
regular.forEach((s) => {
on(`clicked:${s}`, async () => {
getAttrs([s, "clamp_roll_modifier"], async (values) => {
let v = parseInt(values[s])
const clamp = values["clamp_roll_modifier"] === "true"
if(v >= 0) v = "+" + v
const rollQuery = await getRegularQuery(0)
const rollStr = rollQuery[0] + v + rollQuery[1]
startRoll(`&{template:check} {{sheet_type=@{sheet_type}}} {{character=@{character_name}}} {{name=${s}}} {{roll=[[${rollStr}]]}}`, (checkResult) => {
let modifier = checkResult.results.roll.dice[0]
let expression = checkResult.results.roll.expression
if(expression.startsWith("2d12kl1")){
if(modifier > checkResult.results.roll.dice[1]) modifier = checkResult.results.roll.dice[1]
}
else if (expression.startsWith("2d12kh1")){
if(modifier < checkResult.results.roll.dice[1]) modifier = checkResult.results.roll.dice[1]
}
modifier = checkResult.results.roll.result - modifier
let computedResult = checkResult.results.roll.result
if(clamp && modifier > 3)
computedResult = computedResult - modifier + 3
else if(clamp && modifier < -3)
computedResult = computedResult - modifier - 3
finishRoll(checkResult.rollId, {
roll: computedResult
})
})
})
})
})
//********* ATTACK **********/
// Helper function to grab player input
const getAttackQuery = async (v, lastDefense) => {
const strCheckType = getTranslationByKey('check_type')
const strCheckStandard = getTranslationByKey('check_standard')
const strCheckAdvantage = getTranslationByKey('check_advantage')
const strCheckDisadvantage = getTranslationByKey('check_disadvantage')
const strModifier = getTranslationByKey('modifier')
const strDefense = getTranslationByKey("opponents-defense")
let rollBase = `! {{query1=[[?{${strCheckType}|${strCheckStandard},1d12|${strCheckAdvantage},2d12kh1|${strCheckDisadvantage},2d12kl1};?{${strModifier}|${v}};?{${strDefense}|${lastDefense}}]]}}`;
queryRoll = await startRoll(rollBase);
finishRoll(queryRoll.rollId); // you can just let this time out if you want - we're done with it
let queryResponse = queryRoll.results.query1.expression.split(";");
let tmp = parseInt(queryResponse[1]);
queryResponse[1] = tmp>=0 ? "+" + tmp : tmp;
tmp = parseInt(queryResponse[2]);
queryResponse[2] = tmp>=0 ? "+" + tmp : tmp;
return queryResponse;
};
on("clicked:attack", async () => {
getAttrs(["attack", "last_opponent_defense", "clamp_roll_modifier"], async values => {
let v = parseInt(values["attack"])
const clamp = values["clamp_roll_modifier"] === "true"
if(v >= 0) v = "+" + v
let lastDefense = values["last_opponent_defense"] || "+0"
const rollQuery = await getAttackQuery(0, lastDefense)
const rollStr = rollQuery[0] + v + rollQuery[1] + rollQuery[2]
setAttrs({
last_opponent_defense: rollQuery[2]
})
startRoll(`&{template:attack} {{sheet_type=@{sheet_type}}} {{character=@{character_name}}} {{random_index=[[[{1d6}]]]}} {{name=attack}} {{damage=[[@{dread}]]}} {{roll=[[${rollStr}]]}} {{hint=[[0]]}}`, (checkResult) => {
let modifier = checkResult.results.roll.dice[0]
let expression = checkResult.results.roll.expression
let expressionParts = expression.split(/([+-])/)
if(expression.startsWith("2d12kl1")){
if(modifier > checkResult.results.roll.dice[1]) modifier = checkResult.results.roll.dice[1]
}
else if (expression.startsWith("2d12kh1")){
if(modifier < checkResult.results.roll.dice[1]) modifier = checkResult.results.roll.dice[1]
}
modifier = checkResult.results.roll.result - modifier
let computedResult = checkResult.results.roll.result
if(clamp && modifier > 3)
computedResult = computedResult - modifier + 3
else if(clamp && modifier < -3)
computedResult = computedResult - modifier - 3
let computedDamage = checkResult.results.damage.result
if(computedResult > 11) {
computedDamage *= 2
}
finishRoll(checkResult.rollId, {
roll: computedResult,
damage: computedDamage
})
})
})
})
</script>