diff --git a/_functions/Functions1.js b/_functions/Functions1.js index 3fd3701..33f9fb2 100644 --- a/_functions/Functions1.js +++ b/_functions/Functions1.js @@ -1938,15 +1938,6 @@ function FindClasses(NotAtStartup, isFieldVal) { } } - /* TESTING - //special something for classes that have alternative ability scores that can be used for the DC - if (Temps.abilitySave && Temps.abilitySaveAlt) { - var as1 = Number(What(AbilityScores.abbreviations[Temps.abilitySave - 1])); - var as2 = Number(What(AbilityScores.abbreviations[Temps.abilitySaveAlt - 1])); - if (as1 < as2) Temps.abilitySave = Temps.abilitySaveAlt; - } - */ - var fAB = []; var fTrans = {}; //add features of the class @@ -3023,37 +3014,6 @@ function SetWeaponsdropdown(forceTooltips, aCompPrefixes) { } processWea(WeaponsList); -/* TESTING - for (var key in WeaponsList) { - var weaKey = WeaponsList[key]; - var weaList = weaKey.list ? weaKey.list.toLowerCase() : ""; - if (!weaList || testSource(key, weaKey, "weapExcl")) continue; // test if the weapon or its source is set to be included - if (!oWeaponLists[weaList]) { - otherLists.push(weaList); - oWeaponLists[weaList] = []; - } - var weaName = WeaponsList[key].name.capitalize(); - if (added.indexOf(weaName) === -1) { - added.push(weaName); - oWeaponLists[weaList].push(weaName); - } - if (isArray(WeaponsList[key].nameAlt)) { - WeaponsList[key].nameAlt.forEach(function (name) { - name = name.capitalize(); - if (added.indexOf(name) === -1) { - added.push(name); - oWeaponLists.altList.push(name); - } - }); - } - }; - - if (CurrentVars.extraWeaponsDisplay) { - for (var key in CurrentVars.extraWeaponsDisplay) { - oWeaponLists.startlist.push(CurrentVars.extraWeaponsDisplay[key]); - } - }; -*/ // make the definitive list of weapons for the dropdown box var setweapons = []; @@ -6805,7 +6765,6 @@ function SetToManual_Button(bSkipDialog, oDialogResults) { CurrentVars.manual.background = What("Background") + " "; Hide("Background Menu"); } else if (CurrentVars.manual.background) { - // FindBackground(CurrentVars.manual.background); // TESTING CurrentVars.manual.background = false; // Apply the current background field content DontPrint("Background Menu"); @@ -6838,16 +6797,6 @@ function SetToManual_Button(bSkipDialog, oDialogResults) { CurrentVars.manual.classes = false; // Apply the current class and levels field content ApplyClasses(What("Class and Levels"), false); - /* TESTING - var newClassValue = What("Class and Levels"); - // restore the old class value so that we have a working classes.old - var oldClassValue = CurrentVars.manual.classes; - tDoc.getField("Class and Levels").remVal = oldClassValue; - Value("Class and Levels", oldClassValue); - // now set class processing back to automatic and apply the new value - CurrentVars.manual.classes = false; - Value("Class and Levels", newClassValue); - */ } } @@ -6898,29 +6847,6 @@ function SetToManual_Button(bSkipDialog, oDialogResults) { oFeat.idx // bIgnoreCurrent ); } - - /* TESTING - // set the old known feats back and apply the current ones - var oldKnowns = CurrentVars.manual.feats[0]; - CurrentFeats.level = CurrentVars.manual.feats[1]; - CurrentVars.manual.feats = false; - var remIgnoreDuplicates = ignoreDuplicates; - ignoreDuplicates = true; - for (var i = 1; i <= FieldNumbers.feats; i++) { - CurrentFeats.known[i - 1] = oldKnowns[i - 1]; - ApplyFeat(What("Feat Name " + i), i); - } - // loop through the known feats and if any are still the same as before, first delete it and then apply it again - for (var i = 0; i < FieldNumbers.feats; i++) { - if (oldKnowns[i] && CurrentFeats.known[i] == oldKnowns[i]) { - Value("Feat Name " + (i+1), ""); - Value("Feat Name " + (i+1), FeatsList[oldKnowns[i]].name); - } - } - ignoreDuplicates = remIgnoreDuplicates; - // update the feat level to the current level - UpdateLevelFeatures("feat"); - */ } } @@ -6984,32 +6910,6 @@ function SetToManual_Button(bSkipDialog, oDialogResults) { oItem.idx // bIgnoreCurrent ); } - - /* TESTING - var oldKnowns = CurrentVars.manual.items[0]; - var oldChoices = CurrentVars.manual.items[3]; - if (!oldChoices) oldChoices = []; // backwards compatibility - var oldAttuned = CurrentVars.manual.items[1]; - CurrentMagicItems.level = CurrentVars.manual.items[2]; - CurrentVars.manual.items = false; - var remIgnoreDuplicates = ignoreDuplicates; - ignoreDuplicates = true; - for (var i = 1; i <= FieldNumbers.magicitems; i++) { - CurrentMagicItems.known[i - 1] = oldKnowns[i - 1]; - CurrentMagicItems.choices[i - 1] = oldChoices[i - 1]; - ApplyMagicItem(What("Extra.Magic Item " + i), i); - } - // loop through the known magic items and if any are still the same as before, first delete it and then apply it again - for (var i = 0; i < FieldNumbers.magicitems; i++) { - if (oldKnowns[i] && CurrentMagicItems.known[i] == oldKnowns[i]) { - Value("Extra.Magic Item " + (i+1), ""); - Value("Extra.Magic Item " + (i+1), MagicItemsList[oldKnowns[i]].name); - } - } - ignoreDuplicates = remIgnoreDuplicates; - // update the magic item level to the current level - UpdateLevelFeatures("item"); - */ } } @@ -7024,7 +6924,6 @@ function SetToManual_Button(bSkipDialog, oDialogResults) { ]; Hide("Race Features Menu"); } else if (CurrentVars.manual.race) { - // FindRace(CurrentVars.manual.race[0], true); // TESTING // Set the level to the remember field if (CurrentRace.known) CurrentRace.level = CurrentVars.manual.race[1]; // Disable manual races diff --git a/_functions/Functions2.js b/_functions/Functions2.js index df7fc42..7ba5f6e 100644 --- a/_functions/Functions2.js +++ b/_functions/Functions2.js @@ -5750,9 +5750,15 @@ function ApplyWeapon(inputText, fldName, isReCalc, onlyProf, forceRedo) { //add mod var StrDex = What(QI ? "Str" : prefix + "Comp.Use.Ability.Str.Score") < What(QI ? "Dex" : prefix + "Comp.Use.Ability.Dex.Score") ? 2 : 1; var weaponMod = /finesse/i.test(theWea.description) ? StrDex : theWea.ability; - //change mod if this is concerning a spell/cantrip + //special cases + var fixedCaster = theWea.useSpellMod && CurrentSpells[theWea.useSpellMod] ? theWea.useSpellMod : false; var forceUseSpellcastingMod = theWea.useSpellcastingAbility === undefined ? false : theWea.useSpellcastingAbility ? "y" : "n"; - if ((thisWeapon[3] || forceUseSpellcastingMod == "y") && forceUseSpellcastingMod != "n") { + + if (fixedCaster) { + //if the weapon has `useSpellMod`, set the ability to the matching spellcaster + weaponMod = CurrentSpells[theWea.useSpellMod].abilityToUse ? CurrentSpells[theWea.useSpellMod].abilityToUse[0] : getSpellcastingAbility(theWea.useSpellMod)[0]; + } else if ((thisWeapon[3] || forceUseSpellcastingMod == "y") && forceUseSpellcastingMod != "n") { + //change mod if this is concerning a spell/cantrip if (thisWeapon[4].length) { var abiArr = thisWeapon[4].map( function(sClass) { return CurrentSpells[sClass] && CurrentSpells[sClass].ability && !isNaN(CurrentSpells[sClass].ability) ? CurrentSpells[sClass].ability : 0; @@ -5828,7 +5834,13 @@ function ApplyWeapon(inputText, fldName, isReCalc, onlyProf, forceRedo) { i--; } } + + // if the `useSpellMod` was changed, change the ability to match + if (fixedCaster !== theWea.useSpellMod && CurrentSpells[theWea.useSpellMod]) { + weaponMod = CurrentSpells[theWea.useSpellMod].abilityToUse ? CurrentSpells[theWea.useSpellMod].abilityToUse[0] : getSpellcastingAbility(theWea.useSpellMod)[0]; + } }; + // if this is a field recalculation and no custom eval changed specific parts, just use the one from the field so that manual changes are preserved if (isReCalc && !forceRedo) { if (fields.Description === theWea.description) { @@ -5956,7 +5968,7 @@ function CalcAttackDmgHit(fldName) { }; // define some variables that we can check against later or with the CurrentEvals - var isDC = /dc/i.test(fields.To_Hit_Bonus), spTypeShort = isDC ? "dc" : "atk", spTypeFull = isDC ? "dc" : "attack"; + var isDC = /dc/i.test(fields.To_Hit_Bonus), spTypeShort = isDC ? "dc" : "atk"; // Gather some information on the weapon var isSpell = thisWeapon[3] || (theWea && /cantrip|spell/i.test(theWea.type)) || (!theWea && /\b(cantrip|spell)\b/i.test(WeaponText)) ? true : false; @@ -6062,27 +6074,12 @@ function CalcAttackDmgHit(fldName) { ( (fixedCaster && !fixedCaster.fixedDC) || (QI && isSpell && !fixedCaster) ) ) { // get the variables we need to pass to the function - var spCasters = spCaster ? spCaster : !thisWeapon[4].length ? [] : thisWeapon[4].map( function(sClass) { + var aCasters = spCaster ? spCaster : !thisWeapon[4].length ? [] : thisWeapon[4].map( function(sClass) { return CurrentSpells[sClass] && CurrentSpells[sClass].ability == abiScoreNo ? sClass : ""; }); + var sType = isDC ? "dc" : "attack"; - for (var i = 0; i < CurrentEvals.spellCalcOrder.length; i++) { - var evalName = CurrentEvals.spellCalcOrder[i][1]; - var evalThing = CurrentEvals.spellCalc[evalName]; - if (!evalThing || typeof evalThing !== 'function') continue; - try { - var addSpellNo = evalThing(spTypeFull, spCasters, abiScoreNo, thisWeapon[3]); - if (!isNaN(addSpellNo)) output.extraHit += Number(addSpellNo); - } catch (error) { - var eText = "The custom spell attack/DC (spellCalc) script '" + evalName + "' produced an error! It will be removed from the sheet for now, but please contact the author of the feature to have this issue corrected:\n " + error; - for (var e in error) eText += "\n " + e + ": " + error[e]; - console.println(eText); - console.show(); - delete CurrentEvals.spellCalc[evalName]; - CurrentEvals.spellCalcOrder.splice(i, 1); - i--; - } - } + output.extraHit += runSpellCalc(sType, aCasters, abiScoreNo, thisWeapon[3]); } // Now we parse all that information to a total @@ -7580,18 +7577,6 @@ function SetProf(ProfType, AddRemove, ProfObj, ProfSrc, Extra) { } // Get the current expected totals before we change anything var oldTotals = getTotals(); - /* TESTING - var oldTotals = { - walkSpd : parseSpeed("walk", set.walk.spd, false, 0), - walkEnc : parseSpeed("walk", set.walk.enc, false, 0) - }; - for (var i = 0; i < spdTypes.length; i++) { - var sT = spdTypes[i]; - if (sT === "walk") continue; - oldTotals[sT + "Spd"] = parseSpeed(sT, set[sT].spd, false, oldTotals.walkSpd); - oldTotals[sT + "Enc"] = parseSpeed(sT, set[sT].enc, false, oldTotals.walkEnc); - }; - */ // Get the manual changed by comparing the values of the field and the oldTotals var oDeltaSpds = {}; var splitSpdString = function(type, str) { @@ -7639,19 +7624,6 @@ function SetProf(ProfType, AddRemove, ProfObj, ProfSrc, Extra) { }; // Get the new totals var newTotals = getTotals(oDeltaSpds); - /* TESTING - var theWalks = { - spd : parseSpeed("walk", set.walk.spd, "both", 0, oDeltaSpds.walkSpd), - enc : parseSpeed("walk", set.walk.enc, "both", 0, oDeltaSpds.walkEnc) - }; - var newTotals = { walkSpd : theWalks.spd[0], walkEnc : theWalks.enc[0] }; - for (var i = 0; i < spdTypes.length; i++) { - var sT = spdTypes[i]; - if (sT === "walk") continue; - newTotals[sT + "Spd"] = parseSpeed(sT, set[sT].spd, true, theWalks.spd[2], oDeltaSpds[sT + "Spd"]); - newTotals[sT + "Enc"] = parseSpeed(sT, set[sT].enc, true, theWalks.enc[2], oDeltaSpds[sT + "Enc"]); - }; - */ // Create the strings var spdString = ""; var encString = ""; diff --git a/_functions/FunctionsSpells.js b/_functions/FunctionsSpells.js index 1e78c83..e33c72c 100644 --- a/_functions/FunctionsSpells.js +++ b/_functions/FunctionsSpells.js @@ -809,20 +809,31 @@ function CalcSpellScores() { // do custom calculations if (CurrentEvals.spellCalc) { - var abiScoreNo = tDoc.getField(modFldName).currentValueIndices; - var classArray = cSpells ? [aClass] : []; - if (cSpells && cSpells.ability && isNaN(cSpells.ability) && CurrentSpells[cSpells.ability]) classArray.push(cSpells.ability); + var iAbiScore = tDoc.getField(modFldName).currentValueIndices; + var aCasters = cSpells ? [aClass] : []; + if (cSpells && cSpells.ability && isNaN(cSpells.ability) && CurrentSpells[cSpells.ability]) aCasters.push(cSpells.ability); + for (var sType in theResult) { + if ((fixedDC && sType != "prepare") || (sType == "prepare" && !isPrepareVis)) continue; + theResult[sType] += runSpellCalc(sType, aCasters, iAbiScore, ""); + } + } + + // finally set the results to the field + setResults(true); +} + +// Run the calcChanges.spellCalc for the given variables +function runSpellCalc(sType, aCasters, iAbiScore, sSpell) { + var iReturn = 0; + if (CurrentEvals.spellCalc) { for (var i = 0; i < CurrentEvals.spellCalcOrder.length; i++) { var evalName = CurrentEvals.spellCalcOrder[i][1]; var evalThing = CurrentEvals.spellCalc[evalName]; if (!evalThing || typeof evalThing !== 'function') continue; try { - for (var aType in theResult) { - if ((fixedDC && aType != "prepare") || (aType == "prepare" && !isPrepareVis)) continue; - var addSpellNo = evalThing(aType, classArray, abiScoreNo); - if (!isNaN(addSpellNo)) theResult[aType] += Number(addSpellNo); - } + var evalResult = evalThing(sType, aCasters, iAbiScore, sSpell); + if (!isNaN(evalResult)) iReturn = Number(evalResult); } catch (error) { var eText = "The custom spell attack/DC (spellCalc) script from '" + evalName + "' produced an error! It will be removed from the sheet for now, but please contact the author of the feature to have this issue corrected:\n " + error; for (var e in error) eText += "\n " + e + ": " + error[e]; @@ -834,9 +845,7 @@ function CalcSpellScores() { } } } - - // finally set the results to the field - setResults(true); + return iReturn; } //set the blueText field bonus to the global CurrentSpells object for spells to memorize, attack modifier, and DC (field blur) diff --git a/additional content syntax/_common attributes.js b/additional content syntax/_common attributes.js index 2b09175..fa66315 100644 --- a/additional content syntax/_common attributes.js +++ b/additional content syntax/_common attributes.js @@ -1871,7 +1871,7 @@ calcChanges : { */ spellCalc : [ - function (type, spellcasters, ability) { + function (type, spellcasters, ability, spell) { if (type == "dc") return 1; }, "I add +1 to all the saving throw DCs of my spells." @@ -1922,6 +1922,10 @@ calcChanges : { For example, if you want to add 1 to the spell attacks done with Charisma: if (type == "attack" && ability == 6) return 1; + 4) spell, a string, the object name of the spell in the `SpellsList` object + This is only used for DC/attack calculated in the attacks section, + on the 1st page. + // 2nd array entry // OPTIONAL // This has to be a string and will be used to populate the "Things affecting the attack calculations" dialog. It you already have either atkAdd or atkCalc in the same feature,