From 3191766a52a1907b20da44a4f3d48d9bb004d297 Mon Sep 17 00:00:00 2001 From: morepurplemorebetter Date: Sat, 29 May 2021 23:32:43 +0200 Subject: [PATCH] v13.0.6-beta2 final commit * Saving throws on the companion page can display the values from the main character, instead of calculated values * Fix setting class automation to manual if the class field is empty * Fix Firearms other weapon proficiency not working * Move removing upcasting from spell short desccription to its own function, so it can be called from other locations (e.g. calcChanges) --- _functions/Functions1.js | 7 ++++++- _functions/Functions2.js | 2 +- _functions/FunctionsSpells.js | 16 ++++++++++++---- _variables/ListsClasses.js | 12 ++++++------ .../_common attributes.js | 3 ++- ...ature, wild shape option (CreatureList).js | 19 +++++++++++++++++++ 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/_functions/Functions1.js b/_functions/Functions1.js index e3e2a964..6ee5d6a8 100644 --- a/_functions/Functions1.js +++ b/_functions/Functions1.js @@ -4332,6 +4332,11 @@ function CalcSave() { var prefix = QI ? "" : getTemplPre(event.target.name, "AScomp", true); var Sabi = QI ? 4 : 21 + prefix.length; var Ability = Save.substring(0, Sabi - 1).slice(-3); + if (prefix && CurrentCompRace[prefix] && CurrentCompRace[prefix].savesLinked) { + // copy the total from the first page, ignoring any modifiers on this page + event.value = What(Ability + " ST Mod"); + return; + } var Mod = What(Save.substring(0, Sabi) + "Mod"); //get the proficiency bonus if applicable @@ -6212,7 +6217,7 @@ function SetToManual_Button(noDialog) { if (SetToManual_Dialog.mCla) { var classString = What("Class and Levels"); if (classes.parsed.length < 2 && classString.indexOf(classes.totallevel) == -1) classString += " " + classes.totallevel; - CurrentVars.manual.classes = What("Class and Levels"); + CurrentVars.manual.classes = What("Class and Levels") + " "; Hide("Class Features Menu"); } else { var newClassValue = What("Class and Levels"); diff --git a/_functions/Functions2.js b/_functions/Functions2.js index 8bc5bce1..449830e3 100644 --- a/_functions/Functions2.js +++ b/_functions/Functions2.js @@ -5943,7 +5943,7 @@ function isProficientWithWeapon(WeaponName, theWea) { return true; // No need to check further for natural weapons, spells, and 'alwaysprof' } else if ((theWea.type.toLowerCase() == "simple" && tDoc.getField("Proficiency Weapon Simple").isBoxChecked(0)) || (theWea.type.toLowerCase() == "martial" && tDoc.getField("Proficiency Weapon Martial").isBoxChecked(0))) { return true; // Proficient with the relevant type (simple/martial) - } else if (CurrentProfs.weapon.otherWea && RegExp(";(" + CurrentProfs.weapon.otherWea.finalProfs.join("s?|").replace(/ss\?\|/g, "s?|") + ");", "i").test(";" + [WeaponName, theWea.type].concat(theWea.list ? [theWea.list] : []).concat(theWea.baseWeapon ? [theWea.baseWeapon] : []).join(";") + ";")) { + } else if (CurrentProfs.weapon.otherWea && RegExp(";(" + (CurrentProfs.weapon.otherWea.finalProfs.join("s?|") + "s?").replace(/ss\?(\||$)/g, "s?$1") + ");", "i").test(";" + [WeaponName, theWea.type].concat(theWea.list ? [theWea.list] : []).concat(theWea.baseWeapon ? [theWea.baseWeapon] : []).join(";") + ";")) { return true; // Proficient with the weapon through an 'other weapons' proficiency } return false; diff --git a/_functions/FunctionsSpells.js b/_functions/FunctionsSpells.js index f53fc0cf..700282cd 100644 --- a/_functions/FunctionsSpells.js +++ b/_functions/FunctionsSpells.js @@ -120,10 +120,7 @@ function GetSpellObject(theSpl, theCast, firstCol, noOverrides, tipShortDescr) { } // If this spell is gained from an item, feat, or race, remove scaling effects if (aCast && !aCast.allowUpCasting && (aCast.allowUpCasting === false || (/^(item|feat|race)$/i).test(aCast.typeSp) || (aCast.refType && (/^(item|feat|race)$/i).test(aCast.refType))) && (aSpell.level || aCast.typeSp == "item" || (aCast.refType && aCast.refType == "item"))) { - var removeRegex = /\+(\d+d)?\d+\/SL\b|\bSL used/ig - if (removeRegex.test(aSpell.description + aSpell.descriptionMetric)) { - aSpell.description = aSpell.description.replace("SL used", "level " + aSpell.level).replace(removeRegex, '').replace(/, within 30 ft of each other,|, each max 30 ft apart,|; \+\d+d\d+ at CL.*?17/ig, ''); - if (aSpell.descriptionMetric) aSpell.descriptionMetric = aSpell.descriptionMetric.replace("SL used", "level " + aSpell.level).replace(removeRegex, ''); + if (removeSpellUpcasting(aSpell)) { aSpell.changesObj["Innate Spellcasting"] = "\n \u2022 Spell cast by magic items, from feats, or from racial traits can only be cast at the spell's level, not with higher level spell slots."; } } @@ -263,6 +260,17 @@ function fixSpellRangeOverflow(rangeStr) { return (testRx).test(rangeStr) ? rangeStr.trim().replace(/[- /]?m (con|cub)e/i, "m $1").replace(/[- /]?m rad/i, "m rad") : rangeStr; } +// under certain conditions, we want to remove any upcasting from the spell's short description +function removeSpellUpcasting(oSpell) { + var removeRegex = /\+(\d+d)?\d+\/\d*SL\b|\bSL used/ig + if (removeRegex.test(oSpell.description + oSpell.descriptionMetric)) { + oSpell.description = oSpell.description.replace("SL used", "level " + oSpell.level).replace(removeRegex, '').replace(/, within 30 ft of each other,|, each max 30 ft apart,|; \+\d+d\d+ at CL.*?17/ig, ''); + if (oSpell.descriptionMetric) oSpell.descriptionMetric = oSpell.descriptionMetric.replace("SL used", "level " + oSpell.level).replace(removeRegex, ''); + return true; + } + return false; +} + // call this on validation of the hidden spell remember field, to apply something to the spell line // "" = reset all the fields; "HideThisLine" = hide all the fields; recognized spell = apply that spell; not recognized spell = don't do anything (assume name change); "setcaptions" or "setcaptions##Me" = make this a caption line; if followed by "##Me" or "##Kn", change the first line to be either "Me" or "Kn" as the first column, or show or hide the box for checkmark; "___" = put all lines in the fields, making it fillable by hand function ApplySpell(FldValue, rememberFldName) { diff --git a/_variables/ListsClasses.js b/_variables/ListsClasses.js index bc717562..3fc3a99e 100644 --- a/_variables/ListsClasses.js +++ b/_variables/ListsClasses.js @@ -1442,7 +1442,7 @@ var Base_ClassList = { name : "Sneak Attack", source : [["SRD", 39], ["P", 96]], minlevel : 1, - description : "\n " + "Once per turn, I can add damage to finesse/ranged attack if I have adv." + "\n " + "I don't need adv. if a conscious ally is within 5 ft of the target and I don't have disadv.", + description : "\n " + "Once per turn, I can add damage to a finesse/ranged weapon attack if I have advantage" + "\n " + "I don't need adv. if a conscious ally is within 5 ft of the target and I don't have disadv.", additional : levels.map(function (n) { return Math.ceil(n / 2) + "d6"; }), @@ -1482,7 +1482,7 @@ var Base_ClassList = { name : "Uncanny Dodge", source : [["SRD", 40], ["P", 96]], minlevel : 5, - description : "\n " + "As a reaction, I halve the damage of an attack from an attacker that I can see", + description : "\n " + "As a reaction, I can halve the damage of an attack from an attacker that I can see", action : ["reaction", ""] }, "evasion" : { @@ -2280,24 +2280,24 @@ var Base_ClassList = { description : "\n " + "I can choose one spell from the warlock spell list of each level mentioned above" + "\n " + "I can cast these spells each once per long rest without needing to use a spell slot", additional : ["", "", "", "", "", "", "", "", "", "", "6th level", "6th level", "6th and 7th level", "6th and 7th level", "6th, 7th, and 8th level", "6th, 7th, and 8th level", "6th, 7th, 8th, and 9th level", "6th, 7th, 8th, and 9th level", "6th, 7th, 8th, and 9th level", "6th, 7th, 8th, and 9th level"], spellcastingBonus : [{ - name : "Mystic Arcanum (6)", + name : "Mystic Arcanum (6th-level)", "class" : "warlock", level : [6, 6], firstCol : "oncelr" }, { - name : "Mystic Arcanum (7)", + name : "Mystic Arcanum (7th-level)", "class" : "warlock", level : [7, 7], firstCol : "oncelr", times : levels.map(function (n) { return n < 13 ? 0 : 1; }) }, { - name : "Mystic Arcanum (8)", + name : "Mystic Arcanum (8th-level)", "class" : "warlock", level : [8, 8], firstCol : "oncelr", times : levels.map(function (n) { return n < 15 ? 0 : 1; }) }, { - name : "Mystic Arcanum (9)", + name : "Mystic Arcanum (9th-level)", "class" : "warlock", level : [9, 9], firstCol : "oncelr", diff --git a/additional content syntax/_common attributes.js b/additional content syntax/_common attributes.js index 443f18ad..d719255d 100644 --- a/additional content syntax/_common attributes.js +++ b/additional content syntax/_common attributes.js @@ -258,6 +258,7 @@ extraLimitedFeatures : [{ recovery : "long rest", // REQUIRED // usagescalc : "event.value = Math.max(1, What('Cha Mod'));", // OPTIONAL // additional : "2d8", // OPTIONAL // + altResource : "SS 5+", // OPTIONAL // addToExisting : true // OPTIONAL // ADDED v13.0.6 }], /* extraLimitedFeatures // OPTIONAL // @@ -267,7 +268,7 @@ extraLimitedFeatures : [{ Use this attribute only if you have more than one limited feature to add and you already used the default usages/recovery method described above. Each object has to contain at least the `name`, `usages`, and `recovery` attributes. - The `usagescalc`, `additional`, and `addToExisting` attributes are optional. + The `usagescalc`, `additional`, `altResource`, and `addToExisting` attributes are optional. For an explanation of how the different attributes work, see the attributes by the same names above, except for the following, which have a different name above: diff --git a/additional content syntax/creature, wild shape option (CreatureList).js b/additional content syntax/creature, wild shape option (CreatureList).js index e49d4a92..f548b394 100644 --- a/additional content syntax/creature, wild shape option (CreatureList).js +++ b/additional content syntax/creature, wild shape option (CreatureList).js @@ -403,6 +403,25 @@ CreatureList["purple crawler"] = { The sheet will take the number given here, look at the ability score and proficiency bonus, and determine if the creature is proficient and/or has other modifiers. Then it will check the proficiency box and/or fill the modifier field, as appropriate. +*/ + savesLinked : true, +/* savesLinked // OPTIONAL // + TYPE: boolean + USE: whether the total save bonus is the same (true) as the main character or not (false) + ADDED: v13.0.6 + + Setting this to true will cause the totals for saving throws on the Companion page + to always be identical to those of the main character (on the 1st page). + The proficiency checkbox and modifier fields on the Companion page will be ignored. + + It will effectively cause the `saves` attribute above to be overwritten on + the Companion page with the totals of the main character (the 1st page). + Even so, setting the `saves` attribute is still functional, as it will + be used to calculate saving throw proficiencies on the Wild Shape page. + + This attribute has no affect on the Wild Shape page. + + Setting this attribute to false is the same as not including this attribute. */ senses : "Darkvision 60 ft", /* senses // REQUIRED //