Shadow of the Demon Lord v6: made damage rolling optional

This commit is contained in:
joesinghaus
2018-10-22 16:55:49 +02:00
parent 2a9592e8e6
commit 2d56bbbc7a
9 changed files with 222 additions and 131 deletions
+2
View File
@@ -5,7 +5,9 @@
### Version 6
* Styling cleanup, using CSS grid instead of Flexbox in some key places
* Added a rest button
* Made rolling weapon damage optional (or available on extra click)
* Removed legacy conversion code
* Sheet worker refactored and cleaned up
* Made some adjustments to adapt to changed Roll20 base CSS
### Version 5
@@ -0,0 +1,105 @@
<rolltemplate class="sheet-rolltemplate-sotdl">
{{#title}}
<div class="sheet-title">
<div>{{title}}</div>
{{#subtitle}}
<div class="sheet-subtitle">{{subtitle}}</div>
{{/subtitle}}
</div>
{{/title}}
{{#name}}
<div class="sheet-name">{{name}}</div>
{{/name}}
{{^sacrifice}}
<div class="sheet-rolls">
{{#showroll}}
<div class="sheet-roll">
<span class="sheet-label">{{roll-label}}</span>
{{#boons}}
{{#rollGreater() boons 0}}
<span class="sheet-boons sheet-super">
+{{boons}}
<div class="sheet-info">
<span data-i18n="WITH">with</span> {{boons}}<span> </span>
{{#rollLess() boons 2}}
<span class="sheet-lower" data-i18n="BOON">boon</span>
{{/rollLess() boons 2}}
{{#rollGreater() boons 1}}
<span class="sheet-lower" data-i18n="BOONS">boons</span>
{{/rollGreater() boons 1}}
</div>
</span>
{{/rollGreater() boons 0}}
{{#rollLess() boons 0}}
<span class="sheet-banes sheet-super">
{{boons}}
<div class="sheet-info">
<span data-i18n="WITH">with</span>{{boons}}<span> </span>
{{#rollGreater() boons -2}}
<span class="sheet-lower" data-i18n="BANE">bane</span>
{{/rollGreater() boons -2}}
{{#rollLess() boons -1}}
<span class="sheet-lower" data-i18n="BANES">banes</span>
{{/rollLess() boons -1}}
</div>
</span>
{{/rollLess() boons 0}}
{{/boons}}
<span class="sheet-label">: </span>{{roll}}
{{#versus}}
<span> </span><span data-i18n="VS">vs</span> <span class="sheet-vs">{{versus}}</span>
{{/versus}}
</div>
{{/showroll}}
{{#damage}}
<div class="sheet-damage">
<span class="sheet-label"><span data-i18n="DAMAGE">Damage</span>: </span>{{damageroll}}
</div>
{{/damage}}
{{#damageplus}}
<div class="sheet-damageplus">{{damageplus}}</div>
{{/damageplus}}
</div>
{{/sacrifice}}
{{#spell}}{{^sacrifice}}
<div class="sheet-spell-info">
{{#requirement}}
<div><strong data-i18n="REQUIREMENT">Requirement</strong> {{requirement}}</div>
{{/requirement}}
{{#target}}
<div><strong data-i18n="TARGET">Target</strong> {{target}}</div>
{{/target}}
{{#area}}
<div><strong data-i18n="AREA">Area</strong> {{area}}</div>
{{/area}}
{{#duration}}
<div><strong data-i18n="DURATION">Duration</strong> {{duration}}</div>
{{/duration}}
</div>
{{/sacrifice}}{{/spell}}
<div class="sheet-content">
{{#sacrifice}}
<div><strong data-i18n="SACRIFICE">Sacrifice</strong> {{sacrifice}}</div>
{{/sacrifice}}
{{^sacrifice}}
{{#rollGreater() roll 19}}{{#roll20plus}}
<div><strong data-i18n="ATTACK_ROLL_20+">Attack Roll 20+</strong> {{roll20plus}}</div>
{{/roll20plus}}{{/rollGreater() roll 19}}
{{#triggered}}
<div><strong data-i18n="TRIGGERED">Triggered</strong> {{triggered}}</div>
{{/triggered}}
{{#permanence}}
<div><strong data-i18n="PERMANENCE">Permanence</strong> {{permanence}}</div>
{{/permanence}}
{{#aftereffect}}
<div><strong data-i18n="AFTEREFFECT">Aftereffect</strong> {{aftereffect}}</div>
{{/aftereffect}}
{{#special}}
<div><strong data-i18n="SPECIAL">Special</strong> {{special}}</div>
{{/special}}
{{#description}}
<div class="sheet-description"> {{description}}</div>
{{/description}}
{{/sacrifice}}
</div>
</rolltemplate>
+13 -108
View File
@@ -103,6 +103,15 @@
<input type="checkbox" title="@{setting_npc_afflictions}" name="attr_setting_npc_afflictions" value="1">
<span data-i18n="NPC_AFFLICTIONS">NPC afflictions</span>
</label>
<label class="sheet-40">
<input type="checkbox" title="@{setting_roll_weapon_damage}" name="attr_setting_roll_weapon_damage" value="1" checked>
<span data-i18n="ROLL_WEAPON_DAMAGE">Roll weapon damage</span>
</label>
<input type="hidden" name="attr_setting_roll_weapon_damage" class="sheet-weapon-damage-setting" value="1">
<label class="sheet-60">
<input type="checkbox" title="@{setting_show_damage_button}" name="attr_setting_show_damage_button" value="1">
<span data-i18n="SHOW_DAMAGE_BUTTON_INSTEAD">Show damage button instead</span>
</label>
<label>
<input type="checkbox" title="@{setting_versus_freeform}" name="attr_setting_versus_freeform" value="1">
<span data-i18n="SHOW_VERSUS_TEXT">Show a text field instead of dropdown for "Against" fields</span>
@@ -428,7 +437,8 @@
</label>
<div class="sheet-flex-row">
<input type="hidden" name="attr_weapon_against_display" value="">
<button type="roll" name="roll_Attack" title="%{@{character_id}|repeating_weapons_$X_Attack}" value="@{output_option} &{template:sotdl} @{setting_show_name} {{title=@{weapon_name}}} {{showroll=1}} {{roll-label=^{ATTACK}}} {{roll=[[@{die_attack} + @{weapon_mod} + [[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]@{die_boon}k1[boons/banes]]]}} {{boons=[[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]}} {{damage=@{weapon_damage}}} {{damageroll=[[0@{weapon_damage} + @{global_damage_bonus}[global bonus]]]}} {{versus=@{weapon_against}}} {{roll20plus=@{weapon_roll20plus}}} {{description=@{weapon_description}}}"></button>
<input type="hidden" name="attr_weapon_damage_formula" value="">
<button type="roll" name="roll_Attack" title="%{@{character_id}|repeating_weapons_$X_Attack}" value="@{output_option} &{template:sotdl} @{setting_show_name} {{title=@{weapon_name}}} {{showroll=1}} {{roll-label=^{ATTACK}}} {{roll=[[@{die_attack} + @{weapon_mod} + [[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]@{die_boon}k1[boons/banes]]]}} {{boons=[[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]}} @{weapon_damage_formula} {{versus=@{weapon_against}}} {{roll20plus=@{weapon_roll20plus}}} {{description=@{weapon_description}}}"></button>
<input type="text" spellcheck="false" class="sheet-name" title="@{repeating_weapons_$X_weapon_name}" name="attr_weapon_name">
<select title="@{repeating_weapons_$X_weapon_attribute}" name="attr_weapon_attribute" class="sheet-mod">
<option value="strength" data-i18n="STRENGTH" selected>Strength</option>
@@ -462,7 +472,7 @@
</div>
</div>
<div class="sheet-display">
<button type="roll" name="roll_Attack" title="%{@{character_id}|repeating_weapons_$X_Attack}" class="sheet-invisible-button" value="@{output_option} &{template:sotdl} @{setting_show_name} {{title=@{weapon_name}}} {{showroll=1}} {{roll-label=^{ATTACK}}} {{roll=[[@{die_attack} + @{weapon_mod} + [[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]@{die_boon}k1[boons/banes]]]}} {{boons=[[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]}} {{damage=@{weapon_damage}}} {{damageroll=[[0@{weapon_damage} + @{global_damage_bonus}[global bonus]]]}} {{versus=@{weapon_against}}} {{roll20plus=@{weapon_roll20plus}}} {{description=@{weapon_description}}}"></button>
<button type="roll" name="roll_Attack" title="%{@{character_id}|repeating_weapons_$X_Attack}" class="sheet-invisible-button" value="@{output_option} &{template:sotdl} @{setting_show_name} {{title=@{weapon_name}}} {{showroll=1}} {{roll-label=^{ATTACK}}} {{roll=[[@{die_attack} + @{weapon_mod} + [[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]@{die_boon}k1[boons/banes]]]}} {{boons=[[@{boons_banes_query} + @{weapon_boons} + @{global_attack_boons} + @{global_weapon_attack_boons} - @{banes_from_afflictions}]]}} @{weapon_damage_formula} {{versus=@{weapon_against}}} {{roll20plus=@{weapon_roll20plus}}} {{description=@{weapon_description}}}"></button>
<input type="hidden" name="attr_weapon_boons_display" value="">
<span class="sheet-name sheet-space-after" name="attr_weapon_name"></span>
<input type="hidden" name="attr_weapon_properties" class="sheet-hider" value="">
@@ -477,6 +487,7 @@
<span class="sheet-bracketed" name="attr_weapon_damage"></span>
<span class="sheet-space-before-nonempty" name="attr_weapon_against_display"></span>
</div>
<button type="roll" style="display:none" name="roll_damage" value="@{output_option} &{template:sotdl} {{damage=1}} {{damageroll=[[@{weapon_damage} + @{global_damage_bonus}[global bonus] + ?{Bonus damage|0}]]}}"></button>
</fieldset>
</div>
<div class="sheet-right-col">
@@ -1443,109 +1454,3 @@
</div>
</div>
</div>
<rolltemplate class="sheet-rolltemplate-sotdl">
{{#title}}
<div class="sheet-title">
<div>{{title}}</div>
{{#subtitle}}
<div class="sheet-subtitle">{{subtitle}}</div>
{{/subtitle}}
</div>
{{/title}}
{{#name}}
<div class="sheet-name">{{name}}</div>
{{/name}}
{{^sacrifice}}
<div class="sheet-rolls">
{{#showroll}}
<div class="sheet-roll">
<span class="sheet-label">{{roll-label}}</span>
{{#boons}}
{{#rollGreater() boons 0}}
<span class="sheet-boons sheet-super">
+{{boons}}
<div class="sheet-info">
<span data-i18n="WITH">with</span> {{boons}}<span> </span>
{{#rollLess() boons 2}}
<span class="sheet-lower" data-i18n="BOON">boon</span>
{{/rollLess() boons 2}}
{{#rollGreater() boons 1}}
<span class="sheet-lower" data-i18n="BOONS">boons</span>
{{/rollGreater() boons 1}}
</div>
</span>
{{/rollGreater() boons 0}}
{{#rollLess() boons 0}}
<span class="sheet-banes sheet-super">
{{boons}}
<div class="sheet-info">
<span data-i18n="WITH">with</span>{{boons}}<span> </span>
{{#rollGreater() boons -2}}
<span class="sheet-lower" data-i18n="BANE">bane</span>
{{/rollGreater() boons -2}}
{{#rollLess() boons -1}}
<span class="sheet-lower" data-i18n="BANES">banes</span>
{{/rollLess() boons -1}}
</div>
</span>
{{/rollLess() boons 0}}
{{/boons}}
: {{roll}}
{{#versus}}
<span> </span><span data-i18n="VS">vs</span> <span class="sheet-vs">{{versus}}</span>
{{/versus}}
</div>
{{/showroll}}
{{#damage}}
<div class="sheet-damage">
<span class="sheet-label" data-i18n="DAMAGE">Damage</span>: {{damageroll}}
</div>
{{/damage}}
{{#damageplus}}
<div class="sheet-damageplus">{{damageplus}}</div>
{{/damageplus}}
</div>
{{/sacrifice}}
{{#spell}}{{^sacrifice}}
<div class="sheet-spell-info">
{{#requirement}}
<div><strong data-i18n="REQUIREMENT">Requirement</strong> {{requirement}}</div>
{{/requirement}}
{{#target}}
<div><strong data-i18n="TARGET">Target</strong> {{target}}</div>
{{/target}}
{{#area}}
<div><strong data-i18n="AREA">Area</strong> {{area}}</div>
{{/area}}
{{#duration}}
<div><strong data-i18n="DURATION">Duration</strong> {{duration}}</div>
{{/duration}}
</div>
{{/sacrifice}}{{/spell}}
<div class="sheet-content">
{{#sacrifice}}
<div><strong data-i18n="SACRIFICE">Sacrifice</strong> {{sacrifice}}</div>
{{/sacrifice}}
{{^sacrifice}}
{{#rollGreater() roll 19}}{{#roll20plus}}
<div><strong data-i18n="ATTACK_ROLL_20+">Attack Roll 20+</strong> {{roll20plus}}</div>
{{/roll20plus}}{{/rollGreater() roll 19}}
{{#triggered}}
<div><strong data-i18n="TRIGGERED">Triggered</strong> {{triggered}}</div>
{{/triggered}}
{{#permanence}}
<div><strong data-i18n="PERMANENCE">Permanence</strong> {{permanence}}</div>
{{/permanence}}
{{#aftereffect}}
<div><strong data-i18n="AFTEREFFECT">Aftereffect</strong> {{aftereffect}}</div>
{{/aftereffect}}
{{#special}}
<div><strong data-i18n="SPECIAL">Special</strong> {{special}}</div>
{{/special}}
{{#description}}
<div class="sheet-description"> {{description}}</div>
{{/description}}
{{/sacrifice}}
</div>
</rolltemplate>
+57 -11
View File
@@ -154,9 +154,28 @@ const handleHealthChange = () => {
};
// Handle display attributes for weapons
const calcWeaponMod = (prefix) => {
getAttrs([...statMods, `${prefix}_attribute`], v => {
setAttr(`${prefix}_mod`, v[v[`${prefix}_attribute`] + "_mod"]);
const calcWeaponMod = (prefixes) => {
getAttrs([...statMods, ...prefixes.map(prefix => `${prefix}_attribute`)], v => {
const setting = prefixes.reduce((m, prefix) => {
m[`${prefix}_mod`] = v[v[`${prefix}_attribute`] + "_mod"];
return m;
}, {});
setAttrs(setting);
});
};
const calcWeaponDamage = (prefixes) => {
getAttrs([...prefixes.map(prefix => `${prefix}_damage`), "setting_roll_weapon_damage", "global_damage_bonus", "setting_show_damage_button"], v => {
const setting = prefixes.reduce((m, prefix) => {
if (v[`${prefix}_damage`] == "" || (v.setting_roll_weapon_damage === "0" && v.setting_show_damage_button === "0")) {
m[`${prefix}_damage_formula`] = "";
} else if (v.setting_roll_weapon_damage == "0") {
m[`${prefix}_damage_formula`] = "{{damage=1}} {{damageroll=[@{weapon_damage}](~repeating_weapons_damage)}}";
} else {
m[`${prefix}_damage_formula`] = "{{damage=1}} {{damageroll=[[@{weapon_damage} + @{global_damage_bonus}[global bonus]]]}}";
}
return m;
}, {});
setAttrs(setting);
});
};
@@ -237,10 +256,14 @@ const getSpellCastings = (rk, pwr, exp) => {
}
else if (rank === 0) return String(power + expertise + 1);
};
const calcSpellCastings = (prefix) => {
getAttrs([`${prefix}_rank`, "power", "setting_auto_spell_castings", "setting_spell_expertise"], v => {
const calcSpellCastings = (prefixes) => {
getAttrs([...prefixes.map(prefix =>`${prefix}_rank`), "power", "setting_auto_spell_castings", "setting_spell_expertise"], v => {
if (v.setting_auto_spell_castings === "1") {
setAttr(`${prefix}_castings_max`, getSpellCastings(v[`${prefix}_rank`], v.power, v.setting_spell_expertise));
const setting = prefixes.reduce((m, prefix) => {
m[`${prefix}_castings_max`] = getSpellCastings(v[`${prefix}_rank`], v.power, v.setting_spell_expertise);
return m;
}, {});
setAttrs(setting);
}
});
};
@@ -436,9 +459,26 @@ const sanitizeTab = () => getAttrs(["npc", "tab"], v => {
else if (v.npc === "0" && !["main", "equipment_talents", "spells", "background"].includes(v.tab)) setAttr("tab", "main");
});
const updateSheet = version => {
if (version < 6) {
getSectionIDs("repeating_weapons", idArray => {
calcWeaponDamage(idArray.map(id => `repeating_weapons_${id}_weapon`));
});
}
};
// Register events
on("sheet:opened", () => {
setAttr("version", "6");
getAttrs(["version"], v => {
const version = parseInt(v.version);
if (version && version < 6) {
updateSheet(5);
}
setAttrs({
version: "6",
character_sheet: "Shadow of the Demon Lord v6",
});
});
setBoonsBanesQuery();
setWhisperQuery();
});
@@ -455,12 +495,18 @@ register(["health", "healing_rate_divisor"], handleHealthChange);
// Repeating talents, weapons, attacks
register(["repeating_talents:talent_attack_mod"], () => updateTalentAttack("repeating_talents_talent"));
register(["repeating_weapons:weapon_attribute"], () => calcWeaponMod("repeating_weapons_weapon"));
register(["repeating_weapons:weapon_attribute"], () => calcWeaponMod(["repeating_weapons_weapon"]));
register(statMods, () => {
getSectionIDs("repeating_weapons", idArray => {
idArray.forEach(id => calcWeaponMod(`repeating_weapons_${id}_weapon`));
calcWeaponMod(idArray.map(id => `repeating_weapons_${id}_weapon`));
});
});
register(["setting_roll_weapon_damage", "global_damage_bonus", "setting_show_damage_button"], () => {
getSectionIDs("repeating_weapons", idArray => {
calcWeaponDamage(idArray.map(id => `repeating_weapons_${id}_weapon`));
});
});
register(["repeating_weapons"], () => calcWeaponDamage(["repeating_weapons_weapon"]));
register(["change:repeating_attacks:attack_range"], () => updateNpcAttack("repeating_attacks_attack"));
["weapon", "attack"].forEach(sName => {
register([`repeating_${sName}s:${sName}_boons`], () => {
@@ -476,10 +522,10 @@ register(["repeating_spells:spell_sacrifice"], calcSacrificeQuery);
register(["repeating_spells:spell_attack_mod"], () => updateSpellAttack("repeating_spells_spell"));
register(["power", "setting_auto_spell_castings", "setting_spell_expertise"], () => {
getSectionIDs("repeating_spells", idArray => {
idArray.forEach(id => calcSpellCastings(`repeating_spells_${id}_spell`));
calcSpellCastings(idArray.map(id => `repeating_spells_${id}_spell`));
});
});
register(["repeating_spells:spell_rank"], () => calcSpellCastings("repeating_spells_spell"));
register(["repeating_spells:spell_rank"], () => calcSpellCastings(["repeating_spells_spell"]));
register(["repeating_spells", "remove:repeating_spells"], buildSpellBook);
// Reset and resting
+17 -8
View File
@@ -355,6 +355,14 @@ $sheet_col_min_width: 364px;
}
}
.sheet-weapon-damage-setting:not([value="0"]) + label {
pointer-events: none;
input,
span {
display: none;
}
}
div {
padding: 4px 0 0 4px;
width: 100%;
@@ -2008,22 +2016,22 @@ $sheet_col_min_width: 364px;
}
.sheet-rolls {
display: flex;
flex-wrap: wrap;
font-size: 0;
.sheet-roll, .sheet-attack, .sheet-damage {
display: inline-block;
vertical-align: top;
.sheet-roll, .sheet-damage {
line-height: 25px;
font-size: 13px;
white-space: nowrap;
}
.sheet-roll, .sheet-attack, .sheet-damage, .sheet-damageplus {
.sheet-roll, .sheet-damage, .sheet-damageplus {
.sheet-vs .inlinerollresult {
vertical-align: bottom;
}
span {
> span {
vertical-align: middle;
&.sheet-label {
@@ -2094,12 +2102,13 @@ $sheet_col_min_width: 364px;
font-size: 12px;
}
.sheet-roll, .sheet-attack {
width: 65%;
.sheet-roll {
padding-right: 5px;
margin-right: auto;
}
.sheet-damage {
width: 35%;
min-width: 91px;
}
}
File diff suppressed because one or more lines are too long
+22
View File
@@ -69,6 +69,28 @@
"value": "1",
"description": "Show only textarea, hide detailed equipment column",
"descriptiontranslationkey": "BASIC_EQUIPMENT_INFO"
},
{
"attribute": "setting_roll_weapon_damage",
"displayname": "Roll weapon damage",
"displaytranslationkey": "ROLL_WEAPON_DAMAGE",
"type": "select",
"options": [
"Yes|1",
"No|0"
],
"optiontranslationkeys": [
"YES",
"NO"
],
"default": "1"
},
{
"attribute": "setting_show_damage_button",
"displayname": "Show damage button instead",
"displaytranslationkey": "SHOW_DAMAGE_BUTTON_INSTEAD",
"type": "checkbox",
"value": "1"
}
]
}
File diff suppressed because one or more lines are too long
@@ -139,11 +139,13 @@
"RESTORE_CASTINGS": "Restore castings",
"RESTORE_USES": "Restore uses",
"ROLL": "Roll",
"ROLL_WEAPON_DAMAGE": "Roll weapon damage",
"SACRIFICE": "Sacrifice",
"SACRIFICE_SPELL": "Sacrifice Spell",
"SENSES_PLACEHOLDER": "darksight",
"SETTINGS": "Settings",
"SHEET_OUTPUT": "Sheet output",
"SHOW_DAMAGE_BUTTON_INSTEAD": "Show damage button instead",
"SHOW_NAME_ON_ROLL_TEMPLATE": "Show name on roll template",
"SHOW_UP_DOWN_CHARACTERISTICS": "Show up/down arrows on characteristics",
"SHOW_VERSUS_TEXT": "Show a text field instead of dropdown for \"Against\" fields",