Update to help NPCs work better

This requires all the monsters to be updated with force powers, powerForce/TechLevels, and powercasting "classes"
This commit is contained in:
supervj 2021-02-16 02:15:39 -05:00
parent f9bc405787
commit 7fc983b042
6 changed files with 549 additions and 522 deletions

View file

@ -404,7 +404,7 @@ export default class Actor5e extends Actor {
case 'consular': case 'consular':
priority = 3; priority = 3;
forceProgression.levels += levels; forceProgression.levels += levels;
forceProgression.multi += (SW5E.powerMaxLevel['consular'][levels-1]/9)*levels; forceProgression.multi += (SW5E.powerMaxLevel['consular'][19]/9)*levels;
forceProgression.classes++; forceProgression.classes++;
// see if class controls high level forcecasting // see if class controls high level forcecasting
if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){ if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){
@ -420,7 +420,7 @@ export default class Actor5e extends Actor {
case 'engineer': case 'engineer':
priority = 2 priority = 2
techProgression.levels += levels; techProgression.levels += levels;
techProgression.multi += (SW5E.powerMaxLevel['engineer'][levels-1]/9)*levels; techProgression.multi += (SW5E.powerMaxLevel['engineer'][19]/9)*levels;
techProgression.classes++; techProgression.classes++;
// see if class controls high level techcasting // see if class controls high level techcasting
if ((levels >= techProgression.maxClassLevels) && (priority > techProgression.maxClassPriority)){ if ((levels >= techProgression.maxClassLevels) && (priority > techProgression.maxClassPriority)){
@ -435,7 +435,7 @@ export default class Actor5e extends Actor {
case 'guardian': case 'guardian':
priority = 1; priority = 1;
forceProgression.levels += levels; forceProgression.levels += levels;
forceProgression.multi += (SW5E.powerMaxLevel['guardian'][levels-1]/9)*levels; forceProgression.multi += (SW5E.powerMaxLevel['guardian'][19]/9)*levels;
forceProgression.classes++; forceProgression.classes++;
// see if class controls high level forcecasting // see if class controls high level forcecasting
if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){ if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){
@ -450,7 +450,7 @@ export default class Actor5e extends Actor {
case 'scout': case 'scout':
priority = 1; priority = 1;
techProgression.levels += levels; techProgression.levels += levels;
techProgression.multi += (SW5E.powerMaxLevel['scout'][levels-1]/9)*levels; techProgression.multi += (SW5E.powerMaxLevel['scout'][19]/9)*levels;
techProgression.classes++; techProgression.classes++;
// see if class controls high level techcasting // see if class controls high level techcasting
if ((levels >= techProgression.maxClassLevels) && (priority > techProgression.maxClassPriority)){ if ((levels >= techProgression.maxClassLevels) && (priority > techProgression.maxClassPriority)){
@ -465,7 +465,7 @@ export default class Actor5e extends Actor {
case 'sentinel': case 'sentinel':
priority = 2; priority = 2;
forceProgression.levels += levels; forceProgression.levels += levels;
forceProgression.multi += (SW5E.powerMaxLevel['sentinel'][levels-1]/9)*levels; forceProgression.multi += (SW5E.powerMaxLevel['sentinel'][19]/9)*levels;
forceProgression.classes++; forceProgression.classes++;
// see if class controls high level forcecasting // see if class controls high level forcecasting
if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){ if ((levels >= forceProgression.maxClassLevels) && (priority > forceProgression.maxClassPriority)){
@ -482,31 +482,27 @@ export default class Actor5e extends Actor {
// EXCEPTION: multi-classed progression uses multi rounded down rather than levels // EXCEPTION: multi-classed progression uses multi rounded down rather than levels
if (!isNPC && forceProgression.classes > 1) { if (!isNPC && forceProgression.classes > 1) {
forceProgression.levels = Math.floor(forceProgression.multi); forceProgression.levels = Math.floor(forceProgression.multi);
forceProgression.maxClassPowerLevel = SW5E.powerMaxLevel['multi'][levels - 1]; forceProgression.maxClassPowerLevel = SW5E.powerMaxLevel['multi'][forceProgression.levels - 1];
} }
if (!isNPC && techProgression.classes > 1) { if (!isNPC && techProgression.classes > 1) {
techProgression.levels = Math.floor(techProgression.multi); techProgression.levels = Math.floor(techProgression.multi);
techProgression.maxClassPowerLevel = SW5E.powerMaxLevel['multi'][levels - 1]; techProgression.maxClassPowerLevel = SW5E.powerMaxLevel['multi'][techProgression.levels - 1];
} }
// EXCEPTION: NPC with an explicit power-caster level // EXCEPTION: NPC with an explicit power-caster level
if (isNPC && actorData.data.details.powerForceLevel) { if (isNPC && actorData.data.details.powerForceLevel) {
forceProgression.levels = actorData.data.details.powerForceLevel; forceProgression.levels = actorData.data.details.powerForceLevel;
forceProgression.maxClass = 'consular'; forceProgression.maxClass = actorData.data.attributes.powercasting;
forceProgression.maxClassPowerLevel = SW5E.powerMaxLevel['consular'][Math.clamped((forceProgression.levels - 1), 0, 20)]; forceProgression.maxClassPowerLevel = SW5E.powerMaxLevel[forceProgression.maxClass][Math.clamped((forceProgression.levels - 1), 0, 20)];
forceProgression.powersKnown = SW5E.powersKnown['consular'][Math.clamped((forceProgression.levels - 1), 0, 20)];
forceProgression.points = SW5E.powerPoints['consular'][Math.clamped((forceProgression.levels - 1), 0, 20)];
} }
if (isNPC && actorData.data.details.powerTechLevel) { if (isNPC && actorData.data.details.powerTechLevel) {
techProgression.levels = actorData.data.details.powerTechLevel; techProgression.levels = actorData.data.details.powerTechLevel;
techProgression.maxClass = 'engineer'; techProgression.maxClass = actorData.data.attributes.powercasting;
techProgression.maxClassPowerLevel = SW5E.powerMaxLevel['engineer'][Math.clamped((techProgression.levels - 1), 0, 20)]; techProgression.maxClassPowerLevel = SW5E.powerMaxLevel[techProgression.maxClass][Math.clamped((techProgression.levels - 1), 0, 20)];
techProgression.powersKnown = SW5E.powersKnown['engineer'][Math.clamped((techProgression.levels - 1), 0, 20)];
techProgression.points = SW5E.powerPoints['engineer'][Math.clamped((techProgression.levels - 1), 0, 20)];
} }
// Look up the number of slots per level from the powerLimit table // Look up the number of slots per level from the powerLimit table
let forcePowerLimit = SW5E.powerLimit['none']; let forcePowerLimit = Array.from(SW5E.powerLimit['none']);
for (let i = 0; i < (forceProgression.maxClassPowerLevel); i++) { for (let i = 0; i < (forceProgression.maxClassPowerLevel); i++) {
forcePowerLimit[i] = SW5E.powerLimit[forceProgression.maxClass][i]; forcePowerLimit[i] = SW5E.powerLimit[forceProgression.maxClass][i];
} }
@ -516,10 +512,14 @@ export default class Actor5e extends Actor {
if ( Number.isNaN(i) ) continue; if ( Number.isNaN(i) ) continue;
if ( Number.isNumeric(lvl.foverride) ) lvl.fmax = Math.max(parseInt(lvl.foverride), 0); if ( Number.isNumeric(lvl.foverride) ) lvl.fmax = Math.max(parseInt(lvl.foverride), 0);
else lvl.fmax = forcePowerLimit[i-1] || 0; else lvl.fmax = forcePowerLimit[i-1] || 0;
lvl.fvalue = Math.min(parseInt(lvl.fvalue),lvl.fmax); if (isNPC){
lvl.fvalue = lvl.fmax;
}else{
lvl.fvalue = Math.min(parseInt(lvl.fvalue || lvl.value || lvl.fmax),lvl.fmax);
}
} }
let techPowerLimit = SW5E.powerLimit['none']; let techPowerLimit = Array.from(SW5E.powerLimit['none']);
for (let i = 0; i < (techProgression.maxClassPowerLevel); i++) { for (let i = 0; i < (techProgression.maxClassPowerLevel); i++) {
techPowerLimit[i] = SW5E.powerLimit[techProgression.maxClass][i]; techPowerLimit[i] = SW5E.powerLimit[techProgression.maxClass][i];
} }
@ -529,7 +529,11 @@ export default class Actor5e extends Actor {
if ( Number.isNaN(i) ) continue; if ( Number.isNaN(i) ) continue;
if ( Number.isNumeric(lvl.toverride) ) lvl.tmax = Math.max(parseInt(lvl.toverride), 0); if ( Number.isNumeric(lvl.toverride) ) lvl.tmax = Math.max(parseInt(lvl.toverride), 0);
else lvl.tmax = techPowerLimit[i-1] || 0; else lvl.tmax = techPowerLimit[i-1] || 0;
lvl.tvalue = Math.min(parseInt(lvl.tvalue),lvl.tmax); if (isNPC){
lvl.tvalue = lvl.tmax;
}else{
lvl.tvalue = Math.min(parseInt(lvl.tvalue || lvl.value || lvl.tmax),lvl.tmax);
}
} }
// Set Force and tech power // Set Force and tech power
@ -544,29 +548,31 @@ export default class Actor5e extends Actor {
actorData.data.attributes.tech.level = techProgression.levels; actorData.data.attributes.tech.level = techProgression.levels;
} }
// Tally Powers Known // Tally Powers Known and check for migration first to avoid errors
const knownPowers = this.data.items.filter(i => i.type === "power"); let hasKnownPowers = actorData?.data?.attributes?.force?.known?.value !== undefined;
let knownForcePowers = 0; if ( hasKnownPowers ) {
let knownTechPowers = 0; const knownPowers = this.data.items.filter(i => i.type === "power");
for ( let knownPower of knownPowers ) { let knownForcePowers = 0;
const d = knownPower.data; let knownTechPowers = 0;
switch (knownPower.data.school){ for ( let knownPower of knownPowers ) {
case "lgt": const d = knownPower.data;
case "uni": switch (knownPower.data.school){
case "drk":{ case "lgt":
knownForcePowers++; case "uni":
break; case "drk":{
} knownForcePowers++;
case "tec":{ break;
knownTechPowers++; }
break; case "tec":{
} knownTechPowers++;
} break;
continue; }
}
continue;
}
actorData.data.attributes.force.known.value = knownForcePowers;
actorData.data.attributes.tech.known.value = knownTechPowers;
} }
actorData.data.attributes.force.known.value = knownForcePowers;
actorData.data.attributes.tech.known.value = knownTechPowers;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View file

@ -129,7 +129,6 @@ export const migrateActorData = function(actor) {
// Actor Data Updates // Actor Data Updates
_migrateActorMovement(actor, updateData); _migrateActorMovement(actor, updateData);
_migrateActorSenses(actor, updateData); _migrateActorSenses(actor, updateData);
_migrateActorPowers(actor, updateData);
// Migrate Owned Items // Migrate Owned Items
if ( !actor.items ) return updateData; if ( !actor.items ) return updateData;
@ -153,6 +152,10 @@ export const migrateActorData = function(actor) {
} else return i; } else return i;
}); });
if ( hasItemUpdates ) updateData.items = items; if ( hasItemUpdates ) updateData.items = items;
// migrate powers last since it relies on item classes being migrated first.
_migrateActorPowers(actor, updateData);
return updateData; return updateData;
}; };
@ -268,7 +271,6 @@ function _migrateActorPowers(actorData, updateData) {
let hasNewAttrib = ad?.attributes?.force?.level !== undefined; let hasNewAttrib = ad?.attributes?.force?.level !== undefined;
if ( !hasNewAttrib ) { if ( !hasNewAttrib ) {
updateData["data.attributes.force.known.value"] = 0; updateData["data.attributes.force.known.value"] = 0;
updateData["data.attributes.force.known.min"] = 0;
updateData["data.attributes.force.known.max"] = 0; updateData["data.attributes.force.known.max"] = 0;
updateData["data.attributes.force.points.value"] = 0; updateData["data.attributes.force.points.value"] = 0;
updateData["data.attributes.force.points.min"] = 0; updateData["data.attributes.force.points.min"] = 0;
@ -277,7 +279,6 @@ function _migrateActorPowers(actorData, updateData) {
updateData["data.attributes.force.points.tempmax"] = 0; updateData["data.attributes.force.points.tempmax"] = 0;
updateData["data.attributes.force.level"] = 0; updateData["data.attributes.force.level"] = 0;
updateData["data.attributes.tech.known.value"] = 0; updateData["data.attributes.tech.known.value"] = 0;
updateData["data.attributes.tech.known.min"] = 0;
updateData["data.attributes.tech.known.max"] = 0; updateData["data.attributes.tech.known.max"] = 0;
updateData["data.attributes.tech.points.value"] = 0; updateData["data.attributes.tech.points.value"] = 0;
updateData["data.attributes.tech.points.min"] = 0; updateData["data.attributes.tech.points.min"] = 0;
@ -288,13 +289,15 @@ function _migrateActorPowers(actorData, updateData) {
} }
// If new Power F/T split data is not present, create it // If new Power F/T split data is not present, create it
const hasNewLimit = ad?.powers?.power1?.fvalue !== undefined; const hasNewLimit = ad?.powers?.power1?.foverride !== undefined;
if ( !hasNewLimit ) { if ( !hasNewLimit ) {
for (let i = 1; i <= 9; i++) { for (let i = 1; i <= 9; i++) {
// add new // add new
updateData["data.powers.power" + i + ".fvalue"] = 1000; updateData["data.powers.power" + i + ".fvalue"] = getProperty(ad.powers,"power" + i + ".fvalue");
updateData["data.powers.power" + i + ".fmax"] = getProperty(ad.powers,"power" + i + ".fmax");
updateData["data.powers.power" + i + ".foverride"] = null; updateData["data.powers.power" + i + ".foverride"] = null;
updateData["data.powers.power" + i + ".tvalue"] = 1000; updateData["data.powers.power" + i + ".tvalue"] = getProperty(ad.powers,"power" + i + ".tvalue");
updateData["data.powers.power" + i + ".tmax"] = getProperty(ad.powers,"power" + i + ".tmax");
updateData["data.powers.power" + i + ".toverride"] = null; updateData["data.powers.power" + i + ".toverride"] = null;
//remove old //remove old
updateData["data.powers.power" + i + ".-=value"] = null; updateData["data.powers.power" + i + ".-=value"] = null;

File diff suppressed because one or more lines are too long

View file

@ -97,7 +97,6 @@
"force": { "force": {
"known": { "known": {
"value": 0, "value": 0,
"min": 0,
"max": 0 "max": 0
}, },
"points": { "points": {
@ -112,7 +111,6 @@
"tech": { "tech": {
"known": { "known": {
"value": 0, "value": 0,
"min": 0,
"max": 0 "max": 0
}, },
"points": { "points": {
@ -211,57 +209,75 @@
}, },
"powers": { "powers": {
"power1": { "power1": {
"fvalue": 0, "fvalue": 1000,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1000,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power2": { "power2": {
"fvalue": 0, "fvalue": 1000,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1000,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power3": { "power3": {
"fvalue": 0, "fvalue": 1000,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1000,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power4": { "power4": {
"fvalue": 0, "fvalue": 1000,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1000,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power5": { "power5": {
"fvalue": 0, "fvalue": 1000,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1000,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power6": { "power6": {
"fvalue": 0, "fvalue": 1,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power7": { "power7": {
"fvalue": 0, "fvalue": 1,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power8": { "power8": {
"fvalue": 0, "fvalue": 1,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1,
"tmax": 0,
"toverride": null "toverride": null
}, },
"power9": { "power9": {
"fvalue": 0, "fvalue": 1,
"fmax": 0,
"foverride": null, "foverride": null,
"tvalue": 0, "tvalue": 1,
"tmax": 0,
"toverride": null "toverride": null
} }
}, },

View file

@ -52,10 +52,11 @@
</div> </div>
{{else}} {{else}}
<h1>{{localize "SW5E.PowersKnown"}}</h1> <h1>{{localize "SW5E.PowersKnown"}}</h1>
<div class="attribute-value"> <div class="attribute-value multiple">
<div></div> <span class="value-number">{{data.attributes.force.known.value}}</span>
<span>{{data.attributes.force.known.max}}</span> <span class="value-separator">/</span>
<span class="value-number">{{data.attributes.force.known.max}}</span>
</div> </div>
{{/if}} {{/if}}
</div> </div>

View file

@ -35,9 +35,10 @@
{{else}} {{else}}
<h1>{{localize "SW5E.PowersKnown"}}</h1> <h1>{{localize "SW5E.PowersKnown"}}</h1>
<div class="attribute-value"> <div class="attribute-value multiple">
<div></div> <span class="value-number">{{data.attributes.tech.known.value}}</span>
<span>{{data.attributes.tech.known.max}}</span> <span class="value-separator">/</span>
<span class="value-number">{{data.attributes.tech.known.max}}</span>
</div> </div>
{{/if}} {{/if}}
</div> </div>