forked from GitHub-Mirrors/foundry-sw5e
Merge branch 'Develop'
This commit is contained in:
commit
c7ef91e9ed
79 changed files with 2588 additions and 752 deletions
|
@ -25,6 +25,8 @@ export default class Actor5e extends Actor {
|
|||
return this._prepareCharacterData(this.data);
|
||||
case "npc":
|
||||
return this._prepareNPCData(this.data);
|
||||
case "starship":
|
||||
return this._prepareStarshipData(this.data);
|
||||
case "vehicle":
|
||||
return this._prepareVehicleData(this.data);
|
||||
}
|
||||
|
@ -304,6 +306,23 @@ export default class Actor5e extends Actor {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare starship type-specific data
|
||||
* @param actorData
|
||||
* @private
|
||||
*/
|
||||
_prepareStarshipData(actorData) {
|
||||
const data = actorData.data;
|
||||
|
||||
// Proficiency
|
||||
data.attributes.prof = Math.floor((Math.max(data.details.tier, 1) + 7) / 4);
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Prepare skill checks.
|
||||
* @param actorData
|
||||
|
@ -363,7 +382,7 @@ export default class Actor5e extends Actor {
|
|||
* @private
|
||||
*/
|
||||
_computePowercastingProgression (actorData) {
|
||||
if (actorData.type === 'vehicle') return;
|
||||
if (actorData.type === 'vehicle' || actorData.type === 'starship') return;
|
||||
const powers = actorData.data.powers;
|
||||
const isNPC = actorData.type === 'npc';
|
||||
|
||||
|
@ -1597,4 +1616,4 @@ export default class Actor5e extends Actor {
|
|||
if ( item.data.type !== "power" ) throw new Error("Wrong Item type");
|
||||
return item.roll();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
cssClass: isOwner ? "editable" : "locked",
|
||||
isCharacter: this.entity.data.type === "character",
|
||||
isNPC: this.entity.data.type === "npc",
|
||||
isStarship: this.entity.data.type === "starship",
|
||||
isVehicle: this.entity.data.type === 'vehicle',
|
||||
config: CONFIG.SW5E,
|
||||
};
|
||||
|
@ -338,6 +339,7 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
if ( filters.has("prepared") ) {
|
||||
if ( data.level === 0 || ["innate", "always"].includes(data.preparation.mode) ) return true;
|
||||
if ( this.actor.data.type === "npc" ) return true;
|
||||
if ( this.actor.data.type === "starship" ) return true;
|
||||
return data.preparation.prepared;
|
||||
}
|
||||
|
||||
|
@ -407,8 +409,11 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
html.find('.item-create').click(this._onItemCreate.bind(this));
|
||||
html.find('.item-edit').click(this._onItemEdit.bind(this));
|
||||
html.find('.item-delete').click(this._onItemDelete.bind(this));
|
||||
html.find('.item-collapse').click(this._onItemCollapse.bind(this));
|
||||
html.find('.item-uses input').click(ev => ev.target.select()).change(this._onUsesChange.bind(this));
|
||||
html.find('.slot-max-override').click(this._onPowerSlotOverride.bind(this));
|
||||
html.find('.increment-class-level').click(this._onIncrementClassLevel.bind(this));
|
||||
html.find('.decrement-class-level').click(this._onDecrementClassLevel.bind(this));
|
||||
|
||||
// Active Effect management
|
||||
html.find(".effect-control").click(ev => onManageActiveEffect(ev, this.entity));
|
||||
|
@ -757,6 +762,75 @@ export default class ActorSheet5e extends ActorSheet {
|
|||
this.actor.deleteOwnedItem(li.dataset.itemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle collapsing a Feature row on the actor sheet
|
||||
* @param {Event} event The originating click event
|
||||
* @private
|
||||
*/
|
||||
|
||||
_onItemCollapse(event) {
|
||||
event.preventDefault();
|
||||
|
||||
event.currentTarget.classList.toggle("active");
|
||||
|
||||
const li = event.currentTarget.closest("li");
|
||||
const content = li.querySelector(".content");
|
||||
|
||||
if (content.style.display === "none") {
|
||||
content.style.display = "block";
|
||||
} else {
|
||||
content.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incrementing class level on the actor sheet
|
||||
* @param {Event} event The originating click event
|
||||
* @private
|
||||
*/
|
||||
|
||||
_onIncrementClassLevel(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const div = event.currentTarget.closest(".character")
|
||||
const li = event.currentTarget.closest("li");
|
||||
|
||||
const actorId = div.id.split("-")[1];
|
||||
const itemId = li.dataset.itemId;
|
||||
|
||||
const actor = game.actors.get(actorId);
|
||||
const item = actor.getOwnedItem(itemId);
|
||||
|
||||
let levels = item.data.data.levels;
|
||||
const update = {_id: item._id, data: {levels: (levels + 1) }};
|
||||
|
||||
actor.updateOwnedItem(update)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle decrementing class level on the actor sheet
|
||||
* @param {Event} event The originating click event
|
||||
* @private
|
||||
*/
|
||||
|
||||
_onDecrementClassLevel(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const div = event.currentTarget.closest(".character")
|
||||
const li = event.currentTarget.closest("li");
|
||||
|
||||
const actorId = div.id.split("-")[1];
|
||||
const itemId = li.dataset.itemId;
|
||||
|
||||
const actor = game.actors.get(actorId);
|
||||
const item = actor.getOwnedItem(itemId);
|
||||
|
||||
let levels = item.data.data.levels;
|
||||
const update = {_id: item._id, data: {levels: (levels - 1) }};
|
||||
|
||||
actor.updateOwnedItem(update)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,7 +84,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
};
|
||||
|
||||
// Partition items by category
|
||||
let [items, forcepowers, techpowers, feats, classes, species, archetypes, classfeatures, backgrounds, fightingstyles, fightingmasteries, lightsaberforms] = data.items.reduce((arr, item) => {
|
||||
let [items, forcepowers, techpowers, feats, classes, deployments, deploymentfeatures, ventures, species, archetypes, classfeatures, backgrounds, fightingstyles, fightingmasteries, lightsaberforms] = data.items.reduce((arr, item) => {
|
||||
|
||||
// Item details
|
||||
item.img = item.img || DEFAULT_TOKEN;
|
||||
|
@ -116,16 +116,19 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
else if ( item.type === "power" && ["tec"].includes(item.data.school) ) arr[2].push(item);
|
||||
else if ( item.type === "feat" ) arr[3].push(item);
|
||||
else if ( item.type === "class" ) arr[4].push(item);
|
||||
else if ( item.type === "species" ) arr[5].push(item);
|
||||
else if ( item.type === "archetype" ) arr[6].push(item);
|
||||
else if ( item.type === "classfeature" ) arr[7].push(item);
|
||||
else if ( item.type === "background" ) arr[8].push(item);
|
||||
else if ( item.type === "fightingstyle" ) arr[9].push(item);
|
||||
else if ( item.type === "fightingmastery" ) arr[10].push(item);
|
||||
else if ( item.type === "lightsaberform" ) arr[11].push(item);
|
||||
else if ( item.type === "deployment" ) arr[5].push(item);
|
||||
else if ( item.type === "deploymentfeature" ) arr[6].push(item);
|
||||
else if ( item.type === "venture" ) arr[7].push(item);
|
||||
else if ( item.type === "species" ) arr[8].push(item);
|
||||
else if ( item.type === "archetype" ) arr[9].push(item);
|
||||
else if ( item.type === "classfeature" ) arr[10].push(item);
|
||||
else if ( item.type === "background" ) arr[11].push(item);
|
||||
else if ( item.type === "fightingstyle" ) arr[12].push(item);
|
||||
else if ( item.type === "fightingmastery" ) arr[13].push(item);
|
||||
else if ( item.type === "lightsaberform" ) arr[14].push(item);
|
||||
else if ( Object.keys(inventory).includes(item.type ) ) arr[0].push(item);
|
||||
return arr;
|
||||
}, [[], [], [], [], [], [], [], [], [], [], [], []]);
|
||||
}, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]);
|
||||
|
||||
// Apply active item filters
|
||||
items = this._filterItems(items, this._filters.inventory);
|
||||
|
@ -150,6 +153,9 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
classes: { label: "SW5E.ItemTypeClassPl", items: [], hasActions: false, dataset: {type: "class"}, isClass: true },
|
||||
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: true, dataset: {type: "classfeature"}, isClassfeature: true },
|
||||
archetype: { label: "SW5E.ItemTypeArchetype", items: [], hasActions: false, dataset: {type: "archetype"}, isArchetype: true },
|
||||
deployments: { label: "SW5E.ItemTypeDeploymentPl", items: [], hasActions: false, dataset: {type: "deployment"}, isDeployment: true },
|
||||
deploymentfeatures: { label: "SW5E.ItemTypeDeploymentFeaturePl", items: [], hasActions: true, dataset: {type: "deploymentfeature"}, isDeploymentfeature: true },
|
||||
ventures: { label: "SW5E.ItemTypeVenturePl", items: [], hasActions: false, dataset: {type: "venture"}, isVenture: true },
|
||||
species: { label: "SW5E.ItemTypeSpecies", items: [], hasActions: false, dataset: {type: "species"}, isSpecies: true },
|
||||
background: { label: "SW5E.ItemTypeBackground", items: [], hasActions: false, dataset: {type: "background"}, isBackground: true },
|
||||
fightingstyles: { label: "SW5E.ItemTypeFightingStylePl", items: [], hasActions: false, dataset: {type: "fightingstyle"}, isFightingstyle: true },
|
||||
|
@ -166,6 +172,9 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
features.classes.items = classes;
|
||||
features.classfeatures.items = classfeatures;
|
||||
features.archetype.items = archetypes;
|
||||
features.deployments.items = deployments;
|
||||
features.deploymentfeatures.items = deploymentfeatures;
|
||||
features.ventures.items = ventures;
|
||||
features.species.items = species;
|
||||
features.background.items = backgrounds;
|
||||
features.fightingstyles.items = fightingstyles;
|
||||
|
@ -354,7 +363,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
/** @override */
|
||||
async _onDropItemCreate(itemData) {
|
||||
|
||||
// Increment the number of class levels a character instead of creating a new item
|
||||
// Increment the number of class levels of a character instead of creating a new item
|
||||
if ( itemData.type === "class" ) {
|
||||
const cls = this.actor.itemTypes.class.find(c => c.name === itemData.name);
|
||||
let priorLevel = cls?.data.data.levels ?? 0;
|
||||
|
@ -367,6 +376,19 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
|||
}
|
||||
}
|
||||
|
||||
// Increment the number of deployment ranks of a character instead of creating a new item
|
||||
// else if ( itemData.type === "deployment" ) {
|
||||
// const rnk = this.actor.itemTypes.deployment.find(c => c.name === itemData.name);
|
||||
// let priorRank = rnk?.data.data.ranks ?? 0;
|
||||
// if ( !!rnk ) {
|
||||
// const next = Math.min(priorLevel + 1, 5 + priorRank - this.actor.data.data.details.rank);
|
||||
// if ( next > priorRank ) {
|
||||
// itemData.ranks = next;
|
||||
// return rnk.update({"data.ranks": next});
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Default drop handling if levels were not added
|
||||
super._onDropItemCreate(itemData);
|
||||
}
|
||||
|
|
148
module/actor/sheets/newSheet/starship.js
Normal file
148
module/actor/sheets/newSheet/starship.js
Normal file
|
@ -0,0 +1,148 @@
|
|||
import ActorSheet5e from "./base.js";
|
||||
|
||||
/**
|
||||
* An Actor sheet for starships in the SW5E system.
|
||||
* Extends the base ActorSheet5e class.
|
||||
* @extends {ActorSheet5e}
|
||||
*/
|
||||
export default class ActorSheet5eStarship extends ActorSheet5e {
|
||||
|
||||
/** @override */
|
||||
get template() {
|
||||
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
|
||||
return `systems/sw5e/templates/actors/newActor/starship.html`;
|
||||
}
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["sw5e", "sheet", "actor", "starship"],
|
||||
width: 800,
|
||||
tabs: [{
|
||||
navSelector: ".root-tabs",
|
||||
contentSelector: ".sheet-body",
|
||||
initial: "attributes"
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Organize Owned Items for rendering the starship sheet
|
||||
* @private
|
||||
*/
|
||||
_prepareItems(data) {
|
||||
|
||||
// Categorize Items as Features and Powers
|
||||
const features = {
|
||||
weapons: { label: game.i18n.localize("SW5E.ItemTypeWeaponPl"), items: [], hasActions: true, dataset: {type: "weapon", "weapon-type": "natural"} },
|
||||
passive: { label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"} },
|
||||
equipment: { label: game.i18n.localize("SW5E.StarshipEquipment"), items: [], dataset: {type: "equipment"}},
|
||||
starshipfeatures: { label: game.i18n.localize("SW5E.StarshipfeaturePl"), items: [], hasActions: true, dataset: {type: "starshipfeature"} },
|
||||
starshipmods: { label: game.i18n.localize("SW5E.StarshipmodPl"), items: [], hasActions: false, dataset: {type: "starshipmod"} }
|
||||
};
|
||||
|
||||
// Start by classifying items into groups for rendering
|
||||
let [forcepowers, techpowers, other] = data.items.reduce((arr, item) => {
|
||||
item.img = item.img || DEFAULT_TOKEN;
|
||||
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
|
||||
item.hasUses = item.data.uses && (item.data.uses.max > 0);
|
||||
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
|
||||
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
|
||||
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
|
||||
if ( item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school) ) arr[0].push(item);
|
||||
else if ( item.type === "power" && ["tec"].includes(item.data.school) ) arr[1].push(item);
|
||||
else arr[2].push(item);
|
||||
return arr;
|
||||
}, [[], [], []]);
|
||||
|
||||
// Apply item filters
|
||||
forcepowers = this._filterItems(forcepowers, this._filters.forcePowerbook);
|
||||
techpowers = this._filterItems(techpowers, this._filters.techPowerbook);
|
||||
other = this._filterItems(other, this._filters.features);
|
||||
|
||||
// Organize Powerbook
|
||||
// const forcePowerbook = this._preparePowerbook(data, forcepowers, "uni");
|
||||
// const techPowerbook = this._preparePowerbook(data, techpowers, "tec");
|
||||
|
||||
// Organize Features
|
||||
for ( let item of other ) {
|
||||
if ( item.type === "weapon" ) features.weapons.items.push(item);
|
||||
else if ( item.type === "feat" ) {
|
||||
if ( item.data.activation.type ) features.actions.items.push(item);
|
||||
else features.passive.items.push(item);
|
||||
}
|
||||
else if ( item.type === "starshipfeature" ) {
|
||||
features.starshipfeatures.items.push(item);
|
||||
}
|
||||
else if ( item.type === "starshipmod" ) {
|
||||
features.starshipmods.items.push(item);
|
||||
}
|
||||
else features.equipment.items.push(item);
|
||||
}
|
||||
|
||||
// Assign and return
|
||||
data.features = Object.values(features);
|
||||
// data.forcePowerbook = forcePowerbook;
|
||||
// data.techPowerbook = techPowerbook;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
|
||||
// Challenge Rating
|
||||
const cr = parseFloat(data.data.details.cr || 0);
|
||||
const crLabels = {0: "0", 0.125: "1/8", 0.25: "1/4", 0.5: "1/2"};
|
||||
data.labels["cr"] = cr >= 1 ? String(cr) : crLabels[cr] || 1;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Object Updates */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
|
||||
// Format NPC Challenge Rating
|
||||
const crs = {"1/8": 0.125, "1/4": 0.25, "1/2": 0.5};
|
||||
let crv = "data.details.cr";
|
||||
let cr = formData[crv];
|
||||
cr = crs[cr] || parseFloat(cr);
|
||||
if ( cr ) formData[crv] = cr < 1 ? cr : parseInt(cr);
|
||||
|
||||
// Parent ActorSheet update steps
|
||||
super._updateObject(event, formData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Event Listeners and Handlers */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
html.find(".health .rollable").click(this._onRollHPFormula.bind(this));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Handle rolling NPC health values using the provided formula
|
||||
* @param {Event} event The original click event
|
||||
* @private
|
||||
*/
|
||||
_onRollHPFormula(event) {
|
||||
event.preventDefault();
|
||||
const formula = this.actor.data.data.attributes.hp.formula;
|
||||
if ( !formula ) return;
|
||||
const hp = new Roll(formula).roll().total;
|
||||
AudioHelper.play({src: CONFIG.sounds.dice});
|
||||
this.actor.update({"data.attributes.hp.value": hp, "data.attributes.hp.max": hp});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {ClassFeatures} from "./classFeatures.js"
|
||||
import {ClassFeatures} from "./classFeatures.js"
|
||||
|
||||
// Namespace SW5e Configuration Values
|
||||
export const SW5E = {};
|
||||
|
@ -224,7 +224,9 @@ SW5E.limitedUsePeriods = {
|
|||
"sr": "SW5E.ShortRest",
|
||||
"lr": "SW5E.LongRest",
|
||||
"day": "SW5E.Day",
|
||||
"charges": "SW5E.Charges"
|
||||
"charges": "SW5E.Charges",
|
||||
"recharge": "SW5E.Recharge",
|
||||
"refitting": "SW5E.Refitting"
|
||||
};
|
||||
|
||||
|
||||
|
@ -238,11 +240,16 @@ SW5E.equipmentTypes = {
|
|||
"light": "SW5E.EquipmentLight",
|
||||
"medium": "SW5E.EquipmentMedium",
|
||||
"heavy": "SW5E.EquipmentHeavy",
|
||||
"hyper": "SW5E.EquipmentHyperdrive",
|
||||
"bonus": "SW5E.EquipmentBonus",
|
||||
"natural": "SW5E.EquipmentNatural",
|
||||
"powerc": "SW5E.EquipmentPowerCoupling",
|
||||
"reactor": "SW5E.EquipmentReactor",
|
||||
"shield": "SW5E.EquipmentShield",
|
||||
"clothing": "SW5E.EquipmentClothing",
|
||||
"trinket": "SW5E.EquipmentTrinket",
|
||||
"ssarmor": "SW5E.EquipmentStarshipArmor",
|
||||
"ssshield": "SW5E.EquipmentStarshipShield",
|
||||
"vehicle": "SW5E.EquipmentVehicle"
|
||||
};
|
||||
|
||||
|
@ -423,6 +430,7 @@ SW5E.targetTypes = {
|
|||
"square": "SW5E.TargetSquare",
|
||||
"cube": "SW5E.TargetCube",
|
||||
"line": "SW5E.TargetLine",
|
||||
"starship": "SW5E.TargetStarship",
|
||||
"wall": "SW5E.TargetWall",
|
||||
"weapon": "SW5E.TargetWeapon"
|
||||
};
|
||||
|
@ -507,6 +515,29 @@ SW5E.skills = {
|
|||
"tec": "SW5E.SkillTec"
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The set of starship skills which can be trained in SW5e
|
||||
* @type {Object}
|
||||
*/
|
||||
SW5E.starshipSkills = {
|
||||
"ast": "SW5E.StarshipSkillAst",
|
||||
"bst": "SW5E.StarshipSkillBst",
|
||||
"dat": "SW5E.StarshipSkillDat",
|
||||
"hid": "SW5E.StarshipSkillHid",
|
||||
"imp": "SW5E.StarshipSkillImp",
|
||||
"int": "SW5E.StarshipSkillInt",
|
||||
"man": "SW5E.StarshipSkillMan",
|
||||
"men": "SW5E.StarshipSkillMen",
|
||||
"pat": "SW5E.StarshipSkillPat",
|
||||
"prb": "SW5E.StarshipSkillPrb",
|
||||
"ram": "SW5E.StarshipSkillRam",
|
||||
"reg": "SW5E.StarshipSkillReg",
|
||||
"scn": "SW5E.StarshipSkillScn",
|
||||
"swn": "SW5E.StarshipSkillSwn"
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
@ -610,16 +641,21 @@ SW5E.powerScalingModes = {
|
|||
* @type {Object}
|
||||
*/
|
||||
SW5E.weaponTypes = {
|
||||
"simpleVW": "SW5E.WeaponSimpleVW",
|
||||
"simpleB": "SW5E.WeaponSimpleB",
|
||||
"simpleLW": "SW5E.WeaponSimpleLW",
|
||||
|
||||
"ammo": "SW5E.WeaponAmmo",
|
||||
"improv": "SW5E.WeaponImprov",
|
||||
"martialVW": "SW5E.WeaponMartialVW",
|
||||
"martialB": "SW5E.WeaponMartialB",
|
||||
"martialLW": "SW5E.WeaponMartialLW",
|
||||
"natural": "SW5E.WeaponNatural",
|
||||
"improv": "SW5E.WeaponImprov",
|
||||
"ammo": "SW5E.WeaponAmmo",
|
||||
"siege": "SW5E.WeaponSiege"
|
||||
"natural": "SW5E.WeaponNatural",
|
||||
"siege": "SW5E.WeaponSiege",
|
||||
"simpleVW": "SW5E.WeaponSimpleVW",
|
||||
"simpleB": "SW5E.WeaponSimpleB",
|
||||
"simpleLW": "SW5E.WeaponSimpleLW",
|
||||
"primary (starship)": "SW5E.WeaponPrimarySW",
|
||||
"secondary (starship)": "SW5E.WeaponSecondarySW",
|
||||
"tertiary (starship)": "SW5E.WeaponTertiarySW",
|
||||
"quaternary (starship)": "SW5E.WeaponQuaternarySW"
|
||||
};
|
||||
|
||||
|
||||
|
@ -633,6 +669,7 @@ SW5E.weaponProperties = {
|
|||
"amm": "SW5E.WeaponPropertiesAmm",
|
||||
"aut": "SW5E.WeaponPropertiesAut",
|
||||
"bur": "SW5E.WeaponPropertiesBur",
|
||||
"con": "SW5E.WeaponPropertiesCon",
|
||||
"def": "SW5E.WeaponPropertiesDef",
|
||||
"dex": "SW5E.WeaponPropertiesDex",
|
||||
"dir": "SW5E.WeaponPropertiesDir",
|
||||
|
@ -641,20 +678,27 @@ SW5E.weaponProperties = {
|
|||
"dis": "SW5E.WeaponPropertiesDis",
|
||||
"dpt": "SW5E.WeaponPropertiesDpt",
|
||||
"dou": "SW5E.WeaponPropertiesDou",
|
||||
"exp": "SW5E.WeaponPropertiesExp",
|
||||
"fin": "SW5E.WeaponPropertiesFin",
|
||||
"fix": "SW5E.WeaponPropertiesFix",
|
||||
"foc": "SW5E.WeaponPropertiesFoc",
|
||||
"hvy": "SW5E.WeaponPropertiesHvy",
|
||||
"hid": "SW5E.WeaponPropertiesHid",
|
||||
"hom": "SW5E.WeaponPropertiesHom",
|
||||
"ion": "SW5E.WeaponPropertiesIon",
|
||||
"ken": "SW5E.WeaponPropertiesKen",
|
||||
"lgt": "SW5E.WeaponPropertiesLgt",
|
||||
"lum": "SW5E.WeaponPropertiesLum",
|
||||
"mlt": "SW5E.WeaponPropertiesMlt",
|
||||
"mig": "SW5E.WeaponPropertiesMig",
|
||||
"ovr": "SW5E.WeaponPropertiesOvr",
|
||||
"pic": "SW5E.WeaponPropertiesPic",
|
||||
"pow": "SW5E.WeaponPropertiesPow",
|
||||
"rap": "SW5E.WeaponPropertiesRap",
|
||||
"rch": "SW5E.WeaponPropertiesRch",
|
||||
"rel": "SW5E.WeaponPropertiesRel",
|
||||
"ret": "SW5E.WeaponPropertiesRet",
|
||||
"sat": "SW5E.WeaponPropertiesSat",
|
||||
"shk": "SW5E.WeaponPropertiesShk",
|
||||
"sil": "SW5E.WeaponPropertiesSil",
|
||||
"spc": "SW5E.WeaponPropertiesSpc",
|
||||
|
@ -662,9 +706,24 @@ SW5E.weaponProperties = {
|
|||
"thr": "SW5E.WeaponPropertiesThr",
|
||||
"two": "SW5E.WeaponPropertiesTwo",
|
||||
"ver": "SW5E.WeaponPropertiesVer",
|
||||
"vic": "SW5E.WeaponPropertiesVic"
|
||||
"vic": "SW5E.WeaponPropertiesVic",
|
||||
"zon": "SW5E.WeaponPropertiesZon"
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Define the set of starship weapon size flags which can exist on a weapon
|
||||
* @type {Object}
|
||||
*/
|
||||
SW5E.weaponSizes = {
|
||||
"tiny": "SW5E.SizeTiny",
|
||||
"sm": "SW5E.SizeSmall",
|
||||
"med": "SW5E.SizeMedium",
|
||||
"lg": "SW5E.SizeLarge",
|
||||
"huge": "SW5E.SizeHuge",
|
||||
"grg": "SW5E.SizeGargantuan"
|
||||
};
|
||||
|
||||
// Power Components
|
||||
SW5E.powerComponents = {
|
||||
|
|
|
@ -205,19 +205,27 @@ export default class Item5e extends Item {
|
|||
// Class Feature Items
|
||||
else if ( itemData.type === "classfeature" ) {
|
||||
// labels.classFeature = C.classFeature[data.classFeature];
|
||||
}
|
||||
// Fighting Style Items
|
||||
else if ( itemData.type === "fightingstyle" ) {
|
||||
// labels.fightingstyle = C.fightingstyle[data.fightingstyle];
|
||||
}
|
||||
// Fighting Mastery Items
|
||||
else if ( itemData.type === "fightingmastery" ) {
|
||||
// labels.fightingmastery = C.fightingmastery[data.fightingmastery];
|
||||
}
|
||||
// Lightsaber Form Items
|
||||
else if ( itemData.type === "lightsaberform" ) {
|
||||
// labels.lightsaberform = C.lightsaberform[data.lightsaberform];
|
||||
}
|
||||
}
|
||||
// Deployment Items
|
||||
else if ( itemData.type === "deployment" ) {
|
||||
// labels.deployment = C.deployment[data.deployment];
|
||||
}
|
||||
// Venture Items
|
||||
else if ( itemData.type === "venture" ) {
|
||||
// labels.venture = C.venture[data.venture];
|
||||
}
|
||||
// Fighting Style Items
|
||||
else if ( itemData.type === "fightingstyle" ) {
|
||||
// labels.fightingstyle = C.fightingstyle[data.fightingstyle];
|
||||
}
|
||||
// Fighting Mastery Items
|
||||
else if ( itemData.type === "fightingmastery" ) {
|
||||
// labels.fightingmastery = C.fightingmastery[data.fightingmastery];
|
||||
}
|
||||
// Lightsaber Form Items
|
||||
else if ( itemData.type === "lightsaberform" ) {
|
||||
// labels.lightsaberform = C.lightsaberform[data.lightsaberform];
|
||||
}
|
||||
|
||||
// Equipment Items
|
||||
else if ( itemData.type === "equipment" ) {
|
||||
|
|
|
@ -194,6 +194,10 @@ export default class ItemSheet5e extends ItemSheet {
|
|||
//props.push(labels.background);
|
||||
} else if (item.type === "classfeature") {
|
||||
//props.push(labels.classfeature);
|
||||
} else if (item.type === "deployment") {
|
||||
//props.push(labels.deployment);
|
||||
} else if (item.type === "venture") {
|
||||
//props.push(labels.venture);
|
||||
} else if (item.type === "fightingmastery") {
|
||||
//props.push(labels.fightingmastery);
|
||||
} else if (item.type === "fightingstyle") {
|
||||
|
|
|
@ -6,9 +6,10 @@ export const migrateWorld = async function() {
|
|||
ui.notifications.info(`Applying SW5e System Migration for version ${game.system.data.version}. Please be patient and do not close your game or shut down your server.`, {permanent: true});
|
||||
|
||||
// Migrate World Actors
|
||||
for ( let a of game.actors.entities ) {
|
||||
for await ( let a of game.actors.entities ) {
|
||||
try {
|
||||
const updateData = migrateActorData(a.data);
|
||||
console.log(`Checking Actor entity ${a.name} for migration needs`);
|
||||
const updateData = await migrateActorData(a.data);
|
||||
if ( !isObjectEmpty(updateData) ) {
|
||||
console.log(`Migrating Actor entity ${a.name}`);
|
||||
await a.update(updateData, {enforceTypes: false});
|
||||
|
@ -36,7 +37,7 @@ export const migrateWorld = async function() {
|
|||
// Migrate Actor Override Tokens
|
||||
for ( let s of game.scenes.entities ) {
|
||||
try {
|
||||
const updateData = migrateSceneData(s.data);
|
||||
const updateData = await migrateSceneData(s.data);
|
||||
if ( !isObjectEmpty(updateData) ) {
|
||||
console.log(`Migrating Scene entity ${s.name}`);
|
||||
await s.update(updateData, {enforceTypes: false});
|
||||
|
@ -79,18 +80,18 @@ export const migrateCompendium = async function(pack) {
|
|||
const content = await pack.getContent();
|
||||
|
||||
// Iterate over compendium entries - applying fine-tuned migration functions
|
||||
for ( let ent of content ) {
|
||||
for await ( let ent of content ) {
|
||||
let updateData = {};
|
||||
try {
|
||||
switch (entity) {
|
||||
case "Actor":
|
||||
updateData = migrateActorData(ent.data);
|
||||
updateData = await migrateActorData(ent.data);
|
||||
break;
|
||||
case "Item":
|
||||
updateData = migrateItemData(ent.data);
|
||||
break;
|
||||
case "Scene":
|
||||
updateData = migrateSceneData(ent.data);
|
||||
updateData = await migrateSceneData(ent.data);
|
||||
break;
|
||||
}
|
||||
if ( isObjectEmpty(updateData) ) continue;
|
||||
|
@ -123,7 +124,7 @@ export const migrateCompendium = async function(pack) {
|
|||
* @param {object} actor The actor data object to update
|
||||
* @return {Object} The updateData to apply
|
||||
*/
|
||||
export const migrateActorData = function(actor) {
|
||||
export const migrateActorData = async function(actor) {
|
||||
const updateData = {};
|
||||
|
||||
// Actor Data Updates
|
||||
|
@ -133,10 +134,11 @@ export const migrateActorData = function(actor) {
|
|||
// Migrate Owned Items
|
||||
if ( !!actor.items ) {
|
||||
let hasItemUpdates = false;
|
||||
const items = actor.items.map(i => {
|
||||
const items = await actor.items.reduce(async (memo, i) => {
|
||||
const results = await memo;
|
||||
|
||||
// Migrate the Owned Item
|
||||
let itemUpdate = migrateItemData(i);
|
||||
let itemUpdate = await migrateActorItemData(i, actor);
|
||||
|
||||
// Prepared, Equipped, and Proficient for NPC actors
|
||||
if ( actor.type === "npc" ) {
|
||||
|
@ -148,9 +150,11 @@ export const migrateActorData = function(actor) {
|
|||
// Update the Owned Item
|
||||
if ( !isObjectEmpty(itemUpdate) ) {
|
||||
hasItemUpdates = true;
|
||||
return mergeObject(i, itemUpdate, {enforceTypes: false, inplace: false});
|
||||
} else return i;
|
||||
});
|
||||
console.log(`Migrating Actor ${actor.name}'s ${i.name}`);
|
||||
return [...results, mergeObject(i, itemUpdate, {enforceTypes: false, inplace: false})];
|
||||
} else return [...results, i];
|
||||
}, []);
|
||||
|
||||
if ( hasItemUpdates ) updateData.items = items;
|
||||
}
|
||||
|
||||
|
@ -201,23 +205,38 @@ function cleanActorData(actorData) {
|
|||
*/
|
||||
export const migrateItemData = function(item) {
|
||||
const updateData = {};
|
||||
_migrateItemClassPowerCasting(item, updateData)
|
||||
_migrateItemClassPowerCasting(item, updateData);
|
||||
_migrateItemAttunement(item, updateData);
|
||||
return updateData;
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Migrate a single owned actor Item entity to incorporate latest data model changes
|
||||
* @param item
|
||||
* @param actor
|
||||
*/
|
||||
export const migrateActorItemData = async function(item, actor) {
|
||||
const updateData = {};
|
||||
_migrateItemClassPowerCasting(item, updateData);
|
||||
_migrateItemAttunement(item, updateData);
|
||||
await _migrateItemPower(item, actor, updateData);
|
||||
return updateData;
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Migrate a single Scene entity to incorporate changes to the data model of it's actor data overrides
|
||||
* Return an Object of updateData to be applied
|
||||
* @param {Object} scene The Scene data to Update
|
||||
* @return {Object} The updateData to apply
|
||||
*/
|
||||
export const migrateSceneData = function(scene) {
|
||||
export const migrateSceneData = async function(scene) {
|
||||
const tokens = duplicate(scene.tokens);
|
||||
return {
|
||||
tokens: tokens.map(t => {
|
||||
tokens: await Promise.all(tokens.map(async (t) => {
|
||||
if (!t.actorId || t.actorLink || !t.actorData.data) {
|
||||
t.actorData = {};
|
||||
return t;
|
||||
|
@ -227,11 +246,11 @@ export const migrateSceneData = function(scene) {
|
|||
t.actorId = null;
|
||||
t.actorData = {};
|
||||
} else if ( !t.actorLink ) {
|
||||
const updateData = migrateActorData(token.data.actorData);
|
||||
const updateData = await migrateActorData(token.data.actorData);
|
||||
t.actorData = mergeObject(token.data.actorData, updateData);
|
||||
}
|
||||
return t;
|
||||
})
|
||||
}))
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -250,10 +269,13 @@ function _updateNPCData(actor) {
|
|||
|
||||
let actorData = actor.data;
|
||||
const updateData = {};
|
||||
// check for flag.core
|
||||
// check for flag.core, if not there is no compendium monster so exit
|
||||
const hasSource = actor?.flags?.core?.sourceId !== undefined;
|
||||
if (!hasSource) return actor;
|
||||
// shortcut out if dataVersion flag is set to 1.2.4
|
||||
// shortcut out if dataVersion flag is set to 1.2.4 or higher
|
||||
const hasDataVersion = actor?.flags?.sw5e?.dataVersion !== undefined;
|
||||
if (hasDataVersion && (actor.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", actor.flags.sw5e.dataVersion))) return actor;
|
||||
// Check to see what the source of NPC is
|
||||
const sourceId = actor.flags.core.sourceId;
|
||||
const coreSource = sourceId.substr(0,sourceId.length-17);
|
||||
const core_id = sourceId.substr(sourceId.length-16,16);
|
||||
|
@ -284,11 +306,11 @@ function _updateNPCData(actor) {
|
|||
}
|
||||
}
|
||||
|
||||
// get actor to create new powers
|
||||
const liveActor = game.actors.get(actor._id);
|
||||
|
||||
// create the powers on the actor
|
||||
liveActor.createEmbeddedEntity("OwnedItem", newPowers);
|
||||
|
||||
// let updateActor = await actor.createOwnedItem(newPowers);
|
||||
// set flag to check to see if migration has been done so we don't do it again.
|
||||
liveActor.setFlag("sw5e", "dataVersion", "1.2.4");
|
||||
})
|
||||
|
@ -344,16 +366,16 @@ function _migrateActorPowers(actorData, updateData) {
|
|||
updateData["data.attributes.force.points.value"] = 0;
|
||||
updateData["data.attributes.force.points.min"] = 0;
|
||||
updateData["data.attributes.force.points.max"] = 0;
|
||||
updateData["data.attributes.force.points.temp"] = 0;
|
||||
updateData["data.attributes.force.points.tempmax"] = 0;
|
||||
updateData["data.attributes.force.points.temp"] = null;
|
||||
updateData["data.attributes.force.points.tempmax"] = null;
|
||||
updateData["data.attributes.force.level"] = 0;
|
||||
updateData["data.attributes.tech.known.value"] = 0;
|
||||
updateData["data.attributes.tech.known.max"] = 0;
|
||||
updateData["data.attributes.tech.points.value"] = 0;
|
||||
updateData["data.attributes.tech.points.min"] = 0;
|
||||
updateData["data.attributes.tech.points.max"] = 0;
|
||||
updateData["data.attributes.tech.points.temp"] = 0;
|
||||
updateData["data.attributes.tech.points.tempmax"] = 0;
|
||||
updateData["data.attributes.tech.points.temp"] = null;
|
||||
updateData["data.attributes.tech.points.tempmax"] = null;
|
||||
updateData["data.attributes.tech.level"] = 0;
|
||||
}
|
||||
|
||||
|
@ -453,6 +475,52 @@ function _migrateItemClassPowerCasting(item, updateData) {
|
|||
return updateData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Update an Power Item's data based on compendium
|
||||
* @param {Object} item The data object for an item
|
||||
* @param {Object} actor The data object for the actor owning the item
|
||||
* @private
|
||||
*/
|
||||
async function _migrateItemPower(item, actor, updateData) {
|
||||
// if item is not a power shortcut out
|
||||
if (item.type !== "power") return updateData;
|
||||
|
||||
console.log(`Checking Actor ${actor.name}'s ${item.name} for migration needs`);
|
||||
// check for flag.core, if not there is no compendium power so exit
|
||||
const hasSource = item?.flags?.core?.sourceId !== undefined;
|
||||
if (!hasSource) return updateData;
|
||||
|
||||
// shortcut out if dataVersion flag is set to 1.2.4 or higher
|
||||
const hasDataVersion = item?.flags?.sw5e?.dataVersion !== undefined;
|
||||
if (hasDataVersion && (item.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", item.flags.sw5e.dataVersion))) return updateData;
|
||||
|
||||
// Check to see what the source of Power is
|
||||
const sourceId = item.flags.core.sourceId;
|
||||
const coreSource = sourceId.substr(0, sourceId.length - 17);
|
||||
const core_id = sourceId.substr(sourceId.length - 16, 16);
|
||||
|
||||
//if power type is not force or tech exit out
|
||||
let powerType = "none";
|
||||
if (coreSource === "Compendium.sw5e.forcepowers") powerType = "sw5e.forcepowers";
|
||||
if (coreSource === "Compendium.sw5e.techpowers") powerType = "sw5e.techpowers";
|
||||
if (powerType === "none") return updateData;
|
||||
|
||||
const corePower = duplicate(await game.packs.get(powerType).getEntity(core_id));
|
||||
console.log(`Updating Actor ${actor.name}'s ${item.name} from compendium`);
|
||||
const corePowerData = corePower.data;
|
||||
// copy Core Power Data over original Power
|
||||
updateData["data"] = corePowerData;
|
||||
updateData["flags"] = {"sw5e": {"dataVersion": "1.2.4"}};
|
||||
|
||||
return updateData;
|
||||
|
||||
|
||||
//game.packs.get(powerType).getEntity(core_id).then(corePower => {
|
||||
|
||||
//})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
@ -467,7 +535,6 @@ function _migrateItemAttunement(item, updateData) {
|
|||
return updateData;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,11 +14,11 @@ export const preloadHandlebarsTemplates = async function() {
|
|||
"systems/sw5e/templates/actors/oldActor/parts/actor-inventory.html",
|
||||
"systems/sw5e/templates/actors/oldActor/parts/actor-features.html",
|
||||
"systems/sw5e/templates/actors/oldActor/parts/actor-powerbook.html",
|
||||
"systems/sw5e/templates/actors/oldActor/parts/actor-notes.html",
|
||||
"systems/sw5e/templates/actors/oldActor/parts/actor-notes.html",
|
||||
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-biography.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-core.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-active-effects.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-active-effects.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-features.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-inventory.html",
|
||||
"systems/sw5e/templates/actors/newActor/parts/swalt-force-powerbook.html",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue