forked from GitHub-Mirrors/foundry-sw5e
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
This commit is contained in:
parent
fa5dc07869
commit
fb73cdfc08
5 changed files with 154 additions and 77 deletions
|
@ -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
|
||||
|
|
|
@ -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", {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue