From ad50d1549fa6e8f6223a60094d610b6a6263e828 Mon Sep 17 00:00:00 2001 From: supervj <64861570+supervj@users.noreply.github.com> Date: Tue, 9 Feb 2021 23:47:32 -0500 Subject: [PATCH 1/3] Powercasting works based on school of power Updated power items to automatically change mod used when set to powercasting --- lang/en.json | 4 ++++ module/actor/entity.js | 4 +--- module/apps/actor-flags.js | 6 +++++- module/item/entity.js | 41 +++++++++++++++++++++++++++++++------- module/migration.js | 2 +- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/lang/en.json b/lang/en.json index 0afb6bc6..e83df03b 100644 --- a/lang/en.json +++ b/lang/en.json @@ -144,6 +144,10 @@ "SW5E.BonusRWDamage": "Ranged Weapon Damage Bonus", "SW5E.BonusSaveForm": "Update Bonuses", "SW5E.BonusPowerDC": "Global Power DC Bonus", +"SW5E.BonusForceLightPowerDC": "Global Force Light Power DC Bonus", +"SW5E.BonusForceDarkPowerDC": "Global Force Dark Power DC Bonus", +"SW5E.BonusForceUnivPowerDC": "Global Force Universal Power DC Bonus", +"SW5E.BonusTechPowerDC": "Global Tech Power DC Bonus", "SW5E.BonusTitle": "Configure Actor Bonuses", "SW5E.Bonuses": "Global Bonuses", "SW5E.BonusesHint": "Define global bonuses as formulas which are added to certain rolls. For example: 1d4 + 2", diff --git a/module/actor/entity.js b/module/actor/entity.js index 7b242362..489ee602 100644 --- a/module/actor/entity.js +++ b/module/actor/entity.js @@ -94,7 +94,7 @@ export default class Actor5e extends Actor { // Prepare power-casting data data.attributes.powerForceLightDC = 8 + data.abilities.wis.mod + data.attributes.prof ?? 10; data.attributes.powerForceDarkDC = 8 + data.abilities.cha.mod + data.attributes.prof ?? 10; - data.attributes.powerForceUnivDC = Math.ceil(data.attributes.powerForceLightDC,data.attributes.powerForceDarkDC) ?? 10; + data.attributes.powerForceUnivDC = Math.max(data.attributes.powerForceLightDC,data.attributes.powerForceDarkDC) ?? 10; data.attributes.powerTechDC = 8 + data.abilities.int.mod + data.attributes.prof ?? 10; this._computePowercastingProgression(this.data); @@ -1119,8 +1119,6 @@ export default class Actor5e extends Actor { } } - - // Note the change in HP and HD and TP which occurred const dhd = this.data.data.attributes.hd - hd0; const dhp = this.data.data.attributes.hp.value - hp0; diff --git a/module/apps/actor-flags.js b/module/apps/actor-flags.js index 16241782..86293dab 100644 --- a/module/apps/actor-flags.js +++ b/module/apps/actor-flags.js @@ -74,7 +74,11 @@ export default class ActorSheetFlags extends BaseEntitySheet { {name: "data.bonuses.abilities.check", label: "SW5E.BonusAbilityCheck"}, {name: "data.bonuses.abilities.save", label: "SW5E.BonusAbilitySave"}, {name: "data.bonuses.abilities.skill", label: "SW5E.BonusAbilitySkill"}, - {name: "data.bonuses.power.dc", label: "SW5E.BonusPowerDC"} + {name: "data.bonuses.power.dc", label: "SW5E.BonusPowerDC"}, + {name: "data.bonuses.power.forceLightDC", label: "SW5E.BonusForceLightPowerDC"}, + {name: "data.bonuses.power.forceDarkDC", label: "SW5E.BonusForceDarkPowerDC"}, + {name: "data.bonuses.power.forceUnivDC", label: "SW5E.BonusForceUnivPowerDC"}, + {name: "data.bonuses.power.techDC", label: "SW5E.BonusTechPowerDC"} ]; for ( let b of bonuses ) { b.value = getProperty(this.object._data, b.name) || ""; diff --git a/module/item/entity.js b/module/item/entity.js index 8b35bcc5..1bc68041 100644 --- a/module/item/entity.js +++ b/module/item/entity.js @@ -25,8 +25,17 @@ export default class Item5e extends Item { else if (this.actor) { const actorData = this.actor.data.data; - // Powers - Use Actor powercasting modifier - if (this.data.type === "power") return actorData.attributes.powercasting || "int"; + // Powers - Use Actor powercasting modifier based on power school + if (this.data.type === "power") { + switch (this.data.data.school) { + case "lgt": return "wis"; + case "uni": return (actorData.abilities["wis"].mod >= actorData.abilities["cha"].mod) ? "wis" : "cha"; + case "drk": return "cha"; + case "tec": return "int"; + } + return "none"; + } + // Tools - default to Intelligence else if (this.data.type === "tool") return "int"; @@ -291,7 +300,24 @@ export default class Item5e extends Item { // Actor power-DC based scaling if ( save.scaling === "power" ) { - save.dc = this.isOwned ? getProperty(this.actor.data, "data.attributes.powerdc") : null; + switch (this.data.data.school) { + case "lgt": { + save.dc = this.isOwned ? getProperty(this.actor.data, "data.attributes.powerForceLightDC") : null; + break; + } + case "uni": { + save.dc = this.isOwned ? getProperty(this.actor.data, "data.attributes.powerForceUnivDC") : null; + break; + } + case "drk": { + save.dc = this.isOwned ? getProperty(this.actor.data, "data.attributes.powerForceDarkDC") : null; + break; + } + case "tec": { + save.dc = this.isOwned ? getProperty(this.actor.data, "data.attributes.powerTechDC") : null; + break; + } + } } // Ability-score based scaling @@ -394,6 +420,7 @@ export default class Item5e extends Item { const recharge = id.recharge || {}; // Recharge mechanic const uses = id?.uses ?? {}; // Limited uses const isPower = this.type === "power"; // Does the item require a power slot? + // TODO: Possibly Mod this to not consume slots based on class? const requirePowerSlot = isPower && (id.level > 0) && CONFIG.SW5E.powerUpcastModes.includes(id.preparation.mode); // Define follow-up actions resulting from the item usage @@ -420,12 +447,12 @@ export default class Item5e extends Item { // Handle power upcasting if ( requirePowerSlot ) { const slotLevel = configuration.level; - const powerLevel = slotLevel === "pact" ? actor.data.data.powers.pact.level : parseInt(slotLevel); + const powerLevel = parseInt(slotLevel); if (powerLevel !== id.level) { const upcastData = mergeObject(this.data, {"data.level": powerLevel}, {inplace: false}); item = this.constructor.createOwned(upcastData, actor); // Replace the item with an upcast version } - if ( consumePowerSlot ) consumePowerSlot = slotLevel === "pact" ? "pact" : `power${powerLevel}`; + if ( consumePowerSlot ) consumePowerSlot = `power${powerLevel}`; } } @@ -495,7 +522,7 @@ export default class Item5e extends Item { const level = this.actor?.data.data.powers[consumePowerSlot]; const powers = Number(level?.value ?? 0); if ( powers === 0 ) { - const label = game.i18n.localize(consumePowerSlot === "pact" ? "SW5E.PowerProgPact" : `SW5E.PowerLevel${id.level}`); + const label = game.i18n.localize(`SW5E.PowerLevel${id.level}`); ui.notifications.warn(game.i18n.format("SW5E.PowerCastNoSlots", {name: this.name, level: label})); return false; } @@ -772,7 +799,7 @@ export default class Item5e extends Item { /* -------------------------------------------- */ /** - * Prepare chat card data for tool type items + * Prepare chat card data for loot type items * @private */ _lootChatData(data, labels, props) { diff --git a/module/migration.js b/module/migration.js index 75ac202c..a1b138b9 100644 --- a/module/migration.js +++ b/module/migration.js @@ -292,7 +292,7 @@ function _migrateActorPowers(actorData, updateData) { updateData["data.bonuses.power.forceLightDC"] = ""; updateData["data.bonuses.power.forceDarkDC"] = ""; updateData["data.bonuses.power.forceUnivDC"] = ""; - updateData["data.bonuses.power.TechDC"] = ""; + updateData["data.bonuses.power.techDC"] = ""; } // Remove the Power DC Bonus From fa5dc07869945b9446039bf8806c76ec009e2426 Mon Sep 17 00:00:00 2001 From: supervj <64861570+supervj@users.noreply.github.com> Date: Wed, 10 Feb 2021 02:32:08 -0500 Subject: [PATCH 2/3] Have Powers consume Force and Tech Points Add the ability for powers to automatically deduct force and tech points --- module/apps/ability-use-dialog.js | 25 ++++++++++--------- module/item/entity.js | 40 ++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/module/apps/ability-use-dialog.js b/module/apps/ability-use-dialog.js index cc277f9b..a7cedb05 100644 --- a/module/apps/ability-use-dialog.js +++ b/module/apps/ability-use-dialog.js @@ -100,6 +100,19 @@ export default class AbilityUseDialog extends Dialog { // Determine the levels which are feasible let lmax = 0; + let points; + switch (itemData.school){ + case "lgt": + case "uni": + case "drk": { + points = actorData.attributes.force.points.value + actorData.attributes.force.points.temp; + break; + } + case "tec": { + points = actorData.attributes.tech.points.value + actorData.attributes.tech.points.temp; + break; + } + } const powerLevels = Array.fromRange(10).reduce((arr, i) => { if ( i < lvl ) return arr; const label = CONFIG.SW5E.powerLevels[i]; @@ -111,21 +124,11 @@ export default class AbilityUseDialog extends Dialog { level: i, label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label, canCast: max > 0, - hasSlots: slots > 0 + hasSlots: ((slots > 0) && (points > i)) }); return arr; }, []).filter(sl => sl.level <= lmax); - // If this character has pact slots, present them as an option for casting the power. - const pact = actorData.powers.pact; - if (pact.level >= lvl) { - powerLevels.push({ - level: 'pact', - label: `${game.i18n.format('SW5E.PowerLevelPact', {level: pact.level, n: pact.value})}`, - canCast: true, - hasSlots: pact.value > 0 - }); - } const canCast = powerLevels.some(l => l.hasSlots); if ( !canCast ) data.errors.push(game.i18n.format("SW5E.PowerCastNoSlots", { level: CONFIG.SW5E.powerLevels[lvl], diff --git a/module/item/entity.js b/module/item/entity.js index 1bc68041..1b0df501 100644 --- a/module/item/entity.js +++ b/module/item/entity.js @@ -431,11 +431,18 @@ export default class Item5e extends Item { let consumeUsage = !!uses.per; // Consume limited uses let consumeQuantity = uses.autoDestroy; // Consume quantity of the item in lieu of uses + //set rollback values in case you pick a spell level you can't cast anymore + let forcePointValueRollback = actor.data.data.attributes.force.points.value; + let forcePointTempRollback = actor.data.data.attributes.force.points.temp; + let techPointValueRollback = actor.data.data.attributes.tech.points.value; + let techPointTempRollback = actor.data.data.attributes.tech.points.temp; + // Display a configuration dialog to customize the usage const needsConfiguration = createMeasuredTemplate || consumeRecharge || consumeResource || consumePowerSlot || consumeUsage; if (configureDialog && needsConfiguration) { const configuration = await AbilityUseDialog.create(this); if (!configuration) return; + // Determine consumption preferences createMeasuredTemplate = Boolean(configuration.placeTemplate); @@ -448,6 +455,31 @@ export default class Item5e extends Item { if ( requirePowerSlot ) { const slotLevel = configuration.level; const powerLevel = parseInt(slotLevel); + const fp = actor.data.data.attributes.force.points; + const tp = actor.data.data.attributes.tech.points; + const powerCost = powerLevel + 1; + switch (id.school){ + case "lgt": + case "uni": + case "drk": { + if (fp.temp >= powerCost) { + actor.update({"data.attributes.force.points.temp": fp.temp - powerCost}); + }else{ + actor.update({"data.attributes.force.points.value": fp.value + fp.temp - powerCost}); + actor.update({"data.attributes.force.points.temp": 0}); + } + break; + } + case "tec": { + if (tp.temp >= powerCost) { + actor.update({"data.attributes.tech.points.temp": tp.temp - powerCost}); + }else{ + actor.update({"data.attributes.tech.points.value": tp.value + tp.temp - powerCost}); + actor.update({"data.attributes.tech.points.temp": 0}); + break; + } + } + } if (powerLevel !== id.level) { const upcastData = mergeObject(this.data, {"data.level": powerLevel}, {inplace: false}); item = this.constructor.createOwned(upcastData, actor); // Replace the item with an upcast version @@ -458,7 +490,13 @@ export default class Item5e extends Item { // Determine whether the item can be used by testing for resource consumption const usage = item._getUsageUpdates({consumeRecharge, consumeResource, consumePowerSlot, consumeUsage, consumeQuantity}); - if ( !usage ) return; + if ( !usage ) { + actor.update({"data.attributes.force.points.value": forcePointValueRollback}); + actor.update({"data.attributes.force.points.temp": forcePointTempRollback}); + actor.update({"data.attributes.tech.points.value": techPointValueRollback}); + actor.update({"data.attributes.tech.points.temp": techPointTempRollback}); + return; + } const {actorUpdates, itemUpdates, resourceUpdates} = usage; // Commit pending data updates From fb73cdfc086048d8984359a707751a36c4c4f454 Mon Sep 17 00:00:00 2001 From: supervj <64861570+supervj@users.noreply.github.com> Date: Wed, 10 Feb 2021 15:41:02 -0500 Subject: [PATCH 3/3] Split Force and Tech Power Limits Split force and tech power limits. Didn't test, may be broken. Needs separate tab for force vs tech. Still need to tally number of powers known --- module/actor/entity.js | 20 ++++++-- module/apps/ability-use-dialog.js | 58 +++++++++++++++------ module/item/entity.js | 84 ++++++++++++++++--------------- module/migration.js | 15 ++++++ template.json | 54 +++++++++++++------- 5 files changed, 154 insertions(+), 77 deletions(-) diff --git a/module/actor/entity.js b/module/actor/entity.js index 489ee602..4c24956a 100644 --- a/module/actor/entity.js +++ b/module/actor/entity.js @@ -506,7 +506,6 @@ export default class Actor5e extends Actor { } // Look up the number of slots per level from the powerLimit table - // TODO: Add Tech progression afterwards let forcePowerLimit = SW5E.powerLimit['none']; for (let i = 0; i < (forceProgression.maxClassPowerLevel); i++) { forcePowerLimit[i] = SW5E.powerLimit[forceProgression.maxClass][i]; @@ -515,9 +514,22 @@ export default class Actor5e extends Actor { for ( let [n, lvl] of Object.entries(powers) ) { let i = parseInt(n.slice(-1)); if ( Number.isNaN(i) ) continue; - if ( Number.isNumeric(lvl.override) ) lvl.max = Math.max(parseInt(lvl.override), 0); - else lvl.max = forcePowerLimit[i-1] || 0; - lvl.value = parseInt(lvl.value); + if ( Number.isNumeric(lvl.foverride) ) lvl.fmax = Math.max(parseInt(lvl.foverride), 0); + else lvl.fmax = forcePowerLimit[i-1] || 0; + lvl.fvalue = parseInt(lvl.fvalue); + } + + let techPowerLimit = SW5E.powerLimit['none']; + for (let i = 0; i < (techProgression.maxClassPowerLevel); i++) { + techPowerLimit[i] = SW5E.powerLimit[techProgression.maxClass][i]; + } + + for ( let [n, lvl] of Object.entries(powers) ) { + let i = parseInt(n.slice(-1)); + if ( Number.isNaN(i) ) continue; + if ( Number.isNumeric(lvl.toverride) ) lvl.tmax = Math.max(parseInt(lvl.toverride), 0); + else lvl.tmax = techPowerLimit[i-1] || 0; + lvl.tvalue = parseInt(lvl.tvalue); } // Set Force and tech power diff --git a/module/apps/ability-use-dialog.js b/module/apps/ability-use-dialog.js index a7cedb05..b0a1fc91 100644 --- a/module/apps/ability-use-dialog.js +++ b/module/apps/ability-use-dialog.js @@ -101,33 +101,61 @@ export default class AbilityUseDialog extends Dialog { // Determine the levels which are feasible let lmax = 0; let points; + let powerType; switch (itemData.school){ case "lgt": case "uni": case "drk": { + powerType = "force" points = actorData.attributes.force.points.value + actorData.attributes.force.points.temp; break; } case "tec": { + powerType = "tech" points = actorData.attributes.tech.points.value + actorData.attributes.tech.points.temp; break; } } - const powerLevels = Array.fromRange(10).reduce((arr, i) => { - if ( i < lvl ) return arr; - const label = CONFIG.SW5E.powerLevels[i]; - const l = actorData.powers["power"+i] || {max: 0, override: null}; - let max = parseInt(l.override || l.max || 0); - let slots = Math.clamped(parseInt(l.value || 0), 0, max); - if ( max > 0 ) lmax = i; - arr.push({ - level: i, - label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label, - canCast: max > 0, - hasSlots: ((slots > 0) && (points > i)) - }); - return arr; - }, []).filter(sl => sl.level <= lmax); + let powerLevels + if (powerType === "force"){ + powerLevels = Array.fromRange(10).reduce((arr, i) => { + if ( i < lvl ) return arr; + const label = CONFIG.SW5E.powerLevels[i]; + const l = actorData.powers["power"+i] || {fmax: 0, foverride: null}; + let max = parseInt(l.foverride || l.fmax || 0); + let slots = Math.clamped(parseInt(l.fvalue || 0), 0, max); + if ( max > 0 ) lmax = i; + if ((max > 0) && (slots > 0) && (points > i)){ + arr.push({ + level: i, + label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label, + canCast: max > 0, + hasSlots: slots > 0 + }); + } + return arr; + }, []).filter(sl => sl.level <= lmax); + }else if (powerType === "tech"){ + powerLevels = Array.fromRange(10).reduce((arr, i) => { + if ( i < lvl ) return arr; + const label = CONFIG.SW5E.powerLevels[i]; + const l = actorData.powers["power"+i] || {tmax: 0, toverride: null}; + let max = parseInt(l.override || l.tmax || 0); + let slots = Math.clamped(parseInt(l.tvalue || 0), 0, max); + if ( max > 0 ) lmax = i; + if ((max > 0) && (slots > 0) && (points > i)){ + arr.push({ + level: i, + label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label, + canCast: max > 0, + hasSlots: slots > 0 + }); + } + return arr; + }, []).filter(sl => sl.level <= lmax); + } + + const canCast = powerLevels.some(l => l.hasSlots); if ( !canCast ) data.errors.push(game.i18n.format("SW5E.PowerCastNoSlots", { diff --git a/module/item/entity.js b/module/item/entity.js index 1b0df501..479edb49 100644 --- a/module/item/entity.js +++ b/module/item/entity.js @@ -431,12 +431,12 @@ export default class Item5e extends Item { let consumeUsage = !!uses.per; // Consume limited uses let consumeQuantity = uses.autoDestroy; // Consume quantity of the item in lieu of uses - //set rollback values in case you pick a spell level you can't cast anymore + /*//set rollback values in case you pick a spell level you can't cast anymore let forcePointValueRollback = actor.data.data.attributes.force.points.value; let forcePointTempRollback = actor.data.data.attributes.force.points.temp; let techPointValueRollback = actor.data.data.attributes.tech.points.value; let techPointTempRollback = actor.data.data.attributes.tech.points.temp; - + */ // Display a configuration dialog to customize the usage const needsConfiguration = createMeasuredTemplate || consumeRecharge || consumeResource || consumePowerSlot || consumeUsage; if (configureDialog && needsConfiguration) { @@ -455,31 +455,7 @@ export default class Item5e extends Item { if ( requirePowerSlot ) { const slotLevel = configuration.level; const powerLevel = parseInt(slotLevel); - const fp = actor.data.data.attributes.force.points; - const tp = actor.data.data.attributes.tech.points; - const powerCost = powerLevel + 1; - switch (id.school){ - case "lgt": - case "uni": - case "drk": { - if (fp.temp >= powerCost) { - actor.update({"data.attributes.force.points.temp": fp.temp - powerCost}); - }else{ - actor.update({"data.attributes.force.points.value": fp.value + fp.temp - powerCost}); - actor.update({"data.attributes.force.points.temp": 0}); - } - break; - } - case "tec": { - if (tp.temp >= powerCost) { - actor.update({"data.attributes.tech.points.temp": tp.temp - powerCost}); - }else{ - actor.update({"data.attributes.tech.points.value": tp.value + tp.temp - powerCost}); - actor.update({"data.attributes.tech.points.temp": 0}); - break; - } - } - } + if (powerLevel !== id.level) { const upcastData = mergeObject(this.data, {"data.level": powerLevel}, {inplace: false}); item = this.constructor.createOwned(upcastData, actor); // Replace the item with an upcast version @@ -490,13 +466,8 @@ export default class Item5e extends Item { // Determine whether the item can be used by testing for resource consumption const usage = item._getUsageUpdates({consumeRecharge, consumeResource, consumePowerSlot, consumeUsage, consumeQuantity}); - if ( !usage ) { - actor.update({"data.attributes.force.points.value": forcePointValueRollback}); - actor.update({"data.attributes.force.points.temp": forcePointTempRollback}); - actor.update({"data.attributes.tech.points.value": techPointValueRollback}); - actor.update({"data.attributes.tech.points.temp": techPointTempRollback}); - return; - } + if ( !usage ) return; + const {actorUpdates, itemUpdates, resourceUpdates} = usage; // Commit pending data updates @@ -558,14 +529,47 @@ export default class Item5e extends Item { // Consume Power Slots if ( consumePowerSlot ) { const level = this.actor?.data.data.powers[consumePowerSlot]; - const powers = Number(level?.value ?? 0); - if ( powers === 0 ) { - const label = game.i18n.localize(`SW5E.PowerLevel${id.level}`); - ui.notifications.warn(game.i18n.format("SW5E.PowerCastNoSlots", {name: this.name, level: label})); - return false; + const fp = this.actor.data.data.attributes.force.points; + const tp = this.actor.data.data.attributes.tech.points; + const powerCost = level + 1; + switch (id.school){ + case "lgt": + case "uni": + case "drk": { + const powers = Number(level?.fvalue ?? 0); + if ( powers === 0 ) { + const label = game.i18n.localize(`SW5E.PowerLevel${id.level}`); + ui.notifications.warn(game.i18n.format("SW5E.PowerCastNoSlots", {name: this.name, level: label})); + return false; + } + actorUpdates[`data.powers.${consumePowerSlot}.fvalue`] = Math.max(powers - 1, 0); + if (fp.temp >= powerCost) { + actorUpdates["data.attributes.force.points.temp"] = fp.temp - powerCost; + }else{ + actorUpdates["data.attributes.force.points.value"] = fp.value + fp.temp - powerCost; + actorUpdates["data.attributes.force.points.temp"] = 0; + } + break; + } + case "tec": { + const powers = Number(level?.tvalue ?? 0); + if ( powers === 0 ) { + const label = game.i18n.localize(`SW5E.PowerLevel${id.level}`); + ui.notifications.warn(game.i18n.format("SW5E.PowerCastNoSlots", {name: this.name, level: label})); + return false; + } + actorUpdates[`data.powers.${consumePowerSlot}.tvalue`] = Math.max(powers - 1, 0); + if (tp.temp >= powerCost) { + actorUpdates["data.attributes.force.points.temp"] = tp.temp - powerCost; + }else{ + actorUpdates["data.attributes.force.points.value"] = tp.value + tp.temp - powerCost; + actorUpdates["data.attributes.force.points.temp"] = 0; + } + break; + } } - actorUpdates[`data.powers.${consumePowerSlot}.value`] = Math.max(powers - 1, 0); } + // Consume Limited Usage if ( consumeUsage ) { diff --git a/module/migration.js b/module/migration.js index a1b138b9..cf31ec6a 100644 --- a/module/migration.js +++ b/module/migration.js @@ -286,6 +286,21 @@ function _migrateActorPowers(actorData, updateData) { updateData["data.attributes.tech.points.tempmax"] = 0; updateData["data.attributes.tech.level"] = 0; } + + // If new Power F/T split data is not present, create it + const hasNewBonus = ad?.powers?.power1?.fvalue !== undefined; + if ( !hasNewBonus ) { + for (let i = 1; i <= 9; i++) { + // add new + updateData["data.powers.power" + i + ".fvalue"] = 0; + updateData["data.powers.power" + i + ".foverride"] = null; + updateData["data.powers.power" + i + ".tvalue"] = 0; + updateData["data.powers.power" + i + ".toverride"] = null; + //remove old + updateData["data.powers.power" + i + ".-=value"] = null; + updateData["data.powers.power" + i + ".-=override"] = null; + } + } // If new Bonus Power DC data is not present, create it const hasNewBonus = ad?.bonuses?.power?.forceLightDC !== undefined; if ( !hasNewBonus ) { diff --git a/template.json b/template.json index 32084f50..1fe3984a 100644 --- a/template.json +++ b/template.json @@ -211,40 +211,58 @@ }, "powers": { "power1": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power2": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power3": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power4": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power5": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power6": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power7": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power8": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null }, "power9": { - "value": 0, - "override": null + "fvalue": 0, + "foverride": null, + "tvalue": 0, + "toverride": null } }, "bonuses": {