diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000..8cfad22f80
Binary files /dev/null and b/.DS_Store differ
diff --git a/Dragon Warriors/Dice_Warriors-removebg-preview.png b/Dragon Warriors/Dice_Warriors-removebg-preview.png
new file mode 100644
index 0000000000..641c3d440d
Binary files /dev/null and b/Dragon Warriors/Dice_Warriors-removebg-preview.png differ
diff --git a/Dragon Warriors/DragWarsTest.js b/Dragon Warriors/DragWarsTest.js
index 1ab35ad35d..2344269549 100644
--- a/Dragon Warriors/DragWarsTest.js
+++ b/Dragon Warriors/DragWarsTest.js
@@ -7,29 +7,207 @@ buttonlist.forEach(button => {
});
});
-on('change:equippedammo change:equippedrangedwep change:equippedmeleewep change:shield change:attack change:defence change:magicammobonus change:magicrangedweaponbonus change:magicmeleeweaponbonus change:armourattackpenalty change:armourdefencepenalty change:magicshield change:miscattackmelee change:miscdefencemelee change:miscattackranged change:miscdefenceranged sheet:opened', function() {
- getAttrs(['shield','attack','defence','magicammobonus','magicrangedweaponbonus','magicmeleeweaponbonus','armourattackpenalty','armourdefencepenalty','magicshield','miscattackmelee','miscdefencemelee','miscattackranged','miscdefenceranged'], function(v) {
+const repeatingSum = (destinations, section, fields, ...extras) => {
+ const isNumber = value => parseFloat(value).toString() === value.toString();
+ const isOption = value => [...checks.valid, ...checks.roundtypes].includes(value);
+ const isRounding = value => checks.roundtypes.includes(value);
+ const isFraction = value => value.includes('/') && !(value.includes(',') || value.includes('|'));
+ const getTrimmed = value => value.toLowerCase().replace(/\s/g, '');
+ const getRounded = (type, value, pow) => (Math[type](value * Math.pow(10, pow)) / Math.pow(10, pow)).toFixed(Math.max(0, pow));
+ const getFraction = (value) => /*{ console.log(`value: ${value}`); */
+ parseInt(value.split('/')[0]) / parseInt(value.split('/')[1]);
+ const getMultiplier = (value, rounding = 1) => 'undefined' === typeof value ? (rounding ? 0: 1) : (
+ isNumber(value) ? parseFloat(value) : (isFraction(value) ? getFraction(value) : value));
+ if (!Array.isArray(destinations)) destinations = [getTrimmed(destinations)];
+ if (!Array.isArray(fields)) fields = [getTrimmed(fields)];
+ const fields_trimmed = fields.map(field => getTrimmed(field).split(':')[0]);
+ const subfields = fields_trimmed.slice(0,destinations.length);
+ const checks = { valid: ['multiplier'], roundtypes: ['ceil', 'round', 'floor'] };
+ let properties = {attributes: {}, options: {}};
+ extras.forEach(extra => {
+ const [prop, v] = getTrimmed(extra).split(':');
+ const multiplier_maybe = getMultiplier(v, isRounding(prop));
+ const obj = isNumber(multiplier_maybe) ? subfields.reduce((obj,field) => {
+ obj[field] = multiplier_maybe;
+ return obj;
+ },{}) : multiplier_maybe.split(',').reduce((obj, item) => {
+ const [stat, value] = item.split('|');
+ const multiplier = getMultiplier(value, isRounding(prop));
+ obj[stat] = multiplier;
+ return obj;
+ }, {});
+ properties[isOption(prop) ? 'options' : 'attributes'][prop] = obj;
+ });
+ getSectionIDs(`repeating_${section}`, idArray => {
+ const attrArray = idArray.reduce((m, id) => [...m, ...(fields_trimmed.map(field => `repeating_${section}_${id}_${field}`))], []);
+ getAttrs([...attrArray, ...Object.keys(properties.attributes)], v => {
+ const getValue = (section, id, field) => v[`repeating_${section}_${id}_${field}`] === 'on' ? 1 : parseFloat(v[`repeating_${section}_${id}_${field}`]) || 0;
+ const commonMultipliers = (fields.length <= destinations.length) ? [] : fields.splice(destinations.length, fields.length - destinations.length);
+ const output = destinations.reduce((obj, destination, index) => {
+ let sumTotal = idArray.reduce((total, id) => total + getValue(section, id, fields_trimmed[index]) * commonMultipliers.reduce((subtotal, mult) => subtotal * ((!mult.includes(':') || mult.split(':')[1].split(',').includes(fields_trimmed[index])) ? getValue(section, id, mult.split(':')[0]) : 1), 1), 0);
+ sumTotal *= (properties.options.hasOwnProperty('multiplier') && Object.keys(properties.options.multiplier).includes(fields_trimmed[index])) ? (parseFloat(properties.options.multiplier[fields_trimmed[index]]) || 0): 1;
+ sumTotal += Object.entries(properties.attributes).reduce((total, [key, value]) =>
+ total += (value.hasOwnProperty(fields_trimmed[index]) ? parseFloat(v[key] || 0) * (parseFloat(value[fields_trimmed[index]]) || 1): 0) , 0);
+ checks.roundtypes.forEach(type => {
+ if (properties.options.hasOwnProperty(type)) {
+ if (Object.keys(properties.options[type]).includes(fields_trimmed[index])) {
+ sumTotal = getRounded(type, sumTotal, (+properties.options[type][fields_trimmed[index]] || 0));
+ } else if (properties.options[type] == '0' || !isNaN(+properties.options[type] || 'x') ) {
+ sumTotal = getRounded(type, sumTotal, +properties.options[type]);
+ }
+ }
+ });
+ obj[destination] = sumTotal;
+ return obj;
+ }, {});
+ setAttrs(output);
+ });
+ });
+};
+
+on('change:repeating_meleeweapons', function(event) {
+ if (event.sourceType === 'sheetworker' ) return;
+ const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
+ getSectionIDs('repeating_meleeweapons', function (ids) {
+ const fieldnames = [];
+ ids.forEach(id => fieldnames.push(
+ `repeating_meleeweapons_${id}_equippedmeleewep`,
+ `repeating_meleeweapons_${id}_magicmeleeweaponbonus`,
+ `repeating_meleeweapons_${id}_meleeweapon`,
+ `repeating_meleeweapons_${id}_meleeabr`,
+ `repeating_meleeweapons_${id}_meleedamage`
+ ));
+ getAttrs(fieldnames, values => {
+ const output = {};
+ ids.forEach(id => {
+ const checkbox = parseInt(values[`repeating_meleeweapons_${id}_equippedmeleewep`]) || 0;
+ const magicbonus = parseInt(values[`repeating_meleeweapons_${id}_magicmeleeweaponbonus`]) || 0;
+ const meleeweaponname = (values[`repeating_meleeweapons_${id}_meleeweapon`]) || None;
+ const meleeweaponabr = (values[`repeating_meleeweapons_${id}_meleeabr`]) || None;
+ const meleeweapondam = (values[`repeating_meleeweapons_${id}_meleedamage`]) || None;
+
+ if(id.toLowerCase() === playerclickedid) {
+ output.magicmeleeweaponbonus = checkbox ? magicbonus : 0;
+ output.meleeweapon = checkbox ? meleeweaponname : "None";
+ output.meleeabr = checkbox ? meleeweaponabr : "0d0";
+ output.meleedamage = checkbox ? meleeweapondam : "0d0";
+ }
+ else if(checkbox) {
+ output[`repeating_meleeweapons_${id}_equippedmeleewep`] = 0;
+ }
+ setAttrs(output);
+ });
+ });
+ });
+});
+
+on('change:repeating_rangedweapons', function(event) {
+ if (event.sourceType === 'sheetworker' ) return;
+ const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
+ getSectionIDs('repeating_rangedweapons', function (ids) {
+ const fieldnames = [];
+ ids.forEach(id => fieldnames.push(
+ `repeating_rangedweapons_${id}_equippedrangedwep`,
+ `repeating_rangedweapons_${id}_magicrangedweaponbonus`,
+ `repeating_rangedweapons_${id}_rangedweapon`,
+ `repeating_rangedweapons_${id}_rangedabr`,
+ `repeating_rangedweapons_${id}_rangeddamage`,
+ `repeating_rangedweapons_${id}_weaponshortrange`,
+ `repeating_rangedweapons_${id}_weaponmediumrange`,
+ `repeating_rangedweapons_${id}_weaponlongrange`
+
+ ));
+ getAttrs(fieldnames, values => {
+ const output = {};
+ ids.forEach(id => {
+ const checkbox = parseInt(values[`repeating_rangedweapons_${id}_equippedrangedwep`]) || 0;
+ const magicbonus = parseInt(values[`repeating_rangedweapons_${id}_magicrangedweaponbonus`]) || 0;
+ const rangedweaponname = (values[`repeating_rangedweapons_${id}_rangedweapon`]) || None;
+ const rangedweaponabr = (values[`repeating_rangedweapons_${id}_rangedabr`]) || None;
+ const rangedweapondam = (values[`repeating_rangedweapons_${id}_rangeddamage`]) || None;
+ const shortrange = (values[`repeating_rangedweapons_${id}_weaponshortrange`]) || None;
+ const mediumrange = (values[`repeating_rangedweapons_${id}_weaponmediumrange`]) || None;
+ const longrange = (values[`repeating_rangedweapons_${id}_weaponlongrange`]) || None;
+
+ if(id.toLowerCase() === playerclickedid) {
+ output.magicrangedweaponbonus = checkbox ? magicbonus : 0;
+ output.rangedweapon = checkbox ? rangedweaponname : "None";
+ output.rangedabr = checkbox ? rangedweaponabr : "0d0";
+ output.rangeddamage = checkbox ? rangedweapondam : "0d0";
+ output.weaponshortrange = checkbox ? shortrange : 0;
+ output.weaponmediumrange = checkbox ? mediumrange : 0;
+ output.weaponlongrange = checkbox ? longrange : 0;
+ }
+ else if(checkbox) {
+ output[`repeating_rangedweapons_${id}_equippedrangedwep`] = 0;
+ }
+ setAttrs(output);
+ });
+ });
+ });
+});
+
+on('change:repeating_ammo', function(event) {
+ if (event.sourceType === 'sheetworker' ) return;
+ const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
+ getSectionIDs('repeating_ammo', function (ids) {
+ const fieldnames = [];
+ ids.forEach(id => fieldnames.push(
+ `repeating_ammo_${id}_equippedammo`,
+ `repeating_ammo_${id}_magicammobonus`,
+ `repeating_ammo_${id}_specialammomodifier`,
+ `repeating_ammo_${id}_specialammoabrmodifier`,
+ `repeating_ammo_${id}_specialammodmgmodifier`,
+ `repeating_ammo_${id}_ammotype`
+ ));
+ getAttrs(fieldnames, values => {
+ const output = {};
+ ids.forEach(id => {
+ const checkbox = parseInt(values[`repeating_ammo_${id}_equippedammo`]) || 0;
+ const magicbonus = parseInt(values[`repeating_ammo_${id}_magicammobonus`]) || 0;
+ const specialammomodifier = parseInt(values[`repeating_ammo_${id}_specialammomodifier`]) || 0;
+ const specialammoabrmodifier = parseInt(values[`repeating_ammo_${id}_specialammoabrmodifier`]) || 0;
+ const specialammodmgmodifier = parseInt(values[`repeating_ammo_${id}_specialammodmgmodifier`]) || 0;
+ const ammo = (values[`repeating_ammo_${id}_ammotype`]) || 0;
+
+ if(id.toLowerCase() === playerclickedid) {
+ output.magicammobonus = checkbox ? magicbonus : 0;
+ output.specialammomodifier = checkbox ? specialammomodifier : 0;
+ output.specialammoabrmodifier = checkbox ? specialammoabrmodifier : 0;
+ output.specialammodmgmodifier = checkbox ? specialammodmgmodifier : 0;
+ output.ammotype = checkbox ? ammo : "None";
+ }
+ else if(checkbox) {
+ output[`repeating_ammo_${id}_equippedammo`] = 0;
+ }
+ setAttrs(output);
+ });
+ });
+ });
+});
+
+on('change:specialammomodifier change:equippedammo change:equippedrangedwep change:equippedmeleewep change:shield change:attack change:defence change:magicammobonus change:magicrangedweaponbonus change:magicmeleeweaponbonus change:armourattackpenalty change:armourdefencepenalty change:magicshield sheet:opened', function() {
+ getAttrs(['specialammomodifier','shield','attack','defence','magicammobonus','magicrangedweaponbonus','magicmeleeweaponbonus','armourattackpenalty','armourdefencepenalty','magicshield'], function(v) {
let atk = parseInt(v.attack)||0;
let def = parseInt(v.defence)||0;
let ammo = parseInt(v.magicammobonus)||0;
+ let specialammo = parseInt(v.specialammomodifier)||0;
let ranged = parseInt(v.magicrangedweaponbonus)||0;
let melee = parseInt(v.magicmeleeweaponbonus)||0;
let armouratk = parseInt(v.armourattackpenalty)||0;
let armourdef = parseInt(v.armourdefencepenalty)||0;
let shieldequipped = parseInt(v.shield)||0;
if (shieldequipped === 1) {
- let shield = parseInt(v.magicshield)||0;}
+ shield = parseInt(v.magicshield)||0;
+ }
else {
shield = 0;
}
- let miscmeleea = parseInt(v.miscattackmelee)||0;
- let miscmeleed = parseInt(v.miscdefencemelee)||0;
- let miscrangeda = parseInt(v.miscattackranged)||0;
- let miscrangedd = parseInt(v.miscdefenceranged)||0;
- let basemeleeatk = (atk + melee - armouratk + miscmeleea);
- let basemeleedef = (def + melee - armourdef + shield + miscmeleed);
- let baserangedatk = (atk + ranged + ammo - armouratk + miscrangeda);
- let baserangeddef= (def - armourdef + shield + miscrangedd + shield);
+ let basemeleeatk = (atk + melee - armouratk);
+ let basemeleedef = (def + melee - armourdef + shield);
+ let baserangedatk = (atk + ranged + ammo + specialammo - armouratk);
+ let baserangeddef= (def - armourdef + shield);
+
setAttrs({
baserangedattack: baserangedatk,
baserangeddefence: baserangeddef,
@@ -39,314 +217,318 @@ on('change:equippedammo change:equippedrangedwep change:equippedmeleewep change:
});
});
-on('change:berserktoranged change:attack change:basemeleeattack change:basemeleedefence change:baserangedattack change:baserangeddefence change:defence change:rattackmodded change:rdefencemodded change:mattackmodded change:mdefencemodded change:berserkneg change:preciseneg change:stillnessneg change:bloodrageselect change:nonprofselect change:deathvowselect sheet:opened', function() {
- getAttrs(['berserktoranged','finalattack','finaldefence','basemeleedefence','basemeleeattack','baserangedattack','baserangeddefence','mdefencemodded','rattackmodded','rdefencemodded','mattackmodded','berserkneg','berserkpos','preciseneg','precisepos','stillnessneg','bloodrageselect','nonprofselect','deathvowselect'], function(v) {
- let bloodrage = parseInt(v.bloodrageselect) || 0;
- let berserkappliestoranged = parseInt(v.berserktoranged)||0;
+on('change:othermodifications change:armourpiercingselect change:masterbowmanselect change:penetratingshotmultiplier change:penetratingshotselect change:weaponskillselect change:shield change:expertparryselect change:guardcountered change:guardcurrent change:attack change:defence change:basemeleeattack change:basemeleedefence change:baserangedattack change:baserangeddefence change:evasion sheet:opened', function() {
+ getAttrs(['mattackmoda','mdefencemoda','rattackmoda','rdefencemoda','evasionmod','othermodifications','armourpiercingselect','armourpiercingmodifier','masterbowmanselect','masterbowmanmodifier','penetratingshotmultiplier','penetratingshotselect','weaponskillselect','weaponskillabrmodifier','guardabrmodifier','guarddamagemodifier','shield','expertparryselect','shieldsuccessvalue','shielddievalue','guardcountered','basemeleeattack','basemeleedefence','baserangedattack','baserangeddefence','evasion','guardcurrent'], function(value) {
- if (bloodrage === 1) {
- bloodragemod = parseInt(v.basemeleedefence) || 0;
- berserkattack = 0;
- berserkdefence = 0;
- mattackmod = parseInt(v.basemeleeattack)||0;
- mdefencemod= parseInt(v.basemeleedefence)||0;
- rattackmod = parseInt(v.baserangedattack)||0;
- rdefencemod = parseInt(v.baserangeddefence)||0;
+ const forms = {
+ Hawk: {mattackmoda: 1, mattackmodded: 1, mdefencemoda: -2, mdefencemodded: -2, rattackmoda: 1, rattackmodded: 1, rdefencemoda: -2, rdefencemodded: -2, evasionmod: 0, evasionmodded: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "If wielding a two-handed weapon: -1 Evasion and +1 Armour Penetration (please adjust manually)"},
+ Snake: {mattackmoda: 1, mattackmodded: 1, mdefencemoda: -3, mdefencemodded: -3, rattackmoda: 1, rattackmodded: 1, rdefencemoda: -3, rdefencemodded: -3, evasionmod: 0, evasionmodded: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "Critical Hits do +1 HP damage (please adjust manually)"},
+ Wolf: {mattackmoda: 2, mattackmodded: 2, mdefencemoda: -3, mdefencemodded: -3, rattackmoda: 2, rattackmodded: 2, rdefencemoda: -3, rdefencemodded: -3, evasionmod: -1, evasionmodded: -1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"},
+ Bear: {mattackmoda: -2, mattackmodded: -2, mdefencemoda: 1, mdefencemodded: 1, rattackmoda: -2, rattackmodded: -2, rdefencemoda: 1, rdefencemodded: 1, evasionmod: 0, evasionmodded: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "+1 additional Defence for each opponent beyond the first (Please enter in the Miscelaneous Modifiers Section manually)"},
+ Cat: {mattackmoda: -2, mattackmodded: -2, mdefencemoda: 1, mdefencemodded: 1, rattackmoda: -2, rattackmodded: -2, rdefencemoda: 1, rdefencemodded: 1, evasionmod: 1, evasionmodded: 1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "If using a shield: an additional -1 Attack and Shields block on a roll of 1 on 1d4 (these adjustments have been made for you)"},
+ Crab: {mattackmoda: -2, mattackmodded: -2, mdefencemoda: 2, mdefencemodded: 2, rattackmoda: -2, rattackmodded: -2, rdefencemoda: 2, rdefencemodded: 2, evasionmod: 0, evasionmodded: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"},
+ Neutral: {mattackmoda: 0, mattackmodded: 0, mdefencemoda: 0, mdefencemodded: 0, rattackmoda: 0, rattackmodded: 0, rdefencemoda: 0, rdefencemodded: 0, evasionmod: 0, evasionmodded: 0, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"},
+ Defensive: {mattackmoda: -2, mattackmodded: -2, mdefencemoda: 1, mdefencemodded: 1, rattackmoda: -2, rattackmodded: -2, rdefencemoda: 1, rdefencemodded: 1, evasionmod: 1, evasionmodded: 1, guarddamagemodifier: -1, guardabrmodifier: -1, othermodifications: "-1 Damage and -1 Armour Penetration (these adjustments have been made for you)"},
+ Offensive: {mattackmoda: 1, mattackmodded: 1, mdefencemoda: -2, mdefencemodded: -2, rattackmoda: 1, rattackmodded: 1, rdefencemoda: -2, rdefencemodded: -2, evasionmod: -1, evasionmodded: -1, guarddamagemodifier: 0, guardabrmodifier: 0, othermodifications: "None"}
+ };
+
+ let guac = parseInt(value.guardcountered)||0;
+ let gua = value.guardcurrent || 'Neutral';
+ const output = forms[gua] || forms.Neutral;
+
+ output.evasionmodded += parseInt(value.evasion) || 0;
+ output.evasionmod;
+ output.othermodifications == (value.othermodifications) || "None";
+
+ let shieldeq = parseInt(value.shield)||0;
+ let shielddie = (value.shielddievalue)||'1d6';
+ let shieldsuccess = parseInt(value.shieldsuccessvalue)||1;
+
+ let expertparry = parseInt(value.expertparryselect)||0;
+ let weaponskill = parseInt(value.weaponskillselect)||0;
+ let penetratingshot = parseInt(value.penetratingshotselect)||0;
+ let masterbowman = parseInt(value.masterbowmanselect)||0;
+ let armourpiercing = parseInt(value.armourpiercingselect)||0;
+
+ if (masterbowman === 1) {
+ output.masterbowmanmodifier = 1 || 0;
}
else {
- bloodragemod = 0;
- berserkattack = parseInt(v.berserkpos) || 0;
- berserkdefence = parseInt(v.berserkneg) || 0;
- rattackmod = parseInt(v.rattackmodded) || 0;
- rdefencemod = parseInt(v.rdefencemodded) || 0;
- mattackmod = parseInt(v.mattackmodded)||0;
- mdefencemod = parseInt(v.mdefencemodded)||0;
- nonprofmod = parseInt(v.nonprofselect) || 0;
- deathvowmod = parseInt(v.deathvowselect) || 0;
- preciseattack = parseInt(v.precisepos) || 0;
- precisedefence = parseInt(v.preciseneg) || 0;
- stillnessdefence = parseInt(v.stillnessneg) || 0;
- ;}
-
- let fmatk = (mattackmod + berserkattack - nonprofmod + deathvowmod + bloodragemod);
- let fmdef = (mdefencemod - berserkdefence - precisedefence - stillnessdefence - bloodragemod);
-
- if (berserkappliestoranged === 1) {
- fratk = (rattackmod + berserkattack - nonprofmod + deathvowmod + preciseattack)||0;
- frdef = (rdefencemod - berserkdefence - precisedefence - stillnessdefence)||0;
- }
+ output.masterbowmanmodifier = 0 || 0;
+ }
+
+ if (armourpiercing === 1) {
+ output.armourpiercingmodifier = 1 || 0;
+ }
else {
- fratk = (rattackmod - nonprofmod + deathvowmod + preciseattack)||0;
- frdef = (rdefencemod - berserkdefence - precisedefence - stillnessdefence)||0;
- }
-
- setAttrs({
- finalmeleeattack: parseInt(fmatk)||0,
- finalmeleedefence: parseInt(fmdef)||0,
- finalrangedattack: parseInt(fratk)||0,
- finalrangeddefence: parseInt(frdef)||0
+ output.armourpiercingmodifier = 0;
+ }
- });
- });
- });
+ if (weaponskill === 1) {
+ output.weaponskillabrmodifier = 1 || 0;
+ }
+ else {
+ output.weaponskillabrmodifier = 0;
+ }
- on('change:repeating_meleeweapons:equippedmeleewep', function(event) {
- if (event.sourceType === 'sheetworker' ) return;
- const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
- getSectionIDs('repeating_meleeweapons', function (ids) {
- const fieldnames = [];
- ids.forEach(id => fieldnames.push(
- `repeating_meleeweapons_${id}_equippedmeleewep`,
- `repeating_meleeweapons_${id}_magicmeleeweaponbonus`,
- `repeating_meleeweapons_${id}_meleeweapon`,
- `repeating_meleeweapons_${id}_meleeabr`,
- `repeating_meleeweapons_${id}_meleedamage`
-
- ));
- getAttrs(fieldnames, values => {
- const output = {};
- ids.forEach(id => {
- const checkbox = parseInt(values[`repeating_meleeweapons_${id}_equippedmeleewep`]) || 0;
- const magicbonus = parseInt(values[`repeating_meleeweapons_${id}_magicmeleeweaponbonus`]) || 0;
- const meleeweaponname = (values[`repeating_meleeweapons_${id}_meleeweapon`]) || None;
- const meleeweaponabr = (values[`repeating_meleeweapons_${id}_meleeabr`]) || None;
- const meleeweapondam = (values[`repeating_meleeweapons_${id}_meleedamage`]) || None;
-
- if(id.toLowerCase() === playerclickedid) {
- output.magicmeleeweaponbonus = checkbox ? magicbonus : 0;
- output.meleeweapon = checkbox ? meleeweaponname : "None";
- output.meleeabr = checkbox ? meleeweaponabr : "0d0";
- output.meleedamage = checkbox ? meleeweapondam : "0d0";
-
- } else if(checkbox) {
- output[`repeating_meleeweapons_${id}_equippedmeleewep`] = 0;
- }
- setAttrs(output);
- });
- });
- });
- });
+ if (penetratingshot === 1) {
+ output.penetratingshotabrmodifier = parseInt(value.penetratingshotmultiplier) || 0;
+ }
+ else {
+ output.penetratingshotabrmodifier = 0;
+ }
- on('change:repeating_rangedweapons:equippedrangedwep', function(event) {
- if (event.sourceType === 'sheetworker' ) return;
- const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
- getSectionIDs('repeating_rangedweapons', function (ids) {
- const fieldnames = [];
- ids.forEach(id => fieldnames.push(
- `repeating_rangedweapons_${id}_equippedrangedwep`,
- `repeating_rangedweapons_${id}_magicrangedweaponbonus`,
- `repeating_rangedweapons_${id}_rangedweapon`,
- `repeating_rangedweapons_${id}_rangedabr`,
- `repeating_rangedweapons_${id}_rangeddamage`,
- `repeating_rangedweapons_${id}_weaponshortrange`,
- `repeating_rangedweapons_${id}_weaponmediumrange`,
- `repeating_rangedweapons_${id}_weaponlongrange`
-
- ));
- getAttrs(fieldnames, values => {
- const output = {};
- ids.forEach(id => {
- const checkbox = parseInt(values[`repeating_rangedweapons_${id}_equippedrangedwep`]) || 0;
- const magicbonus = parseInt(values[`repeating_rangedweapons_${id}_magicrangedweaponbonus`]) || 0;
- const rangedweaponname = (values[`repeating_rangedweapons_${id}_rangedweapon`]) || None;
- const rangedweaponabr = (values[`repeating_rangedweapons_${id}_rangedabr`]) || None;
- const rangedweapondam = (values[`repeating_rangedweapons_${id}_rangeddamage`]) || None;
- const shortrange = (values[`repeating_rangedweapons_${id}_weaponshortrange`]) || None;
- const mediumrange = (values[`repeating_rangedweapons_${id}_weaponmediumrange`]) || None;
- const longrange = (values[`repeating_rangedweapons_${id}_weaponlongrange`]) || None;
-
- if(id.toLowerCase() === playerclickedid) {
- output.magicrangedweaponbonus = checkbox ? magicbonus : 0;
- output.rangedweapon = checkbox ? rangedweaponname : "None";
- output.rangedabr = checkbox ? rangedweaponabr : "0d0";
- output.rangeddamage = checkbox ? rangedweapondam : "0d0";
- output.weaponshortrange = checkbox ? shortrange : 0;
- output.weaponmediumrange = checkbox ? mediumrange : 0;
- output.weaponlongrange = checkbox ? longrange : 0;
-
- } else if(checkbox) {
- output[`repeating_rangedweapons_${id}_equippedrangedwep`] = 0;
- }
- setAttrs(output);
- });
- });
- });
- });
-
- on('change:repeating_ammo:equippedammo', function(event) {
- if (event.sourceType === 'sheetworker' ) return;
- const playerclickedid = (event.sourceAttribute.split('_')[2] || '').toLowerCase();
- getSectionIDs('repeating_ammo', function (ids) {
- const fieldnames = [];
- ids.forEach(id => fieldnames.push(
- `repeating_ammo_${id}_equippedammo`,
- `repeating_ammo_${id}_magicammobonus`,
- `repeating_ammo_${id}_ammotype`
-
- ));
- getAttrs(fieldnames, values => {
- const output = {};
- ids.forEach(id => {
- const checkbox = parseInt(values[`repeating_ammo_${id}_equippedammo`]) || 0;
- const magicbonus = parseInt(values[`repeating_ammo_${id}_magicammobonus`]) || 0;
- const ammo = (values[`repeating_ammo_${id}_ammotype`]) || 0;
-
- if(id.toLowerCase() === playerclickedid) {
- output.magicammobonus = checkbox ? magicbonus : 0;
- output.ammotype = checkbox ? ammo : "None";
-
- } else if(checkbox) {
- output[`repeating_ammo_${id}_equippedammo`] = 0;
- }
- setAttrs(output);
- });
- });
- });
- });
-
- on('change:strength', function() {
- getAttrs(['strength','meleedmgbonus','meleeabrbonus'], function(value) {
-
- let str = parseInt(value.strength)||0;
-
- if (str < 5) {
- output.maxenc = 6;
- output.meleeabrbonus = 0 || 0;
- output.meleedmgbonus = 0 || 0;
- }
- else if (str < 8) {
- output.maxenc = 8;
- output.meleeabrbonus = 0 || 0;
- output.meleedmgbonus = 0 || 0;
-
- }
- else if (str < 12) {
- output.maxenc = 10;
- output.meleeabrbonus = 0 || 0;
- output.meleedmgbonus = 0 || 0;
-
- }
- else if (str < 15) {
- output.maxenc = 12;
- output.meleeabrbonus = 0 || 0;
- output.meleedmgbonus = 0 || 0;
-
- }
- else if (str < 18) {
- output.maxenc = 14;
- output.meleeabrbonus = 1 || 0;
- output.meleedmgbonus = 1 || 0;
+ if (gua === "Cat") {
+ shielddie = '1d4';
+ shieldsuccess = 1;
+ }
+ else if (expertparry === 1) {
+ shielddie = '1d10';
+ shieldsuccess = 2;
+ }
+ else {
+ shielddie = '1d6';
+ shieldsuccess = 1;
+ }
+ output.shielddievalue = shielddie;
+ output.shieldsuccessvalue = shieldsuccess;
+ if (guac === 1 && gua !== "Neutral") {
+ if (gua === "Hawk" || gua === "Snake" || gua === "Wolf") {
+ output.mattackmodded += (parseInt(value.basemeleeattack)-2) || 0;
+ output.mattackmoda-2;
+ output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
+ output.mdefencemoda;
+ output.rattackmodded += (parseInt(value.baserangedattack)-2) || 0;
+ output.rattackmoda-2;
+ output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
+ output.rdefencemoda;
+ }
+ else if (gua === "cat" && shieldeq === 1) {
+ output.mattackmodded += (parseInt(value.basemeleeattack)-1) || 0;
+ output.mattackmoda-1;
+ output.mdefencemodded += (parseInt(value.basemeleedefence)-2) || 0;
+ output.mdefencemoda-2;
+ output.rattackmodded += parseInt(value.baserangedattack)-1 || 0;
+ output.rattackmoda;
+ output.rdefencemodded += (parseInt(value.baserangeddefence)-2) || 0;
+ output.rdefencemoda-2;
}
else {
- output.maxenc = 14;
- output.meleeabrbonus = 1 || 0;
- output.meleedmgbonus = 1 || 0;
+ output.mattackmodded += parseInt(value.basemeleeattack) || 0;
+ output.mattackmoda;
+ output.mdefencemodded += (parseInt(value.basemeleedefence)-2) || 0;
+ output.mdefencemoda-2;
+ output.rattackmodded += parseInt(value.baserangedattack) || 0;
+ output.rattackmoda;
+ output.rdefencemodded += (parseInt(value.baserangeddefence)-2) || 0;
+ output.rdefencemoda-2;
+ }
+ }
+ else if (gua === "Cat" && shieldeq === 1) {
+ output.mattackmodded += (parseInt(value.basemeleeattack)-1) || 0;
+ output.mattackmoda-1;
+ output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
+ output.mdefencemoda;
+ output.rattackmodded += (parseInt(value.baserangedattack)-1) || 0;
+ output.rattackmoda-1;
+ output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
+ output.rdefencemoda;
+ }
+ else {
+ output.mattackmodded += parseInt(value.basemeleeattack) || 0;
+ output.mattackmoda;
+ output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
+ output.mdefencemoda;
+ output.rattackmodded += parseInt(value.baserangedattack) || 0;
+ output.rattackmoda;
+ output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
+ output.rdefencemoda;
+ }
+
+ setAttrs(output);
+
+ });
+ });
+
+ on('change:miscattackmelee change:miscdefencemelee change:miscattackranged change:miscdefenceranged change:mainguacheactive change:berserktoranged change:attack change:basemeleeattack change:basemeleedefence change:baserangedattack change:baserangeddefence change:defence change:rattackmodded change:rdefencemodded change:mattackmodded change:mdefencemodded change:berserkneg change:preciseneg change:stillnessneg change:bloodrageselect change:nonprofselect change:deathvowselect sheet:opened', function() {
+ getAttrs(['mainguachedefence','mainguacheactive','berserktoranged','finalattack','finaldefence','basemeleedefence','basemeleeattack','baserangedattack','baserangeddefence','mdefencemodded','rattackmodded','rdefencemodded','mattackmodded','berserkneg','berserkpos','preciseneg','precisepos','stillnessneg','bloodrageselect','nonprofselect','deathvowselect','miscattackmelee','miscdefencemelee','miscattackranged','miscdefenceranged'], function(v) {
+ let bloodrage = parseInt(v.bloodrageselect) || 0;
+ let berserkappliestoranged = parseInt(v.berserktoranged)||0;
+ let mainguache = parseInt(v.mainguacheactive)||0;
+
+ if (bloodrage === 1) {
+ bloodragemod = parseInt(v.basemeleedefence) || 0;
+ bloodragedmgmod = 1;
+ berserkattack = 0;
+ berserkdefence = 0;
+ mainguachedefence = 0;
+ nonprofmod = 0;
+ deathvowmod = 0;
+ preciseattack = 0;
+ precisedefence = 0;
+ stillnessdefence = 0;
+ mattackmod = parseInt(v.basemeleeattack)||0;
+ mdefencemod= parseInt(v.basemeleedefence)||0;
+ rattackmod = parseInt(v.baserangedattack)||0;
+ rdefencemod = parseInt(v.baserangeddefence)||0;
+ }
+ else if (mainguache === 2) {
+ mainguachedefence = parseInt(v.basemeleedefence) || 0;
+ berserkattack = 0;
+ berserkdefence = 0;
+ mattackmod = parseInt(v.mattackmodded)||0;
+ mdefencemod= parseInt(v.basemeleedefence)||0;
+ rattackmod = parseInt(v.rattackmodded) || 0;
+ rdefencemod = parseInt(v.rdefencemodded) || 0;
+ nonprofmod = 0;
+ deathvowmod = 0;
+ preciseattack = 0;
+ precisedefence = 0;
+ stillnessdefence = 0;
+ }
+ else if (mainguache === 1) {
+ berserkattack = 0;
+ berserkdefence = 0;
+ rattackmod = parseInt(v.rattackmodded) || 0;
+ rdefencemod = parseInt(v.rdefencemodded) || 0;
+ mattackmod = parseInt(v.mattackmodded)||0;
+ mdefencemod = parseInt(v.mdefencemodded)||0;
+ nonprofmod = 0;
+ deathvowmod = 0;
+ preciseattack = 0;
+ precisedefence = 0;
+ stillnessdefence = 0;
+ mainguachedefence = -2;
+ }
+ else {
+ bloodragemod = 0;
+ bloodragedmgmod = 0;
+ berserkattack = parseInt(v.berserkpos) || 0;
+ berserkdefence = parseInt(v.berserkneg) || 0;
+ rattackmod = parseInt(v.rattackmodded) || 0;
+ rdefencemod = parseInt(v.rdefencemodded) || 0;
+ mattackmod = parseInt(v.mattackmodded)||0;
+ mdefencemod = parseInt(v.mdefencemodded)||0;
+ nonprofmod = parseInt(v.nonprofselect) || 0;
+ deathvowmod = parseInt(v.deathvowselect) || 0;
+ preciseattack = parseInt(v.precisepos) || 0;
+ precisedefence = parseInt(v.preciseneg) || 0;
+ stillnessdefence = parseInt(v.stillnessneg) || 0;
+ mainguachedefence = 0;
+ }
+
+ let miscmeleea = parseInt(v.miscattackmelee)||0;
+ let miscmeleed = parseInt(v.miscdefencemelee)||0;
+ let miscrangeda = parseInt(v.miscattackranged)||0;
+ let miscrangedd = parseInt(v.miscdefenceranged)||0;
+
+ let fmatk = (mattackmod + berserkattack - nonprofmod + deathvowmod + bloodragemod + miscmeleea);
+ let fmdef = (mdefencemod - berserkdefence - precisedefence - stillnessdefence - bloodragemod - mainguachedefence + miscmeleed);
+
+ if (berserkappliestoranged === 1) {
+ fratk = (rattackmod + berserkattack - nonprofmod + deathvowmod + preciseattack + miscrangeda)||0;
+ frdef = (rdefencemod - berserkdefence - precisedefence - stillnessdefence + miscrangedd)||0;
}
- setAttrs(output);
+ else {
+ fratk = (rattackmod - nonprofmod + deathvowmod + preciseattack + miscrangeda)||0;
+ frdef = (rdefencemod - berserkdefence - precisedefence - stillnessdefence + miscrangedd)||0;
+ }
+
+ setAttrs({
+ bloodragedmgmod: bloodragedmgmod,
+ finalmeleeattack: parseInt(fmatk)||0,
+ finalmeleedefence: parseInt(fmdef)||0,
+ finalrangedattack: parseInt(fratk)||0,
+ finalrangeddefence: parseInt(frdef)||0
});
});
-
+ });
+
+ on('change: miscabrmelee change:miscdamagemelee change:miscabrranged change:miscdamageranged change:meleeabrbonus change:magicmeleeweaponbonus change:weaponskillabrmodifier change:armourpiercingmodifier change:weaponskillabrmodifier change:guardabrmodifier change:guarddamagemodifier change:meleedmgbonus change:magicammobonus change:magicrangedweaponbonus change:specialammoabrmodifier change:specialammodmgmodifier change:penetratingshotabrmodifier change:armourpiercingmodifier change:masterbowmanmodifier change:bloodragedmgmod', function() {
+ getAttrs(['miscabrmelee','miscdamagemelee','miscabrranged','miscdamageranged','meleeabrbonus','magicmeleeweaponbonus','weaponskillabrmodifier','armourpiercingmodifier','weaponskillabrmodifier','guardabrmodifier','guarddamagemodifier','meleedmgbonus','magicammobonus','magicrangedweaponbonus','specialammoabrmodifier','specialammodmgmodifier','penetratingshotabrmodifier','armourpiercingmodifier','masterbowmanmodifier','bloodragedmgmod'], function(v) {
+ let meleeabrbonus = parseInt(v.meleeabrbonus)||0;
+ let magicmeleeweaponbonus = parseInt(v.magicmeleeweaponbonus)||0;
+ let weaponskillabrmodifier = parseInt(v.weaponskillabrmodifier)||0;
+ let armourpiercingmodifier = parseInt(v.armourpiercingmodifier)||0;
+ let guardabrmodifier = parseInt(v.guardabrmodifier)||0;
+ let meleedmgbonus = parseInt(v.meleedmgbonus)||0;
+ let guarddamagemodifier = parseInt(v.guarddamagemodifier)||0;
+ let magicammobonus = parseInt(v.magicammobonus)||0;
+ let magicrangedweaponbonus = parseInt(v.magicrangedweaponbonus)||0;
+ let specialammoabrmodifier = parseInt(v.specialammoabrmodifier)||0;
+ let penetratingshotabrmodifier = parseInt(v.penetratingshotabrmodifier)||0;
+ let masterbowmanmodifier = parseInt(v.masterbowmanmodifier)||0;
+ let specialammodmgmodifier = parseInt(v.specialammodmgmodifier)||0;
+ let bloodragedmgmod = parseInt(v.bloodragedmgmod)||0;
+ let miscabrmelee = parseInt(v.miscabrmelee)||0;
+ let miscdamagemelee = parseInt(v.miscdamagemelee)||0;
+ let miscabrranged = parseInt(v.miscabrranged)||0;
+ let miscdamageranged = parseInt(v.miscdamageranged)||0;
-on('change:rank sheet:opened', function() {
- getAttrs(['pfc','rank','espchance','premonitionchance'], function(value) {
- let rank = parseInt(value.rank)||0;
- let psycfatcheck = rank + 13;
- let esp = 5 + rank * 3;
- let prem = 35 + rank * 2;
- setAttrs({
- pfc: psycfatcheck,
- espchance: esp,
- premonitionchance: prem
+ let fmeleeabrbonus = (miscabrmelee + meleeabrbonus + magicmeleeweaponbonus + weaponskillabrmodifier + armourpiercingmodifier + guardabrmodifier);
+ let fmeleedmgbonus = (miscdamagemelee + magicmeleeweaponbonus + meleedmgbonus + guarddamagemodifier + bloodragedmgmod);
+ let frangedabrbonus = (miscabrranged + guardabrmodifier + magicammobonus + magicrangedweaponbonus + specialammoabrmodifier + penetratingshotabrmodifier + masterbowmanmodifier + armourpiercingmodifier);
+ let frangeddmgbonus = (miscdamageranged + guarddamagemodifier + magicammobonus + magicrangedweaponbonus + specialammodmgmodifier + bloodragedmgmod);
+
+ setAttrs({
+ finalmeleeabrbonus: parseInt(fmeleeabrbonus)||0,
+ finalmeleedmgbonus: parseInt(fmeleedmgbonus)||0,
+ finalrangedabrbonus: parseInt(frangedabrbonus)||0,
+ finalrangeddmgbonus: parseInt(frangeddmgbonus)||0
});
});
});
-
- on('change:strength change:weaponskillselect change:shield change:expertparryselect change:guardcountered change:guardcurrent change:attack change:defence change:basemeleeattack change:basemeleedefence change:baserangedattack change:baserangeddefence change:evasion sheet:opened', function() {
- getAttrs(['weaponskillselect','strength','rangedabrbonus','rangeddmgbonus','meleedmgbonus','meleeabrbonus','shield','expertparryselect','shieldsuccessvalue','shielddievalue','guardcountered','basemeleeattack','basemeleedefence','baserangedattack','baserangeddefence','evasion','guardcurrent'], function(value) {
-
- const forms = {
- Hawk: {mattackmodded: 1, mdefencemodded: -2, rattackmodded: 1, rdefencemodded: -2, evasionmodded: 0, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "If wielding a two-handed weapon: -1 Evasion and +1 Armour Penetration"},
- Snake: {mattackmodded: 1, mdefencemodded: -3, rattackmodded: 1, rdefencemodded: -3, evasionmodded: 0, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "Critical Hits do +1 HP damage"},
- Wolf: {mattackmodded: 2, mdefencemodded: -3, rattackmodded: 2, rdefencemodded: -3, evasionmodded: -1, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "None"},
- Bear: {mattackmodded: -2, mdefencemodded: 1, rattackmodded: -2, rdefencemodded: 1, evasionmodded: 0, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "+1 additional Defence for each opponent beyond the first (enter in the Miscelaneous Modifiers Section manually)"},
- Cat: {mattackmodded: -2, mdefencemodded: 1, rattackmodded: -2, rdefencemodded: 1, evasionmodded: 1, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "If using a shield: an additional -1 Attack and Shields block on a roll of 1 on 1d4"},
- Crab: {mattackmodded: -2, mdefencemodded: 2, rattackmodded: -2, rdefencemodded: 2, evasionmodded: 0, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "None"},
- Neutral: {mattackmodded: 0, mdefencemodded: 0, rattackmodded: 0, rdefencemodded: 0, evasionmodded: 0, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "None"},
- Defensive: {mattackmodded: -2, mdefencemodded: 1, rattackmodded: -2, rdefencemodded: 1, evasionmodded: 1, meleeabrbonus: -1, meleedmgbonus: -1, rangedabrbonus: -1, rangeddmgbonus: -1, othermodifications: "-1 Damage and -1 Armour Penetration"},
- Offensive: {mattackmodded: 1, mdefencemodded: -2, rattackmodded: 1, rdefencemodded: -2, evasionmodded: -1, meleeabrbonus: 0, meleedmgbonus: 0, rangedabrbonus: 0, rangeddmgbonus: 0, othermodifications: "None"}
-
- };
- let guac = parseInt(value.guardcountered)||0;
- let gua = value.guardcurrent || 'Neutral';
- const output = forms[gua] || forms.Neutral;
+ on('change:finalstrength', function() {
+ getAttrs(['finalstrength','meleedmgbonus','meleeabrbonus'], function(value) {
- let shieldeq = parseInt(value.shield)||0;
- let shielddie = (value.shielddievalue)||'1d6';
- let shieldsuccess = parseInt(value.shieldsuccessvalue)||1;
+ let str = parseInt(value.finalstrength)||0;
+ let maxenc = parseInt(value.maxenc)||0;
+ let meleeabrbonus = parseInt(value.meleeabrbonus)||0;
+ let meleedmgbonus = parseInt(value.meleeadmgbonus)||0;
- let expertparry = parseInt(value.expertparryselect)||0;
- let weaponskill = parseInt(value.weaponskillselect)||0;
- let str = parseInt(value.strength)||0;
-
- if (gua === "Cat") {
- shielddie = '1d4';
- shieldsuccess = 1;
- }
- else if (expertparry === 1) {
- shielddie = '1d10';
- shieldsuccess = 2;
- }
+ if (str <= 5) {
+ maxenc = 6;
+ meleeabrbonus = 0;
+ meleedmgbonus = 0;
+ }
+ else if (str <= 8) {
+ maxenc = 8;
+ meleeabrbonus = 0;
+ meleedmgbonus = 0;
+ }
+ else if (str <= 12) {
+ maxenc = 10;
+ meleeabrbonus = 0;
+ meleedmgbonus = 0;
+ }
+ else if (str <= 15) {
+ maxenc = 12;
+ meleeabrbonus = 0;
+ meleedmgbonus = 0;
+ }
+ else if (str <= 18) {
+ maxenc = 14;
+ meleeabrbonus = 1;
+ meleedmgbonus = 1;
+ }
else {
- shielddie = '1d6';
- shieldsuccess = 1;
- }
-
- if (guac === 1 && gua !== "Neutral") {
- if (gua === "Hawk" || gua === "Snake" || gua === "Wolf") {
- output.mattackmodded += (parseInt(value.basemeleeattack)-2) || 0;
- output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
- output.rattackmodded += (parseInt(value.baserangedattack)-2) || 0;
- output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
- }
- else if (gua === "cat" && shieldeq === 1) {
- output.mattackmodded += (parseInt(value.basemeleeattack)-1) || 0;
- output.mdefencemodded += (parseInt(value.basemeleedefence)-2) || 0;
- output.rattackmodded += parseInt(value.baserangedattack)-1 || 0;
- output.rdefencemodded += (parseInt(value.baserangeddefence)-2) || 0;
- }
- else {
- output.mattackmodded += parseInt(value.basemeleeattack) || 0;
- output.mdefencemodded += (parseInt(value.basemeleedefence)-2) || 0;
- output.rattackmodded += parseInt(value.baserangedattack) || 0;
- output.rdefencemodded += (parseInt(value.baserangeddefence)-2) || 0;
- }
- }
- else if (gua === "Cat" && shieldeq === 1) {
- output.mattackmodded += (parseInt(value.basemeleeattack)-1) || 0;
- output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
- output.rattackmodded += (parseInt(value.baserangedattack)-1) || 0;
- output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
+ maxenc = 14;
+ meleeabrbonus = 2;
+ meleedmgbonus = 2;
}
- else {
- output.mattackmodded += parseInt(value.basemeleeattack) || 0;
- output.mdefencemodded += parseInt(value.basemeleedefence) || 0;
- output.rattackmodded += parseInt(value.baserangedattack) || 0;
- output.rdefencemodded += parseInt(value.baserangeddefence) || 0;
- }
-
- output.evasionmodded += parseInt(value.evasion) || 0;
- output.othermodifications = (value.othermodifications) || "None";
- output.shielddievalue = shielddie;
- output.shieldsuccessvalue = shieldsuccess;
-
- setAttrs(output);
- });
- });
-on('change:mdefencemodded change:berserkneg ', () => {
+ setAttrs({
+ meleeabrbonus: meleeabrbonus,
+ meleedmgbonus: meleedmgbonus,
+ maxenc: maxenc
+ });
+ });
+ });
+
+on('change:berserkneg ', () => {
getAttrs(['berserkneg', 'mdefencemodded', 'rdefencemodded'], v=> {
const stats = ['berserk'];
const output = {};
@@ -364,7 +546,7 @@ on('change:mdefencemodded change:berserkneg ', () => {
});
});
-on('change:rdefencemodded change:preciseneg change:stilnessneg', () => {
+on('change:preciseneg change:stillnessneg', () => {
getAttrs(['preciseneg', 'stillnessneg','rdefencemodded'], v=> {
const stats = ['precise', 'stillness'];
const output = {};
@@ -380,61 +562,61 @@ on('change:rdefencemodded change:preciseneg change:stilnessneg', () => {
setAttrs(output, {silent:true});
});
});
-
-on('change:guardstomeleeonly change:attack change:basemeleeattack change:basemeleedefence change:baserangedattack change:baserangeddefence change:defence change:mattackmodded change:mdefencemodded change:rattackmodded change:rdefencemodded change:berserkneg change:preciseneg change:stillnessneg change:bloodrageselect change:nonprofselect change:deathvowselect sheet:opened', function() {
- getAttrs(['guardstomeleeonly','finalattack','finaldefence','basemeleedefence','basemeleeattack','baserangedattack','baserangeddefence','rdefencemodded','rattackmodded', 'mdefencemodded','mattackmodded','berserkneg','berserkpos','preciseneg','precisepos','stillnessneg','bloodrageselect','nonprofselect','deathvowselect'], function(v) {
- let bloodrage = parseInt(v.bloodrageselect)||0;
- let restrictedguards = parseInt(v.guardstomeleeonly)||0;
- if (restrictedguards === 1) {
- rattackmod = parseInt(v.baserangedattack)||0;
- rdefencemod = parseInt(v.baserangeddefence)||0;
- mattackmod = parseInt(v.mattackmodded)||0;
- mdefencemod = parseInt(v.mdefencemodded)||0;
- nonprofmod = parseInt(v.nonprofselect) || 0;
- deathvowmod = parseInt(v.deathvowselect) || 0;
- preciseattack = parseInt(v.precisepos) || 0;
- precisedefence = parseInt(v.preciseneg) || 0;
- stillnessdefence = parseInt(v.stillnessneg) || 0;
- }
- else if (bloodrage === 1) {
- bloodragemod = parseInt(v.basemeleedefence) || 0;
- berserkattack = 0;
- berserkdefence = 0;
- mattackmod = parseInt(v.basemeleeattack)||0;
- mdefencemod= parseInt(v.basemeleedefence)||0;
- rattackmod = parseInt(v.baserangedattack)||0;
- rdefencemod = parseInt(v.baserangeddefence)||0;
- }
- else {
- mattackmod = parseInt(v.mattackmodded) || 0;
- mdefencemod = parseInt(v.mdefencemodded) || 0;
- rattackmod = parseInt(v.rattackmodded) || 0;
- rdefencemod = parseInt(v.rdefencemodded) || 0;
- bloodragemod = 0;
- berserkattack = parseInt(v.berserkpos) || 0;
- berserkdefence = parseInt(v.berserkneg) || 0;
- nonprofmod = parseInt(v.nonprofselect) || 0;
- deathvowmod = parseInt(v.deathvowselect) || 0;
- preciseattack = parseInt(v.precisepos) || 0;
- precisedefence = parseInt(v.preciseneg) || 0;
- stillnessdefence = parseInt(v.stillnessneg) || 0;
- }
+on('change:magicalattack change:magicaldefence change:miscmagicattack change:miscmagicdefence change:stillnesspos change:evasionmodded change:evasion change:miscevasion change:stealth change:perception change:miscstealth change:miscperception change:af change:magicafbonus change:miscaf change:strength change:reflexes change:intelligence change:psychictalent change:looks change:miscstrength change:miscreflexes change:miscintelligence change:miscpsychictalent change:misclooks sheet:opened', function(event) {
+ getAttrs(['magicalattack','magicaldefence','miscmagicattack','miscmagicdefence','finalevasion','finalstealth','finalperception','stillnesspos','evasionmodded','evasion','miscevasion','stealth','perception','miscstealth','miscperception','finalstrength','finalreflexes','finalintelligence','finalpsychictalent','finallooks','totalaf','af','magicafbonus','miscaf','strength','reflexes','intelligence','psychictalent','looks','miscstrength','miscreflexes','miscintelligence','miscpsychictalent','misclooks'], function(v) {
+ let af = parseInt(v.af);
+ let magicaf = parseInt(v.magicafbonus);
+ let miscaf = parseInt(v.miscaf);
+ let str = parseInt(v.strength);
+ let ref = parseInt(v.reflexes);
+ let int = parseInt(v.intelligence);
+ let psy = parseInt(v.psychictalent);
+ let lks = parseInt(v.looks);
+ let mstr = parseInt(v.miscstrength);
+ let mref = parseInt(v.miscreflexes);
+ let mint = parseInt(v.miscintelligence);
+ let mpsy = parseInt(v.miscpsychictalent);
+ let mlks = parseInt(v.misclooks);
+ let bstl = parseInt(v.stealth);
+ let bper = parseInt(v.perception);
+ let mstl = parseInt(v.miscstealth);
+ let pstl = parseInt(v.stillnesspos)||0;
+ let mper = parseInt(v.miscperception);
+ let beva = parseInt(v.evasionmodded);
+ let meva = parseInt(v.miscevasion);
+ let maa = parseInt(v.magicalattack);
+ let mde = parseInt(v.magicaldefence);
+ let mmaa = parseInt(v.miscmagicattack);
+ let mmde = parseInt(v.miscmagicdefence);
- let fmatk = mattackmod + berserkattack - nonprofmod + deathvowmod + bloodragemod;
- let fmdef = mdefencemod - berserkdefence - precisedefence - stillnessdefence - bloodragemod;
- let fratk = rattackmod + berserkattack - nonprofmod + deathvowmod + preciseattack;
- let frdef = rdefencemod - berserkdefence - precisedefence - stillnessdefence;
-
- setAttrs({
- finalmeleeattack: parseInt(fmatk)||0,
- finalmeleedefence: parseInt(fmdef)||0,
- finalrangedattack: parseInt(fratk)||0,
- finalrangeddefence: parseInt(frdef)||0
+ let fstr = str + mstr;
+ let fref = ref + mref;
+ let fint = int + mint;
+ let fpsy = psy + mpsy;
+ let flks = lks + mlks;
+ let faf = (af + magicaf + miscaf);
+ let fstl = (bstl + mstl + pstl);
+ let fper = bper + mper;
+ let feva = beva + meva;
+ let fmaa = maa + mmaa;
+ let fmde = mde + mmde;
- });
+ setAttrs({
+ finalstrength: fstr,
+ finalreflexes: fref,
+ finalintelligence: fint,
+ finalpsychictalent: fpsy,
+ finallooks: flks,
+ totalaf: faf,
+ finalstealth: fstl,
+ finalperception: fper,
+ finalevasion: feva,
+ finalmagicalattack: fmaa,
+ finalmagicaldefence: fmde
+ });
});
- });
+});
const woundValues = ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30"];
woundValues.forEach(function(value) {
@@ -517,84 +699,29 @@ on("clicked:termp_reset", function() {
});
});
-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;
+on('change:rank sheet:opened', function() {
+ getAttrs(['pfc','rank','espchance','premonitionchance'], function(value) {
+ let rank = parseInt(value.rank)||0;
+ let psycfatcheck = rank + 13;
+ let esp = 5 + rank * 3;
+ let prem = 35 + rank * 2;
+ setAttrs({
+ pfc: psycfatcheck,
+ espchance: esp,
+ premonitionchance: prem
+ });
+ });
});
- getSectionIDs(`repeating_${section}`, idArray => {
- const attrArray = idArray.reduce((m, id) => [...m, ...(fields_trimmed.map(field => `repeating_${section}_${id}_${field}`))], []);
- getAttrs([...attrArray, ...Object.keys(properties.attributes)], v => {
- const getValue = (section, id, field) => v[`repeating_${section}_${id}_${field}`] === 'on' ? 1 : parseFloat(v[`repeating_${section}_${id}_${field}`]) || 0;
- const commonMultipliers = (fields.length <= destinations.length) ? [] : fields.splice(destinations.length, fields.length - destinations.length);
- const output = destinations.reduce((obj, destination, index) => {
- let sumTotal = idArray.reduce((total, id) => total + getValue(section, id, fields_trimmed[index]) * commonMultipliers.reduce((subtotal, mult) => subtotal * ((!mult.includes(':') || mult.split(':')[1].split(',').includes(fields_trimmed[index])) ? getValue(section, id, mult.split(':')[0]) : 1), 1), 0);
- sumTotal *= (properties.options.hasOwnProperty('multiplier') && Object.keys(properties.options.multiplier).includes(fields_trimmed[index])) ? (parseFloat(properties.options.multiplier[fields_trimmed[index]]) || 0): 1;
- sumTotal += Object.entries(properties.attributes).reduce((total, [key, value]) =>
- total += (value.hasOwnProperty(fields_trimmed[index]) ? parseFloat(v[key] || 0) * (parseFloat(value[fields_trimmed[index]]) || 1): 0) , 0);
- checks.roundtypes.forEach(type => {
- if (properties.options.hasOwnProperty(type)) {
- if (Object.keys(properties.options[type]).includes(fields_trimmed[index])) {
- sumTotal = getRounded(type, sumTotal, (+properties.options[type][fields_trimmed[index]] || 0));
- } else if (properties.options[type] == '0' || !isNaN(+properties.options[type] || 'x') ) {
- sumTotal = getRounded(type, sumTotal, +properties.options[type]);
- }
- }
- });
- obj[destination] = sumTotal;
- return obj;
- }, {});
- setAttrs(output);
- });
- });
-};
-on("change:repeating_meleeweapons remove:repeating_meleeweapons sheet:opened", function() {
-repeatingSum("totalweapons", "weapons", "weaponweight");
-});
-
-on("change:repeating_rangedweapons remove:repeating_rangedweapons sheet:opened", function() {
- repeatingSum("totalweapons", "weapons", "weaponweight");
- });
-
-on("change:repeating_ammo remove:repeating_ammo sheet:opened", function() {
-repeatingSum("ammoweight", "ammo", "ammoqty");
-});
-
-on("change:gc change:sf change:cp sheet:opened", function() {
- getAttrs(["gc","sf", "cp"], function(value) {
- let gc = parseFloat(value.GC)||0;
- let sf = parseFloat(value.SF)||0;
- let cp = parseFloat(value.CP)||0;
- });
-});
-
-on("change:repeating_inventoryitems remove:repeating_inventoryitems change:gc change:sf change:cp change:totalweapons change:ammoweight change:shield sheet:opened", function() {
-repeatingSum("totalencumbrance", "inventoryitems", ["inventoryqty", "encumbrancevalue"], "gc:1/150", "sf:1/150", "cp:1/150", "ammoweight:1/12", "totalweapons", "shield", "round");
-});
+ on("change:repeating_inventoryitems remove:repeating_inventoryitems change:gc change:sf change:cp change:repeating_meleeweapons remove:repeating_meleeweapons change:repeating_rangedweapons remove:repeating_rangedweapons change:repeating_ammo remove:repeating_ammo change:shield sheet:opened", function() {
+ repeatingSum("totalmeleeweaponweight", "meleeweapons", "meleeweaponweight");
+ repeatingSum("totalrangedweaponweight", "rangedweapons", "rangedweaponweight");
+ repeatingSum("ammoweight", "ammo", "ammoqty");
+ getAttrs(["gc","sf", "cp"], function(value) {
+ let gc = parseFloat(value.GC)||0;
+ let sf = parseFloat(value.SF)||0;
+ let cp = parseFloat(value.CP)||0;
+ });
+
+ repeatingSum("totalencumbrance", "inventoryitems", ["inventoryqty", "encumbrancevalue"], "gc:1/150", "sf:1/150", "cp:1/150", "ammoweight:1/12", "totalmeleeweaponweight", "totalrangedweaponweight", "shield", "round");
+ });
\ No newline at end of file
diff --git a/Dragon Warriors/Dragon Warriors Revised HomeBrew.html b/Dragon Warriors/Dragon Warriors Revised HomeBrew.html
new file mode 100644
index 0000000000..23a705f846
--- /dev/null
+++ b/Dragon Warriors/Dragon Warriors Revised HomeBrew.html
@@ -0,0 +1,1765 @@
+
+
+
+ Character
+ Inventory
+ Combat
+ Magic
+ Skills
+ Languages
+ Biography
+ Documentation
+
+
+
+
+
+
+ Name
+ Profession
+ (Pick One)
+ Knight
+ Barbarian
+ Sorcerer
+ Mystic
+ Elementalist
+ Warlock
+ Assassin
+ Knave
+ Hunter
+ Priest
+ Demonologist
+
+ Rank
+ Experience
+
+
+
Characteristics
+
Strength
+
Reflexes
+
Intelligence
+
Psychic Talent
+
Looks
+
+
+
Base Combat Factors
+
Attack
+
Defence
+
+
+
Dodging
+
Base Evasion
+
+
+
Base Magical Combat Factors
+
Magical Attack
+
Magical Defence
+
+
+
Base Stealth and Perception
+
Stealth
+
Perception
+
+
+
Health Points
+
Maximum Health Points
+
Wounds Taken:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Heal!
+
+
+
Armour
+
Type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Advanced Guards
+
+ Guard Taken
+ Neutral (0)
+ Hawk (1)
+ Snake (2)
+ Wolf (3)
+ Bear (4)
+ Cat (5)
+ Crab (6)
+
+ Melee Attack:
+ Melee Defence:
+ Ranged Attack:
+ Ranged Defence:
+
+ Evasion:
+ Other Modifications:
+
+
+
Magic
+
+ Direct Magical Attack
+ Indirect Magical Attack
+
+
+
+ Spell Expiry Check
+
+
+ Spell Expiry Check
+
+
+
Magic Points:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Refresh!
+
+
+ Psychic Fatigue Check: - spell level
+ ESP %
+ Premonition %
+
+
+
+
Magic Points:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Refresh!
+
Magic Points:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Refresh!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Elemental Specialisms
+
+
Primary Element
+
+ (Pick One)
+ Earth (moonset)
+ Air (noon)
+ Water (moonrise)
+ Fire (sunrise)
+ Darkness (sunset)
+
+
Secondary Element
+
+ (Pick One)
+ Earth (moonset)
+ Air (noon)
+ Water (moonrise)
+ Fire (sunrise)
+
+
Secondary Element
+
+ (Pick One)
+ Earth (moonset)
+ Air (noon)
+ Water (moonrise)
+ Fire (sunrise)
+
+
+
+
Magic Points
+
Magic Points
+
Magic Points Used:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Refresh!
+
+
+
+
Element Max
+
Magic Points Used:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Refresh!
+
+
Element Max
+
Magic Points Used:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Refresh!
+
+
+
+
+
+ Mystic Magic
+ Psychic Fatigue Check: - spell level
+ ESP %
+ Premonition %
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This character sheet includes material based on the Dragon Warriors setting, as created by and copyright (c) Dave Morris and Oliver Johnson, and used according to the terms of the Serpent King Games Fan Policy. We are not permitted to charge you to use or access this content. This character sheet is not published, endorsed, or officially approved by Serpent King Games. For more information about Dragon Warriors products and Serpent King Games, please visit www.serpentking.com
+ Serpent King Games expects you to use the Dragon Warriors setting responsibly and legally. That means avoiding associating the setting with extreme graphic violence, explicit sexual content, hate speech against any particular real-world segment of society, or anything else that does not present Dragon Warriors in a positive light.
+ If you have any questions about Dragon Warriors, or the conditions of use of this character sheet, please email info@serpentking.com
+ Most of the images used on the character sheet come directly from the Dragon Warriors books.
+ The image used to represent Magic Points named "effect" and was created by ATOM and sourced from the Noun Project.
+ A huge shoutout to Roll20 forums member GiGs, without whom this sheet would not have been built.
+ Release Notes
+ Ver 1.2.1
+ Bug fixes and Sheet Roll updates
+ Fixed and Added:
+ Encumberance was not calculating properly due to an old Sheet Worker, fixed.
+ Sheet rolls were unprofessional looking, they have been updated to use roll templates. Thanks to @SouthernSkies on the Dragon Warriors Discord server for his assistance with this.
+ PFC sheet roll was not working at all, fixed.
+ ESP and Premonition checks were dependent on an API, this requirement has been removed for the published version. If you are a Pro Subscriber, I suggest that you install the "Blind Roll" API and create the following macros:
+ ESP "!broll 1d100<@{espchance}"
+ Premonition "!broll 1d100<@{premonitionchance}"
+
+ Ver 1.2
+ Total Overhaul Update
+ Fixed and Added:
+ Major changes to layout, and corrected font style for inputs
+ Added artworks
+ Corrected problems with Elementalist MP sections
+ Fixed issues with Mystic's Psychic Fatigue field
+ Added Combat page to track all changes to Attack and Defence scores through guards, profession abilities and equipment modifiers
+ Changed the button image on wounds and mana points trackers
+ Added wound counters to track Health Points down to -1, -2 and -3 (wounds tracker for Macros does not take these into account, but they are not relevant for KO/shock calculations anyway)
+ Added a magic bonus section to weapons and shields for applying bonuses to combat attributes.
+ Added 'equipped' value to weapons selection to ensure only a single weapon's magic bonuses applies at a time.
+ Modified the Armour Factor area to be more specific.
+ Added sheet rolls for attacks, attribute checks and other basic game roll functions
+ Further code stream-lining.
+
+ Ver 1.1
+ Fixed and Added:
+ Missing Languages added and literacy checkbox default value fixed
+ Slight remodel of the front page to incorporate new elements
+ Sheet Worker now rounds off encumberance, and calculates total (including equipment, coins, weapons and shield) and maximum encumbrance values
+ Added a quantity field for inventory items
+ Added an ammunition section underneath the Weapons
+ Wounds checkboxes have been updated, the number of radioboxes available is set to equal a character's max HP. The sheet can calculate remaining HP based on the wounds counter.
+ Show/hide magic sections (front page and magic page) dependant on profession selected from the dropdown list
+ Major code tidy up
+
+ Bugs to work out:
+ None known, let me know if you see one so I can squash it!
+
+ Features still to add:
+
+
+
+
\ No newline at end of file
diff --git a/Dragon Warriors/Dragon Warriors Revised.css b/Dragon Warriors/Dragon Warriors Revised.css
index 5f112e3aa9..27af8e7b86 100644
--- a/Dragon Warriors/Dragon Warriors Revised.css
+++ b/Dragon Warriors/Dragon Warriors Revised.css
@@ -1174,7 +1174,7 @@ button.sheet-m3dot > span {
height: auto;
grid-template-columns: 29% 34% 36%;
grid-template-rows: auto;
- grid-template-areas: "common common common" "attributes afattributes finalcombatattributes" "atkdefattributes hpattributes finalcombatattributes" "evaattribute hpattributes finalcombatattributes" "mamdattributes mpattributes classcombatabilities" "steperattributes mpattributes classcombatabilities";
+ grid-template-areas: "common common common" "attributes afattributes finalcombatattributes" "atkdefattributes hpattributes finalcombatattributes" "evaattribute hpattributes finalcombatattributes" "mamdattributes mpattributes classcombatabilities" "steperattributes mpattributes classcombatabilities" "gapfillimg mpattributes classcombatabilities";
}
.sheet-inventory {
width: auto;
@@ -1194,14 +1194,14 @@ button.sheet-m3dot > span {
height: auto;
grid-template-columns: 34% 64%;
grid-template-rows: auto;
- grid-template-areas: "manabox spellbox";
+ grid-template-areas: "allprofessionattribs spellbox" "allcastermana spellbox" "manabox spellbox";
}
.sheet-skills {
width: auto;
height: auto;
grid-template-columns: auto;
grid-template-rows: auto;
- grid-template-areas: "professionskills" "secondaryskills";
+ grid-template-areas: "paths" "professionskills" "secondaryskills";
}
.sheet-languages {
width: auto;
@@ -1278,6 +1278,10 @@ button.sheet-m3dot > span {
border-style: double;
border-width: 6px;
}
+.sheet-gapfillimg {
+ display: grid;
+ grid-area: gapfillimg;
+}
.sheet-attributes {
grid-area: attributes;
border-style: double;
@@ -1340,7 +1344,7 @@ label.sheet-charheading {
border-width: 6px;
justify-content: space-around;
display: grid;
- grid-template-areas: "cfheading cfheading" "cf1 cfa" "finalmeleelabel1 finalmeleebox1" "finalrangedlabel1 finalrangedbox1" "cf2 cfd" "finalmeleelabel2 finalmeleebox2" "finalrangedlabel2 finalrangedbox2";
+ grid-template-areas: "cfheading cfheading" "finalmeleelabel1 finalmeleebox1" "finalrangedlabel1 finalrangedbox1" "finalmeleelabel2 finalmeleebox2" "finalrangedlabel2 finalrangedbox2";
}
.sheet-finalmeleelabel1 {
grid-area: finalmeleelabel1;
@@ -1478,7 +1482,7 @@ label.sheet-mcfheading {
border-width: 6px;
justify-content: space-around;
display: grid;
- grid-template-areas: "steperheading steperheading steperheading " "steper1 stealth ." "steper3 finalstealth button1" "steper2 percep ." "steper4 finalperception button2";
+ grid-template-areas: "steperheading steperheading steperheading " "steper3 finalstealth button1" "steper4 finalperception button2";
}
label.sheet-steperheading {
grid-area: steperheading;
@@ -1691,9 +1695,6 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-mpattributeshidd
.sheet-guardother1 {
grid-area: guardother1;
}
-.sheet-allcasterattribs {
- grid-template-areas: "finmagatk finmagatkbox" "finmagdef finmagdefbox";
-}
.sheet-castermp {
justify-content: space-between;
grid-template-areas: "dma1 dmabutton1" "ima1 imabutton1" "ser1 serbutton1";
@@ -1808,11 +1809,6 @@ button.sheet-serbutton2 {
.sheet-frontmp {
display: none;
}
-input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-allcasterattribs,
-input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-allcasterattribs,
-input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-allcasterattribs,
-input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-allcasterattribs,
-input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-allcasterattribs,
input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-castermp,
input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-castermp,
input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-castermp,
@@ -1826,6 +1822,11 @@ input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-standardmp,
input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-standardmp {
display: grid;
}
+.sheet-paths {
+ grid-area: paths;
+ border-style: double;
+ border-width: 6px;
+}
.sheet-professionskills {
grid-area: professionskills;
border-style: double;
@@ -1853,7 +1854,7 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-standardmp {
border-style: double;
border-width: 6px;
justify-content: space-around;
- grid-template-areas: " aflabel1 aflabel1" "armourtypelabel1 armourtypebox1" "armourfactorlabel1 armourfactorbox1" "armourmagiclabel1 armourmagicbox1" "nonprofarmourheader1 nonprofarmourheader1" "nonprofarmourpenaltylabel1 nonprofarmourpenaltybox1" "nonprofarmourpenaltylabel2 nonprofarmourpenaltybox2" " nonprofarmourpenaltylabel3 nonprofarmourpenaltybox3" "shieldcol1 shieldcol1";
+ grid-template-areas: " aflabel1 aflabel1" "armourtypelabel1 armourtypebox1" "armourfactorlabel1 armourfactorbox1" "armourmagiclabel1 armourmagicbox1" "colstatlabel9 colstatmodbox9" "nonprofarmourheader1 nonprofarmourheader1" "nonprofarmourpenaltylabel1 nonprofarmourpenaltybox1" "nonprofarmourpenaltylabel2 nonprofarmourpenaltybox2" " nonprofarmourpenaltylabel3 nonprofarmourpenaltybox3" "shieldcol1 shieldcol1";
}
.sheet-aflabel1 {
grid-area: aflabel1;
@@ -1962,6 +1963,15 @@ input.sheet-shield-toggle[value="1"] ~ div.sheet-shieldhidden1 {
border-width: 6px;
}
/*define Magic tab children*/
+.sheet-allprofessionattribs {
+ grid-area: allprofessionattribs;
+ border-style: double;
+ border-width: 6px;
+ justify-content: space-between;
+ display: grid;
+ grid-template-areas: "magattribheader magattribheader" "mcf2 mcfmd" "magmod2 magbox2" "magfmod2 magfbox2";
+}
+
.sheet-manabox {
grid-area: manabox;
border-style: double;
@@ -1972,14 +1982,17 @@ input.sheet-shield-toggle[value="1"] ~ div.sheet-shieldhidden1 {
border-style: double;
border-width: 6px;
}
+.sheet-allcastermana{
+ border-style: double;
+ border-width: 6px;
+ justify-content: space-between;
+ display: grid; grid-template-areas: "magattribheader magattribheader" "mcf1 mcfma" "magmod1 magbox1" "magfmod1 magfbox1";
+}
+
/*define which elements should be shown, based on profession*/
.sheet-mana {
display: none;
}
-.sheet-allcastermana{
- justify-content: space-between;
- grid-template-areas: "magattribheader magattribheader" "magmod1 magbox1" "magfmod1 magfbox1" "magmod2 magbox2" "magfmod2 magfbox2"
-}
.sheet-magmod1 {
grid-area: magmod1;
}
@@ -2067,11 +2080,12 @@ label.sheet-magattribheader {
grid-area: serbutton4;
justify-content: space-around;
}
-input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-allcastermana,
-input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-allcastermana,
-input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-allcastermana,
-input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-allcastermana,
-input.sheet-profession-toggle[value="Warlock"] ~ div.sheet-allcastermana,
+input.sheet-profession-toggle[value="Knight"] ~ div.sheet-notacaster,
+input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-notacaster,
+input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-notacaster,
+input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-notacaster,
+input.sheet-profession-toggle[value="Knave"] ~ div.sheet-notacaster,
+input.sheet-profession-toggle[value="Priest"] ~ div.sheet-notacaster,
input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-castermana,
input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-castermana,
input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-castermana,
@@ -2089,6 +2103,12 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-standardmana {
.sheet-spells {
display: none;
}
+input.sheet-profession-toggle[value="Knight"] ~ div.sheet-noncaster,
+input.sheet-profession-toggle[value="Barbarian"] ~ div.sheet-noncaster,
+input.sheet-profession-toggle[value="Assassin"] ~ div.sheet-noncaster,
+input.sheet-profession-toggle[value="Knave"] ~ div.sheet-noncaster,
+input.sheet-profession-toggle[value="Hunter"] ~ div.sheet-noncaster,
+input.sheet-profession-toggle[value="Priest"] ~ div.sheet-noncaster,
input.sheet-profession-toggle[value="Sorcerer"] ~ div.sheet-list,
input.sheet-profession-toggle[value="Mystic"] ~ div.sheet-list,
input.sheet-profession-toggle[value="Elementalist"] ~ div.sheet-list,
@@ -2173,7 +2193,7 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-list {
border-width: 6px;
justify-content: space-around;
display: grid;
- grid-template-areas: "misccharacteristicheading misccharacteristicheading misccharacteristicheading" "colhead1 colhead2 colhead3" "colstatlabel4 colstatmodbox4 colstatfinal4" "colstatlabel5 colstatmodbox5 colstatfinal5" "colstatlabel6 colstatmodbox6 colstatfinal6" "colstatlabel7 colstatmodbox7 colstatfinal7" "colstatlabel8 colstatmodbox8 colstatfinal8";
+ grid-template-areas: "misccharacteristicheading misccharacteristicheading misccharacteristicheading" "colhead1 colhead3 colhead2" "colstatlabel4 colstatfinal4 colstatmodbox4" "colstatlabel5 colstatfinal5 colstatmodbox5" "colstatlabel6 colstatfinal6 colstatmodbox6" "colstatlabel7 colstatfinal7 colstatmodbox7" "colstatlabel8 colstatfinal8 colstatmodbox8";
}
.sheet-misccharacteristicheading {
grid-area: misccharacteristicheading;
@@ -2214,7 +2234,7 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-list {
border-width: 6px;
justify-content: space-around;
display: grid;
- grid-template-areas: "miscotherheading miscotherheading" "colhead1 colhead2" "colstatlabel1 colstatmodbox1" "colstatlabel2 colstatmodbox2" "colstatlabel3 colstatmodbox3" "colstatlabel9 colstatmodbox9";
+ grid-template-areas: "miscotherheading miscotherheading miscotherheading" "colhead1 colhead2 colhead3" "cf1 cfa colstatlabel10" "cf2 cfd colstatlabel20" "colstatlabel1 stealth colstatmodbox1" "colstatlabel2 percep colstatmodbox2" "colstatlabel3 evade colstatmodbox3";
}
.sheet-miscotherheading {
grid-area: miscotherheading;
@@ -2231,6 +2251,12 @@ input.sheet-profession-toggle[value="Demonologist"] ~ div.sheet-list {
.sheet-colstatlabel2 {
grid-area: colstatlabel2;
}
+.sheet-colstatlabel10 {
+ grid-area: colstatlabel10;
+}
+.sheet-colstatlabel20 {
+ grid-area: colstatlabel20;
+}
.sheet-colstatlabel3 {
grid-area: colstatlabel3;
}
diff --git a/Dragon Warriors/Dragon Warriors Revised.html b/Dragon Warriors/Dragon Warriors Revised.html
index 938eb0e759..4336401b63 100644
--- a/Dragon Warriors/Dragon Warriors Revised.html
+++ b/Dragon Warriors/Dragon Warriors Revised.html
@@ -2,10 +2,10 @@
Character
- Miscellaneous Modifiers
- Inventory
+ Base Scores
Magic
- Skills
+ Inventory
+ Paths and Skills
Languages
Biography
Documentation
@@ -33,41 +33,35 @@
Characteristics
-
Strength
-
Reflexes
-
Intelligence
-
Psychic Talent
-
Looks
+
Strength
+
Reflexes
+
Intelligence
+
Psychic Talent
+
Looks
Combat Factors
-
Attack
-
Modified Melee
-
Modified Ranged
-
Defence
-
Modified Melee
-
Modified Ranged
+
Melee Attack
+
Ranged Attack
+
Melee Defence
+
Ranged Defence
Dodging
-
Base Evasion
-
Modified
+
Evasion
Magical Combat Factors
-
Magical Attack
-
Modified
-
Magical Defence
-
Modified
+
Magical Attack
+
Magical Defence
Stealth and Perception
-
Stealth
-
Modified
-
Perception
-
Modified
+
Stealth
+
Perception
+
Health Points
Maximum Health Points
@@ -237,38 +231,35 @@
- Heal!
+ Heal!
+ Poison Save
@@ -280,7 +271,7 @@
Defence Penalty:
- Attack Bonus
+ Attack Bonus
Check this box to apply Berserk bonuses to both melee and ranged attacks.
Activate Bloodrage
@@ -305,8 +296,8 @@
- Modifiers: Melee Attack:
- Melee Defence:
- Ranged Attack:
- Ranged Defence:
- Evasion:
+ Modifiers: Melee Attack:
+ Melee Defence:
+ Ranged Attack:
+ Ranged Defence:
+ Evasion:
Other Effects:
@@ -344,11 +335,11 @@
Offensive (8)
Defensive (7)
- Modifiers: Melee Attack:
- Melee Defence:
- Ranged Attack:
- Ranged Defence:
- Evasion:
+ Modifiers: Melee Attack:
+ Melee Defence:
+ Ranged Attack:
+ Ranged Defence:
+ Evasion:
Other Effects:
@@ -364,11 +355,11 @@
Crab (6)
Guard Countered?
- Modifiers: Melee Attack:
- Melee Defence:
- Ranged Attack:
- Ranged Defence:
- Evasion:
+ Modifiers: Melee Attack:
+ Melee Defence:
+ Ranged Attack:
+ Ranged Defence:
+ Evasion:
Other Effects:
@@ -384,10 +375,6 @@
Indirect Magical Attack
Spell Expiry Roll
-
-
Final Magical Attack
-
Final Magical Defence
-
Magic Points:
Miscellaneous Modifiers - Melee Combat
@@ -979,12 +967,13 @@
Damage
-
Miscellaneous Modifiers - Other Attributes
-
Attribute
Modifier
-
Stealth
-
Perception
-
Evasion
-
Armour Factor
+
Base Factors
+
Attribute
Base Attribute
Modifier
+
Attack
See Below
+
Defence
See Below
+
Stealth
+
Perception
+
Evasion
@@ -1015,15 +1004,21 @@
+
+
+
Base Score
+
Modifier
+
Final
+
+
+
+
Base Score
+
Modifier
+
Final
+
-
-
-
Magical Attack - Miscelaneous Modifier
-
Final Score
-
Magical Defence - Miscelaneous Modifier
-
Final Score
-
+
Direct Magical Attack
Indirect Magical Attack
@@ -1550,6 +1545,7 @@
+
Spells of Rank 1
@@ -1625,10 +1621,15 @@
+
+ Path Taken
+ Name
+ Description
+
Profession Skills
- Skill
+ Skill
Description
@@ -1747,6 +1748,18 @@
The image used to represent Magic Points named "effect" and was created by ATOM and sourced from the Noun Project.
A huge shoutout to Roll20 forums member GiGs, without whom this sheet would not have been built.
Release Notes
+
Ver 1.2.2
+ Layout fixes, Bug fixes
+
Fixed and Added:
+ Fixed error preventing Precise Shot modifiers from being applied to rolls.
+ Spinners removed from read-only boxes to avoid confusion.
+ Have moved base score inputs (all) to the renamed tab "Base Scores" (formerly Miscelaneous Modifiers).
+ Removed ABR / DMG bonus boxes from front sheet as unnecessary.
+ Moved AF misc bonus to the AF section of the Inventory page.
+ Opened up base Magic Stats on the Magic page for all classes.
+ Changed tab name from "Skills" to "Path and Skills" and added a paths box.
+ Added a classic DW picture to the front page to reduce strange spacing issues after taking out unnecessary input boxes.
+ Poison save roll button added under health points
Ver 1.2.1
Layout changes, Bug fixes and Sheet Roll updates
Fixed and Added:
@@ -1794,6 +1807,9 @@
None known, let me know if you see one so I can squash it!
Features still to add:
+ Change Attribute names so that making custom Macro Calls for end users is easier to work.
+ Change the way wound counts are processed to allow better token integration.
+ Need to streamline Sheet Workers in the code to reduce overall attribute calls (looking for experience JS coders for some help here!).
@@ -2244,7 +2260,7 @@
});
});
- on('change: miscabrmelee change:miscdamagemelee change:miscabrranged change:miscdamageranged change:meleeabrbonus change:magicmeleeweaponbonus change:weaponskillabrmodifier change:armourpiercingmodifier change:weaponskillabrmodifier change:guardabrmodifier change:guarddamagemodifier change:meleedmgbonus change:magicammobonus change:magicrangedweaponbonus change:specialammoabrmodifier change:specialammodmgmodifier change:penetratingshotabrmodifier change:armourpiercingmodifier change:masterbowmanmodifier change:bloodragedmgmod', function() {
+ on('change:miscabrmelee change:miscdamagemelee change:miscabrranged change:miscdamageranged change:meleeabrbonus change:magicmeleeweaponbonus change:weaponskillabrmodifier change:armourpiercingmodifier change:weaponskillabrmodifier change:guardabrmodifier change:guarddamagemodifier change:meleedmgbonus change:magicammobonus change:magicrangedweaponbonus change:specialammoabrmodifier change:specialammodmgmodifier change:penetratingshotabrmodifier change:armourpiercingmodifier change:masterbowmanmodifier change:bloodragedmgmod', function() {
getAttrs(['miscabrmelee','miscdamagemelee','miscabrranged','miscdamageranged','meleeabrbonus','magicmeleeweaponbonus','weaponskillabrmodifier','armourpiercingmodifier','weaponskillabrmodifier','guardabrmodifier','guarddamagemodifier','meleedmgbonus','magicammobonus','magicrangedweaponbonus','specialammoabrmodifier','specialammodmgmodifier','penetratingshotabrmodifier','armourpiercingmodifier','masterbowmanmodifier','bloodragedmgmod'], function(v) {
let meleeabrbonus = parseInt(v.meleeabrbonus)||0;
let magicmeleeweaponbonus = parseInt(v.magicmeleeweaponbonus)||0;
diff --git a/Dragon Warriors/scrollNoBG.png b/Dragon Warriors/scrollNoBG.png
new file mode 100644
index 0000000000..d6a07eafaf
Binary files /dev/null and b/Dragon Warriors/scrollNoBG.png differ
diff --git a/Dragon Warriors/untitled folder/.DS_Store b/Dragon Warriors/untitled folder/.DS_Store
new file mode 100644
index 0000000000..5008ddfcf5
Binary files /dev/null and b/Dragon Warriors/untitled folder/.DS_Store differ