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 @@ +
+
+ Dragon Warriors
+ + + + + + + + +
+ + + +
+
+ Name + Profession + Rank + Experience +
+
+ +
Strength
+
Reflexes
+
Intelligence
+
Psychic Talent
+
Looks
+
+
+ +
Attack
+
Defence
+
+
+ +
Base Evasion
+
+
+ +
Magical Attack
+
Magical Defence
+
+
+ +
Stealth

+
Perception
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + +
+
+ Shield +
+
+ + + + +
+
+
+
+
+ + + + Equipped Weapon:
+ ABR
+ Damage
+ Sword +
+ + + + Equipped Weapon: +
+ Ammunition Type: +
+ ABR +
+ Damage +
+
+
+
+
+
+ Range:
Short
Medium
Long

+
+
+ Bow +
+
+ + Final Melee Attack +
+ Final Melee Defence +
+

+ + Final Ranged Attack +
+ Final Ranged Defence +
+
+ +
+ +
+ No Magic Attributes +
+
+ + + Guard Taken + + + + + + + +
+
+ +
+ Direct Magical Attack
+ Indirect Magical Attack
+
+ +
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+
+ +
+ Item + Location + Quantity + Encumbrance Value +
+
+
+
+ +
+ + + +
+
+ Coin Chest +
+
+ + +
+
+ + Type +
+ Armour Factor           Magic Bonus +

+ + Attack Penalty +
+ Defence Penalty +
+ Stealth Penalty +


+
+
+ Helmed Skull +
+
+ Shield Equipped? +
+ Magic Bonus +
+ Shield Die +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ + Magic Bonus + Armour Bypass Roll + Damage + Equipped + +
+ +
+ + Magic Bonus + Armour Bypass Roll + Damage + Equipped +
+ Short + Medium + Long + +
+ +
+ Ammunition Type + Quantity + Magic Bonus + Special Attack Modifier + Special ABR Modifier + Special Damage Modifier + Equipped + +
+
+
+
+ +
+ + +
+
+ Encumbrance +
+
+
+
+ +
+
+ + + + + + + + +
+
+ + + + + + + + +
+
+ +
+ + + + + + +
+
+ + + +
+ + + +
+ + +
+ +
+ +
+
+
+ +
+ + Berserk Defence Penalty: Attack Bonus +
+ + +
+ +
+
+ + Activated abilities apply without regard to rules restrictions, for example Weaponskill applies a bonus to all Armour Bypass rolls while active. Manual control is required. + Activate Expert Parry
+ Activate Weaponskill
+
Activate Main Guache: Inactive Defensive Offensive

+ Activate Master Bowman +
+
+ + Activated abilities apply without regard to rules restrictions, the Non-Proficiency penalty applies all rolls while active. Manual control is required. + Activate Non-Proficient Weapon +
+
+ + Activated abilities apply without regard to rules restrictions. Armour Piercing applies a bonus to all Armour Bypass rolls while active. Manual control is required. + Activate Armour Peircing + Activate Deathvow +
+
+ + Activated abilities apply without regard to rules restrictions, for example Penetrating Shot applies a bonus to all Ranged Armour Bypass rolls while active. Manual control is required. + Precise Shot Defence Penalty Attack Bonus +
+ Stillness Defence Penalty Stealth Bonus
+
Penetrating Shot Skill Level: None Once Twice

+ Activate Penetrating Shot +
+
+ No Magic Attributes +
+ +
+
+ + + Final Melee Attack + Final Melee Defence + +
+ + Final Ranged Attack + Final Ranged Defence + +

+ Equipped Melee Weapon: + ABR + Damage + +
+ + Shield Equipped?       + Shield Die + + + +

+ + Equipped Ranged Weapon: + ABR + Damage + +
+ + Equipped Ammunition Type: +
+ Special Ammunition Modifiers: Attack + Armour Bypass + Damage +
+
+ + Ranges: Short + Medium + Long + +
+
+
+
+ +
+
+ +
+ + The Elements: Earth, Air, Fire, Water, Darkness + +
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + +
+ +
+
+ +
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+ +
+ Name + Range + Duration
+ Description
+
+
+
+
+ +
+
+ +
+ Skill + Description
+
+
+
+ +
+ Skill + Level
+ Description
+
+
+
+ +
+
+ +
+ Language + Fluency Level + Literate? + Script +
+
+
+ +
+ Language + Fluency Level + Literate? + Script +
+
+
+
+
+ + + + + + + + + + + +
+
+ +
+ 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.

+ + + Bug fixes and Sheet Roll updates

+ + 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}"
+ + + Total Overhaul Update

+ + 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.
+
+ + + 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
+
+ + None known, let me know if you see one so I can squash it!
+
+ +
+
+ + \ 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 @@
Dragon Warriors
- - + - + + @@ -33,41 +33,35 @@
-
Strength
-
Reflexes
-
Intelligence
-
Psychic Talent
-
Looks
+
Strength
+
Reflexes
+
Intelligence
+
Psychic Talent
+
Looks
-
Attack
-
Modified Melee
-
Modified Ranged


-
Defence
-
Modified Melee
-
Modified Ranged
+
Melee Attack
+
Ranged Attack

+
Melee Defence
+
Ranged Defence
-
Base Evasion
-
Modified
+
Evasion
-
Magical Attack
-
Modified
-
Magical Defence
-
Modified
+
Magical Attack
+
Magical Defence
-
Stealth
-
Modified

-
Perception
-
Modified

+
Stealth

+
Perception

+
Dice Warriors
@@ -237,38 +231,35 @@
- +
+ Poison Save
Shield
-


+


-
Roll
on
+
Roll
on
Equipped Weapon:
ABR
-
ABR Bonus
Damage
-
Damage Bonus
Sword
Equipped Weapon:
Ammunition Type:
ABR
-
ABR Bonus
Damage
-
Damage Bonus
Ranges:
-
Short
-
Medium
-
Long

+
Short
+
Medium
+
Long

Bow
@@ -280,7 +271,7 @@
Berserk:
Defence Penalty:
-
Attack Bonus

+
Attack Bonus


Activate Bloodrage
@@ -305,8 +296,8 @@
- Precise Shot:
Defence Penalty
Attack Bonus

- Stillness:
Defence Penalty
Stealth Bonus

+ Precise Shot:
Defence Penalty
Attack Bonus

+ Stillness:
Defence Penalty
Stealth Bonus

Penetrating Shot Skill Level:
None Once Twice

@@ -323,11 +314,11 @@
-
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
+
Modifiers:
Melee Attack:

+
Melee Defence:
+
Ranged Attack:
+
Ranged Defence:
+
Evasion:
@@ -344,11 +335,11 @@ -
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
+
Modifiers:
Melee Attack:

+
Melee Defence:
+
Ranged Attack:
+
Ranged Defence:
+
Evasion:
@@ -364,11 +355,11 @@
-
Modifiers:
Melee Attack:

-
Melee Defence:
-
Ranged Attack:
-
Ranged Defence:
-
Evasion:
+
Modifiers:
Melee Attack:

+
Melee Defence:
+
Ranged Attack:
+
Ranged Defence:
+
Evasion:
@@ -384,10 +375,6 @@


-
-
Final Magical Attack
-
Final Magical Defence

-
@@ -931,6 +918,7 @@
Type
Armour Factor
Magic Bonus

+
Armour Factor
Non-Proficiency Penalties:
Attack
Defence
@@ -954,13 +942,13 @@
-
-
Final Score
-
Strength
-
Reflexes
-
Intelligence
-
Psychic Talent
-
Looks
+
+
Base Score
+
Strength
+
Reflexes
+
Intelligence
+
Psychic Talent
+
Looks
@@ -979,12 +967,13 @@
Damage
-
-
-
Stealth
-
Perception
-
Evasion
-
Armour Factor
+
+
Base Attribute
+
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

-
+
Sword
Direct Magical Attack
Indirect Magical Attack
@@ -1550,6 +1545,7 @@
+
Scroll
@@ -1625,10 +1621,15 @@
+
+ + Name
+ Description +
- 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.

+ + Layout fixes, Bug fixes + + 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
Layout changes, Bug fixes and Sheet Roll updates

@@ -1794,6 +1807,9 @@ None known, let me know if you see one so I can squash it!

+ 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