Browse Source

Roll20 charsheet, total encumbrance, some tooltips

master
Brandon Cornejo 1 year ago
parent
commit
60c6f72880
  1. 58
      roll20/char_sheet.css
  2. 171
      roll20/char_sheet.html
  3. 12
      roll20/hit_dice.js
  4. 18
      roll20/npc_party_import.js

58
roll20/char_sheet.css

@ -98,6 +98,13 @@ div.sheet-attacks-grid {
column-gap: 10px;
margin-bottom: 5px;
}
div.sheet-hitdie-grid {
display: grid;
grid-template-columns: 1fr 50px 80px 50px;
row-gap: 5px;
column-gap: 10px;
margin-bottom: 5px;
}
div.sheet-proficiencies-grid {
display: grid;
grid-template-columns: 1fr 50px 50px;
@ -300,26 +307,38 @@ div.sheet-npc-rsection, div.sheet-npc-lsection {
.sheet-spells-grid-daily > input {
text-align: center;
}
.sheet-total-encumb-display {
text-align: center;
grid-column: 1 / span 2;
margin-bottom: 15px;
}
/** Roll Templates **/
.sheet-rolltemplate-acks {}
.sheet-rolltemplate-acks div.sheet-acks-container {
border: 2px solid black;
border: 2px solid #333;
border-radius: 3px;
margin-bottom: 5px;
margin-right: 5px;
box-shadow: 5px 5px 5px 0px #9B9DA3;
}
.sheet-rolltemplate-acks div.sheet-acks-header {
background-color: rgba(112, 32, 130, 1);
border-bottom: 1px solid black;
padding: 5px;
line-height: 1.6em;
background-color: rgb(123, 62, 136);
border-bottom: 1px solid #333;
padding: 4px;
line-height: 1.4em;
font-size: 1.2em;
font-weight: bold;
color: #FFF;
color: #F2EBEB;
text-align: center;
}
.sheet-rolltemplate-acks div.sheet-acks-charname {
background-color: rgb(123, 62, 136);
padding-top: 5px;
line-height: 1.0em;
font-size: 0.85em;
color: #F2EBEB;
text-align: center;
}
.sheet-rolltemplate-acks div.sheet-acks-subheader {
@ -329,10 +348,11 @@ div.sheet-npc-rsection, div.sheet-npc-lsection {
font-size: 1.1em;
}
.sheet-rolltemplate-acks div.sheet-acks-row {
/*border-bottom: 1px solid black;*/
padding: 10px;
line-height: 1.0em;
font-size: 0.8em;
}
.sheet-rolltemplate-acks div.sheet-acks-row .inlinerollresult {
.sheet-rolltemplate-acks div.sheet-acks-row:not(.sheet-acks-desc) .inlinerollresult {
float: right;
}
.sheet-rolltemplate-acks div.sheet-acks-row .sheet-acks-target-value {
@ -347,8 +367,9 @@ div.sheet-npc-rsection, div.sheet-npc-lsection {
.sheet-rolltemplate-acks div.sheet-acks-row:nth-child(even) {
background-color: rgba(233, 233, 233, 1);
}
.sheet-rolltemplate-acks div.sheet-ask-desc {
font-size: 0.7em;
.sheet-rolltemplate-acks div.sheet-acks-desc {
font-size: 0.8em;
line-height: 1.5em;
color: rgb(115, 115, 115);
}
@ -364,3 +385,14 @@ textarea.sheet-txtarea {
padding: 0;
text-align: left;
}
input.sheet-hd-checkbox {
-webkit-appearance: none;
-moz-appearance: none;
border: 1px solid #888;
width: 10px;
height: 10px;
overflow: hidden;
}
input.sheet-hd-checkbox:checked {
background-color: #aaa;
}

171
roll20/char_sheet.html

@ -46,37 +46,37 @@
<input class="sheet-stat-input" type="text" name="attr_str" value="10">
<span class="sheet-stat-span">Str</span>
<input class="sheet-stat-input" type="text" name="attr_str_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Strength Throw}} {{roll=[[1d20 + @{str_mod}]]}}' name='roll_StrengthCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Strength Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{str_mod}]]}}' name='roll_StrengthCheck'></button>
<!-- Intelligence -->
<input class="sheet-stat-input" type="text" name="attr_int" value="10">
<span class="sheet-stat-span">Int</span>
<input class="sheet-stat-input" type="text" name="attr_int_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Intelligence Throw}} {{roll=[[1d20 + @{int_mod}]]}}' name='roll_IntelligenceCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Intelligence Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{int_mod}]]}}' name='roll_IntelligenceCheck'></button>
<!-- Wisdom -->
<input class="sheet-stat-input" type="text" name="attr_wis" value="10">
<span class="sheet-stat-span">Wis</span>
<input class="sheet-stat-input" type="text" name="attr_wis_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Wisdom Throw}} {{roll=[[1d20 + @{wis_mod}]]}}' name='roll_WisdomCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Wisdom Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{wis_mod}]]}}' name='roll_WisdomCheck'></button>
<!-- Dexterity -->
<input class="sheet-stat-input" type="text" name="attr_dex" value="10">
<span class="sheet-stat-span">Dex</span>
<input class="sheet-stat-input" type="text" name="attr_dex_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Dexterity Throw}} {{roll=[[1d20 + @{dex_mod}]]}}' name='roll_DexterityCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Dexterity Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{dex_mod}]]}}' name='roll_DexterityCheck'></button>
<!-- Constitution -->
<input class="sheet-stat-input" type="text" name="attr_con" value="10">
<span class="sheet-stat-span">Con</span>
<input class="sheet-stat-input" type="text" name="attr_con_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Constitution Throw}} {{roll=[[1d20 + @{con_mod}]]}}' name='roll_ConstitutionCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Constitution Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{con_mod}]]}}' name='roll_ConstitutionCheck'></button>
<!-- Charisma -->
<input class="sheet-stat-input" type="text" name="attr_chr" value="10">
<span class="sheet-stat-span">Chr</span>
<input class="sheet-stat-input" type="text" name="attr_chr_mod" value="0">
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Charisma Throw}} {{roll=[[1d20 + @{chr_mod}]]}}' name='roll_CharismaCheck'></button>
<button class="sheet-roll-button" type='roll' value='&{template:acks} {{name=Charisma Throw}} {{character=@{character_name}}} {{roll=[[1d20 + @{chr_mod}]]}}' name='roll_CharismaCheck'></button>
</div>
<div class="stat2-grid">
<!-- Hit Points -->
@ -126,27 +126,27 @@
<span class="sheet-save-span">Petrif. & Paral.</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_pp"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_pp_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Petrification & Paralysis}} {{roll=[[1d20 + @{save_pp_mod}]]}} {{target=[[@{save_pp}]]}}" name="roll_PPSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Petrification & Paralysis}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_pp_mod}]]}} {{target=[[@{save_pp}]]}}" name="roll_PPSave"></button></div>
<span class="sheet-save-span">Poison & Death</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_pd"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_pd_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Poison & Death}} {{roll=[[1d20 + @{save_pd_mod}]]}} {{target=[[@{save_pd}]]}}" name="roll_PDSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Poison & Death}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_pd_mod}]]}} {{target=[[@{save_pd}]]}}" name="roll_PDSave"></button></div>
<span class="sheet-save-span">Blast & Breath</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_bb"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_bb_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Blast & Breath}} {{roll=[[1d20 + @{save_bb_mod}]]}} {{target=[[@{save_bb}]]}}" name="roll_BBSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Blast & Breath}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_bb_mod}]]}} {{target=[[@{save_bb}]]}}" name="roll_BBSave"></button></div>
<span class="sheet-save-span">Staffs & Wands</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_sw"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_sw_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Staffs & Wands}} {{roll=[[1d20 + @{save_sw_mod}]]}} {{target=[[@{save_sw}]]}}" name="roll_SWSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Staffs & Wands}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_sw_mod}]]}} {{target=[[@{save_sw}]]}}" name="roll_SWSave"></button></div>
<span class="sheet-save-span">Spells</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_sp"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_sp_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Spells}} {{roll=[[1d20 + @{save_sp_mod}]]}} {{target=[[@{save_sp}]]}}" name="roll_SPSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Spells}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_sp_mod}]]}} {{target=[[@{save_sp}]]}}" name="roll_SPSave"></button></div>
</div>
</div>
</div>
@ -156,7 +156,7 @@
<!-- Initiative -->
<span class="sheet-initiative-span">Initiative</span>
<div><input class="sheet-stat-input" type="text" name="attr_initiative_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Initiative Roll}} {{subheader=@{character_name}}} {{roll=[[1d6 + @{initiative_mod} &{tracker}]]}}" name="roll_Initiative"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Initiative Roll}} {{character=@{character_name}}} {{roll=[[1d6 + @{initiative_mod} &{tracker}]]}}" name="roll_Initiative"></button></div>
<span class="sheet-initiative-span">Attack Throw</span>
<div><input class="sheet-stat-input" type="text" name="attr_attack_throw_vis" value="@{attack_throw}" disabled="true"></div>
@ -173,7 +173,7 @@
<input class="sheet-name-input" type="text" name="attr_attack_name">
<div><input class="sheet-stat-input" type="text" name="attr_attack_throw_mod"></div>
<div><input class="sheet-stat-input" type="text" name="attr_attack_dmg"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{attack_name} Attack}} {{roll=[[1d20 + @{attack_throw_mod}]]}} {{target=[[@{attack_throw}]]}} {{damage=[[@{attack_dmg}]]}}" name="roll_Attack"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{attack_name} Attack}} {{character=@{character_name}}} {{roll=[[1d20 + @{attack_throw_mod}]]}} {{target=[[@{attack_throw}]]}} {{damage=[[@{attack_dmg}]]}}" name="roll_Attack"></button></div>
</div>
</fieldset>
@ -187,7 +187,7 @@
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_proficiency_name">
<div><input class="sheet-stat-input" type="text" name="attr_proficiency_desc"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{proficiency_name} Proficency}} {{desc=@{proficiency_desc}}}" name="roll_Proficiency"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{proficiency_name}}} {{character=@{character_name}}} {{subheader=Proficiency}} {{desc=@{proficiency_desc}}}" name="roll_Proficiency"></button></div>
</div>
</fieldset>
</div>
@ -202,7 +202,7 @@
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_ability_name">
<div><input class="sheet-stat-input" type="text" name="attr_ability_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{ability_name}}} {{@subheader=Class/Race Ability}} {{roll=[[1d20]]}} {{target=@{ability_throw}}}" name="roll_Ability"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{ability_name}}} {{@subheader=Class/Race Ability}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{ability_throw}}}" name="roll_Ability"></button></div>
</div>
</fieldset>
@ -213,30 +213,30 @@
<span>Action Name</span><span>Throw</span><span></span>
</div>
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_opendoor_name" value="Open Door" disabled>
<input class="sheet-name-input" type="text" name="attr_opendoor_name" value="Open Door" title="A stuck door can be forced open with brute strength. Forcing open a door requires a proficiency throw of 18+. Doors of unusual material or size may impose a penalty on this proficiency throw. In addition, for each point of Strength adjustment, modify the result of the die roll by +/- 4. (A character with Strength 18 thus opens doors with a proficiency throw of 6+). If two characters cooperate to force open a door, use the stronger character’s Strength adjustment +4. A roll of 1 always fails to open a door. It takes only one combat round to force open a door, and characters may try again if they fail." disabled>
<div><input class="sheet-stat-input" type="text" name="attr_opendoor_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="/roll 1d20" name="roll_OpenDoor"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Open Door}} {{@subheader=Action}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{opendoor_throw}}}" name="roll_OpenDoor"></button></div>
</div>
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_detectdoor_name" value="Detect Secret Door" disabled>
<input class="sheet-name-input" type="text" name="attr_detectdoor_name" value="Detect Secret Door" title="Some doors are somehow concealed or hidden - these are secret doors. Common secret doors are sliding panels in a wall, trap-doors under rugs, and so on. Secret doors can only be spotted if characters are specifically looking for them. When a player declares that his character is looking for secret door, the Judge should make a proficiency throw on behalf of the character. All characters except elves will spot a secret door if one is present on a throw of 18+ on 1d20. Elves have keen eyes that allow them to detect hidden and secret doors with a proficiency throw of 8+ on 1d20 when actively searching, or 14+ on casual inspection. It takes 1 turn for a character to search a 10’ x 10’ area. Since the Judge rolls the dice, the player never know if the roll failed or if there simply is no door in the area searched. Each character has only one chance to find each secret door." disabled>
<div><input class="sheet-stat-input" type="text" name="attr_detectdoor_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="/roll 1d20" name="roll_DetectDoor"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Detect Secret Door}} {{@subheader=Action}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{detectdoor_throw}}}" name="roll_DetectDoor"></button></div>
</div>
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_hearnoise_name" value="Hear Noise" disabled>
<input class="sheet-name-input" type="text" name="attr_hearnoise_name" value="Hear Noise" title="Players will sometimes want their character to listen at a door or intersection to hear any noises beyond. Again, the Judge should make a proficiency throw on behalf of the character. A throw of 18+ on 1d20 succeeds. Dwarves and elves only need to throw 14+ due to their keen hearing. A thief has specially trained for this task, and has a different chance of success (refer to the Thief Skills table). This attempt may only be made one time at any door or intersection by a character. Note that some creatures, such as undead, do not make noise." disabled>
<div><input class="sheet-stat-input" type="text" name="attr_hearnoise_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="/roll 1d20" name="roll_HearNoise"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Hear Noise}} {{@subheader=Action}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{hearnoise_throw}}}" name="roll_HearNoise"></button></div>
</div>
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_findtraps_name" value="Find Traps" disabled>
<input class="sheet-name-input" type="text" name="attr_findtraps_name" value="Find Traps" title="While thieves have a special skill to detect traps, characters of all classes can search for non-magical traps with time and caution. All characters except dwarves succeed in spotting a trap with a proficiency throw of 18+ on 1d20. Dwarves succeed with a proficiency throw of 14+. Players must declare that their characters are actively looking for traps, and they must be looking in the right place. This roll may only be made once per character in a particular location, and it takes 1 turn per 10’ x 10’ area searched." disabled>
<div><input class="sheet-stat-input" type="text" name="attr_findtraps_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="?{Spell|Cure Light Wounds, **Cure Light Wounds** Target Regains [[1d8+5]] HP. | Cure Moderate Wounds, **Cure Moderate Wounds** Target Regains [[2d8+8]] HP. | Cure Serious Wounds, **Cure Serious Wounds** Target Regains [[3d8+8]] HP.}" name="roll_FindTraps"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Find Traps}} {{@subheader=Action}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{findtraps_throw}}}" name="roll_FindTraps"></button></div>
</div>
<fieldset class="repeating_actions">
<div class="proficiencies-grid">
<input class="sheet-name-input" type="text" name="attr_action_name">
<div><input class="sheet-stat-input" type="text" name="attr_action_throw"></div>
<div><button class="sheet-roll-button" type="roll" value="/roll 1d20" name="roll_Action"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{action_name}}} {{@subheader=Action}} {{character=@{character_name}}} {{roll=[[1d20]]}} {{target=@{action_throw}}}" name="roll_Action"></button></div>
</div>
</fieldset>
</div>
@ -246,7 +246,18 @@
<div class="sheet-equipment-title">
<h3>Equipment & Magic Items</h3>
</div>
<span>Item Name</span><span>Encumb.</span>
<div class="total-encumb-display">
<span>Total Encumbrance:</span>
<span name="attr_encumbrance_total"></span>
</div>
<span>Item Name</span><span title="Stone Fractions to Decimal:
1/6 = 0.167
2/6 (1/3) = 0.333
3/6 (1/2) = 0.5
4/6 (2/3) = 0.667
5/6 = 0.833">Encumb.</span>
</div>
<fieldset class="repeating_equipment">
<div class="equipment-grid">
@ -315,8 +326,8 @@
<div><input class="sheet-stat-input" type="text" name="attr_spell_level"></div>
<div class="grid-span-4-2"><textarea class="sheet-stat-input sheet-txtarea" name="attr_spell_effect" ></textarea></div>
<div><input class="sheet-stat-input" type="text" name="attr_spell_range"></div>
<div><input class="sheet-stat-input" type="text" name="attr_spell_roll"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{spell_name}}} {{subheader=Level @{spell_level} @{spell_school} Spell}} {{desc=@{spell_effect}}} {{roll=[[@{spell_roll}]]}} {{range=@{spell_range}}}" name="roll_Spell"></button></div>
<div><input class="sheet-stat-input" type="text" name="attr_spell_roll" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{spell_name}}} {{subheader=Level @{spell_level} @{spell_school} Spell}} {{desc=@{spell_effect}}} {{character=@{character_name}}} {{roll=[[@{spell_roll}]]}} {{range=@{spell_range}}}" name="roll_Spell"></button></div>
<div class="sheet-hidden"><input type="text" name="attr_spell_school"></div>
</div>
</fieldset>
@ -343,7 +354,7 @@
<!-- Initiative -->
<span class="sheet-initiative-span">Initiative</span>
<div><input class="sheet-stat-input" type="text" name="attr_initiative_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Initiative Roll}} {{subheader=@{character_name}}} {{roll=[[1d6 + @{initiative_mod} &{tracker}]]}}" name="roll_Initiative"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Initiative Roll}} {{character=@{character_name}}} {{roll=[[1d6 + @{initiative_mod} &{tracker}]]}}" name="roll_Initiative"></button></div>
</div>
<div class="attacks-grid">
<div class="sheet-attack-title">
@ -356,7 +367,7 @@
<input class="sheet-name-input" type="text" name="attr_attack_name">
<div><input class="sheet-stat-input" type="text" name="attr_attack_throw_mod"></div>
<div><input class="sheet-stat-input" type="text" name="attr_attack_dmg"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{attack_name} Attack}} {{roll=[[1d20 + @{attack_throw_mod}]]}} {{target=[[@{attack_throw}]]}} {{damage=[[@{attack_dmg}]]}}" name="roll_Attack"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=@{attack_name} Attack}} {{character=@{character_name}}} {{roll=[[1d20 + @{attack_throw_mod}]]}} {{target=[[@{npc_attack_throw}]]}} {{damage=[[@{attack_dmg}]]}}" name="roll_Attack"></button></div>
</div>
</fieldset>
@ -375,11 +386,15 @@
</fieldset>
</div>
<div class="npc-rsection">
<div class="attacks-grid">
<div class="hitdie-grid">
<span class="sheet-title-line">Hit Dice</span>
<input class="sheet-stat-input" type="text" name="attr_npc_hitdice">
<input class="sheet-stat-input" type="text" name="attr_npc_hitdicemod" value="d8">
<div><button class="sheet-roll-button" type="roll" value="/w gm &{template:acks}{{name=@{character_name} Hit Dice}}{{roll=[[@{npc_hitdice}@{npc_hitdicemod}]]}}" name="roll_NPCHitDice"></button></div>
<span>
<input type="checkbox" name="attr_npc_hda_1" class="hd-checkbox">
<input type="checkbox" name="attr_npc_hda_2" class="hd-checkbox">
<input type="checkbox" name="attr_npc_hda_3" class="hd-checkbox">
</span>
<input class="sheet-stat-input" type="text" name="attr_npc_hitdice" value="d8">
<div><button class="sheet-roll-button" type="roll" value="/w gm &{template:acks}{{name=Hit Dice}}{{character=@{character_name}}} {{roll=[[@{npc_hitdice}]]}}" name="roll_NPCHitDice"></button></div>
<span class="sheet-title-line">Hit Points/Max</span><input class="sheet-stat-input" type="text" name="attr_hp"><input class="sheet-stat-input" type="text" name="attr_hp_max"><span></span>
@ -410,27 +425,27 @@
<span class="sheet-save-span">Petrif. & Paral.</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_pp"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_pp_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Petrification & Paralysis}} {{roll=[[1d20 + @{save_pp_mod}]]}} {{target=[[@{save_pp}]]}}" name="roll_PPSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Petrification & Paralysis}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_pp_mod}]]}} {{target=[[@{save_pp}]]}}" name="roll_PPSave"></button></div>
<span class="sheet-save-span">Poison & Death</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_pd"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_pd_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Poison & Death}} {{roll=[[1d20 + @{save_pd_mod}]]}} {{target=[[@{save_pd}]]}}" name="roll_PDSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Poison & Death}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_pd_mod}]]}} {{target=[[@{save_pd}]]}}" name="roll_PDSave"></button></div>
<span class="sheet-save-span">Blast & Breath</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_bb"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_bb_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Blast & Breath}} {{roll=[[1d20 + @{save_bb_mod}]]}} {{target=[[@{save_bb}]]}}" name="roll_BBSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Blast & Breath}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_bb_mod}]]}} {{target=[[@{save_bb}]]}}" name="roll_BBSave"></button></div>
<span class="sheet-save-span">Staffs & Wands</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_sw"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_sw_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Staffs & Wands}} {{roll=[[1d20 + @{save_sw_mod}]]}} {{target=[[@{save_sw}]]}}" name="roll_SWSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Staffs & Wands}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_sw_mod}]]}} {{target=[[@{save_sw}]]}}" name="roll_SWSave"></button></div>
<span class="sheet-save-span">Spells</span>
<div><input class="sheet-stat-input" type="text" name="attr_save_sp"></div>
<div><input class="sheet-stat-input" type="text" name="attr_save_sp_mod" value="0"></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Spells}} {{roll=[[1d20 + @{save_sp_mod}]]}} {{target=[[@{save_sp}]]}}" name="roll_SPSave"></button></div>
<div><button class="sheet-roll-button" type="roll" value="&{template:acks} {{name=Saving Throw}} {{subheader=Spells}} {{character=@{character_name}}} {{roll=[[1d20 + @{save_sp_mod}]]}} {{target=[[@{save_sp}]]}}" name="roll_SPSave"></button></div>
</div>
</div>
</div>
@ -439,31 +454,109 @@
<!-- Roll Templates -->
<rolltemplate class="sheet-rolltemplate-acks">
<div class="sheet-acks-container">
{{#character}}
<div class="sheet-acks-charname">{{character}}</div>
{{/character}}
<div class="sheet-acks-header">{{name}}</div>
{{#subheader}}
<div class="sheet-acks-subheader sheet-acks-row">{{subheader}}</div>
{{/subheader}}
{{#target}}
<div class="sheet-acks-row"><strong>Target</strong> <span class="sheet-acks-target-value">{{target}}+</span></div>
{{/target}}
{{#range}}
<div class="sheet-acks-row"><strong>Range</strong> <span class="sheet-acks-target-value">{{range}}</span></div>
{{/range}}
{{#roll}}
<div class="sheet-acks-row"><strong>Roll</strong> {{roll}}</div>
{{/roll}}
{{#damage}}
<div class="sheet-acks-row"><strong>Damage</strong> {{damage}}</div>
{{/damage}}
{{#desc}}
<div class="sheet-acks-row sheet-acks-desc">{{desc}}</div>
{{/desc}}
{{#allprops() character subheader target range roll damage desc}}
<div class="sheet-acks-row"><strong>{{key}}</strong> {{value}}</div>
{{/allprops() character subheader target range roll damage desc}}
</div>
</rolltemplate>
<!-- Sheet Workers -->
<script type="text/worker">
/*** Equipment Encumbrance Totaling ***/
on('change:repeating_equipment:equipment_encumb remove:repeating_equipment', function() {
console.log('calculating equipment encumbrance');
repeatingSum("encumbrance_total","equipment","equipment_encumb", "round: 3");
});
const repeatingSum = (destinations, section, fields, ...extras) => {
const isNumber = value => parseFloat(value).toString() === value.toString();
const isOption = value => [...checks.valid, ...checks.roundtypes].includes(value);
const isRounding = value => checks.roundtypes.includes(value);
const isFraction = value => value.includes('/') && !(value.includes(',') || value.includes('|'));
const getTrimmed = value => value.toLowerCase().replace(/\s/g, '');
const getRounded = (type, value, pow) => (Math[type](value * Math.pow(10, pow)) / Math.pow(10, pow)).toFixed(Math.max(0, pow));
const getFraction = (value) => /*{ console.log(`value: ${value}`); */
parseInt(value.split('/')[0]) / parseInt(value.split('/')[1]);
const getMultiplier = (value, rounding = 1) => 'undefined' === typeof value ? (rounding ? 0: 1) : (
isNumber(value) ? parseFloat(value) : (isFraction(value) ? getFraction(value) : value));
if (!Array.isArray(destinations)) destinations = [getTrimmed(destinations)];
if (!Array.isArray(fields)) fields = [getTrimmed(fields)];
const fields_trimmed = fields.map(field => getTrimmed(field).split(':')[0]);
const subfields = fields_trimmed.slice(0,destinations.length);
const checks = { valid: ['multiplier'], roundtypes: ['ceil', 'round', 'floor'] };
let properties = {attributes: {}, options: {}};
extras.forEach(extra => {
const [prop, v] = getTrimmed(extra).split(':');
const multiplier_maybe = getMultiplier(v, isRounding(prop));
const obj = isNumber(multiplier_maybe) ? subfields.reduce((obj,field) => {
obj[field] = multiplier_maybe;
return obj;
},{}) : multiplier_maybe.split(',').reduce((obj, item) => {
const [stat, value] = item.split('|');
const multiplier = getMultiplier(value, isRounding(prop));
obj[stat] = multiplier;
return obj;
}, {});
properties[isOption(prop) ? 'options' : 'attributes'][prop] = obj;
});
getSectionIDs(`repeating_${section}`, idArray => {
const attrArray = idArray.reduce((m, id) => [...m, ...(fields_trimmed.map(field => `repeating_${section}_${id}_${field}`))], []);
getAttrs([...attrArray, ...Object.keys(properties.attributes)], v => {
const getValue = (section, id, field) => v[`repeating_${section}_${id}_${field}`] === 'on' ? 1 : parseFloat(v[`repeating_${section}_${id}_${field}`]) || 0;
const commonMultipliers = (fields.length <= destinations.length) ? [] : fields.splice(destinations.length, fields.length - destinations.length);
const output = destinations.reduce((obj, destination, index) => {
let sumTotal = idArray.reduce((total, id) => total + getValue(section, id, fields_trimmed[index]) * commonMultipliers.reduce((subtotal, mult) => subtotal * ((!mult.includes(':') || mult.split(':')[1].split(',').includes(fields_trimmed[index])) ? getValue(section, id, mult.split(':')[0]) : 1), 1), 0);
sumTotal *= (properties.options.hasOwnProperty('multiplier') && Object.keys(properties.options.multiplier).includes(fields_trimmed[index])) ? (parseFloat(properties.options.multiplier[fields_trimmed[index]]) || 0): 1;
sumTotal += Object.entries(properties.attributes).reduce((total, [key, value]) =>
total += (value.hasOwnProperty(fields_trimmed[index]) ? parseFloat(v[key] || 0) * (parseFloat(value[fields_trimmed[index]]) || 1): 0) , 0);
checks.roundtypes.forEach(type => {
if (properties.options.hasOwnProperty(type)) {
if (Object.keys(properties.options[type]).includes(fields_trimmed[index])) {
sumTotal = getRounded(type, sumTotal, (+properties.options[type][fields_trimmed[index]] || 0));
} else if (properties.options[type] == '0' || !isNaN(+properties.options[type] || 'x') ) {
sumTotal = getRounded(type, sumTotal, +properties.options[type]);
}
}
});
obj[destination] = sumTotal;
return obj;
}, {});
setAttrs(output);
});
});
};
</script>
<script type="text/worker">
/*** ATTRIBUTE RELATED WORKERS ***/
const calculateAttrMod = function(attr) {
// Calculate the modifier for a given attribute value
@ -672,7 +765,7 @@
/* NPC Attack Throw */
const calculateNpcHit = function(hd) {
switch(hd.toString()) {
switch(hd.toString().replace(/(d\d+[+\-0-9]*)/, '')) {
case '1':
return 10;
case '2':

12
roll20/hit_dice.js

@ -30,8 +30,9 @@ var HitDice = HitDice || (function() {
sendChat('',`/w "${who}" Rolling hit dice for ${count} token(s).`);
}
},
findRoll = function(txt){
return txt.match(/\d+d\d+(\+\d+)?/)[0] || 0;
findRoll = function(txt) {
let roll = txt.match(/\d+d\d+([\+\-]\d+)?/);
return roll ? roll[0] : 0;
},
rollHitDice = function(obj) {
@ -56,9 +57,8 @@ var HitDice = HitDice || (function() {
name: state.HitDice.config.hitDiceAttribute
})[0];
if( hdAttrib ) {
//sendChat('', 'HERE WE ARE');
//log(hdAttrib);
if(hdAttrib) {
log(hdAttrib);
hdExpression = findRoll(hdAttrib.get('current'));
sendChat('','/r '+hdExpression+'+'+bonus,function(r){
@ -113,5 +113,3 @@ on('ready',function() {
HitDice.configure();
HitDice.RegisterEventHandlers();
});

18
roll20/npc_party_import.js

@ -48,6 +48,12 @@ var addAttr = function(char_id, name, value, max) {
on("chat:message", function(msg) {
if(msg.type == "api" && msg.content.indexOf("!acksimport ") !== -1) {
var default_token_images = {
"arcane": "",
"divine": "https://s3.amazonaws.com/files.d20.io/images/137282084/8KCYW2UxnjP83Frhl0rLyg/thumb.png?1590201189",
"physical": ""
};
var data = msg.content.replace("!acksimport ", "");
var npcs = JSON.parse(data);
@ -108,6 +114,7 @@ on("chat:message", function(msg) {
addAttr(sheet.id, melee_name + "_attack_throw_mod", c.melee.throw_mod, null);
addAttr(sheet.id, melee_name + "_attack_dmg", c.melee.damage, null);
// for spells
if(c.spells) {
for(spell of c.spells) {
let spell_name = "repeating_spells_" + generateRowID();
@ -126,6 +133,16 @@ on("chat:message", function(msg) {
}
}
// populate the default token
let default_token = createObj("graphic", {
"imgsrc": default_token_images["divine"],
represents: sheet.id,
"showname": true,
"layer": "objects",
"pageid": Campaign().get('playerpageid')
});
setDefaultTokenForCharacter(sheet, default_token);
}
}
@ -142,4 +159,3 @@ on("chat:message", function(msg) {
}
}
});
Loading…
Cancel
Save