Update Core 1.2.2

Update core to 1.2.2.  Sheets are broken
This commit is contained in:
supervj 2021-01-18 23:49:04 -05:00
parent 8f2b0488a4
commit 9c6bd3873e
31 changed files with 189 additions and 114 deletions

View file

@ -1180,6 +1180,7 @@ export default class Actor5e extends Actor {
/* -------------------------------------------- */
/**
* Transform this Actor into another one.
*

View file

@ -119,22 +119,44 @@ export default class ActorSheet5e extends ActorSheet {
/* -------------------------------------------- */
/**
* Prepare the display of movement speed data for the Actor
* @param {object} actorData
* Prepare the display of movement speed data for the Actor*
* @param {object} actorData The Actor data being prepared.
* @param {boolean} [largestPrimary=false] Show the largest movement speed as "primary", otherwise show "walk"
* @returns {{primary: string, special: string}}
* @private
*/
_getMovementSpeed(actorData) {
_getMovementSpeed(actorData, largestPrimary=false) {
const movement = actorData.data.attributes.movement || {};
const speeds = [
// Prepare an array of available movement speeds
let speeds = [
[movement.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
[movement.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
].filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
]
if ( largestPrimary ) {
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
}
// Filter and sort speeds on their values
speeds = speeds.filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
// Case 1: Largest as primary
if ( largestPrimary ) {
let primary = speeds.shift();
return {
primary: `${primary ? primary[1] : "0"} ${movement.units}`,
special: speeds.map(s => s[1]).join(", ")
}
}
// Case 2: Walk as primary
else {
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
}
}
}
@ -352,7 +374,7 @@ export default class ActorSheet5e extends ActorSheet {
1: '<i class="fas fa-check"></i>',
2: '<i class="fas fa-check-double"></i>'
};
return icons[level];
return icons[level] || icons[0];
}
/* -------------------------------------------- */

View file

@ -57,6 +57,9 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// Experience Tracking
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class.map(c => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(' ')
}).join(', ');
// Return data for rendering
return sheetData;
@ -86,6 +89,18 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// Item details
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.attunement = {
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
icon: "fa-sun",
cls: "not-attuned",
title: "SW5E.AttunementRequired"
},
[CONFIG.SW5E.attunementTypes.ATTUNED]: {
icon: "fa-sun",
cls: "attuned",
title: "SW5E.AttunementAttuned"
}
}[item.data.attunement];
// Item usage
item.hasUses = item.data.uses && (item.data.uses.max > 0);

View file

@ -115,7 +115,7 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
/** @override */
activateListeners(html) {
super.activateListeners(html);
html.find(".health .rollable").click(this._onRollHealthFormula.bind(this));
html.find(".health .rollable").click(this._onRollHPFormula.bind(this));
}
/* -------------------------------------------- */
@ -125,7 +125,7 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
* @param {Event} event The original click event
* @private
*/
_onRollHealthFormula(event) {
_onRollHPFormula(event) {
event.preventDefault();
const formula = this.actor.data.data.attributes.hp.formula;
if ( !formula ) return;

View file

@ -56,6 +56,13 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData, largestPrimary=true) {
return super._getMovementSpeed(actorData, largestPrimary);
}
/* -------------------------------------------- */
/**
* Prepare items that are mounted to a vehicle and require one or more crew
* to operate.
@ -86,13 +93,6 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData) {
return {primary: "", special: ""};
}
/* -------------------------------------------- */
/**
* Organize Owned Items for rendering the Vehicle sheet.
* @private

View file

@ -119,22 +119,44 @@ export default class ActorSheet5e extends ActorSheet {
/* -------------------------------------------- */
/**
* Prepare the display of movement speed data for the Actor
* @param {object} actorData
* Prepare the display of movement speed data for the Actor*
* @param {object} actorData The Actor data being prepared.
* @param {boolean} [largestPrimary=false] Show the largest movement speed as "primary", otherwise show "walk"
* @returns {{primary: string, special: string}}
* @private
*/
_getMovementSpeed(actorData) {
_getMovementSpeed(actorData, largestPrimary=false) {
const movement = actorData.data.attributes.movement || {};
const speeds = [
// Prepare an array of available movement speeds
let speeds = [
[movement.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
[movement.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
].filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
]
if ( largestPrimary ) {
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
}
// Filter and sort speeds on their values
speeds = speeds.filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
// Case 1: Largest as primary
if ( largestPrimary ) {
let primary = speeds.shift();
return {
primary: `${primary ? primary[1] : "0"} ${movement.units}`,
special: speeds.map(s => s[1]).join(", ")
}
}
// Case 2: Walk as primary
else {
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
}
}
}
@ -352,7 +374,7 @@ export default class ActorSheet5e extends ActorSheet {
1: '<i class="fas fa-check"></i>',
2: '<i class="fas fa-check-double"></i>'
};
return icons[level];
return icons[level] || icons[0];
}
/* -------------------------------------------- */

View file

@ -46,6 +46,9 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
// Experience Tracking
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class.map(c => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(' ')
}).join(', ');
// Return data for rendering
return sheetData;
@ -76,12 +79,12 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.attunement = {
1: {
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
icon: "fa-sun",
cls: "not-attuned",
title: "SW5E.AttunementRequired"
},
2: {
[CONFIG.SW5E.attunementTypes.ATTUNED]: {
icon: "fa-sun",
cls: "attuned",
title: "SW5E.AttunementAttuned"

View file

@ -56,6 +56,13 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData, largestPrimary=true) {
return super._getMovementSpeed(actorData, largestPrimary);
}
/* -------------------------------------------- */
/**
* Prepare items that are mounted to a vehicle and require one or more crew
* to operate.
@ -86,13 +93,6 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData) {
return {primary: "", special: ""};
}
/* -------------------------------------------- */
/**
* Organize Owned Items for rendering the Vehicle sheet.
* @private

View file

@ -127,10 +127,13 @@ export default class AbilityUseDialog extends Dialog {
});
}
const canCast = powerLevels.some(l => l.hasSlots);
if ( !canCast ) data.errors.push(game.i18n.format("SW5E.PowerCastNoSlots", {
level: CONFIG.SW5E.powerLevels[lvl],
name: data.item.name
}));
// Return merged data
data = mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
if ( !canCast ) data.errors.push("SW5E.PowerCastNoSlots");
// Merge power casting data
return mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
}
/* -------------------------------------------- */

View file

@ -49,7 +49,7 @@ export default class TraitSelector extends FormApplication {
}
// Return data
return {
return {
allowCustom: this.options.allowCustom,
choices: choices,
custom: attr ? attr.custom : ""
@ -85,4 +85,4 @@ export default class TraitSelector extends FormApplication {
// Update the object
this.object.update(updateData);
}
}
}

View file

@ -13,7 +13,7 @@ export const _getInitiativeFormula = function(combatant) {
let nd = 1;
let mods = "";
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r=1";
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r1=1";
if (actor.getFlag("sw5e", "initiativeAdv")) {
nd = 2;
mods += "kh";

View file

@ -4,14 +4,13 @@ import {ClassFeatures} from "./classFeatures.js"
export const SW5E = {};
// ASCII Artwork
SW5E.ASCII = `__________________________________________
_
| |
___| |_ __ _ _ ____ ____ _ _ __ ___
/ __| __/ _\\ | |__\\ \\ /\\ / / _\\ | |__/ __|
\\__ \\ || (_) | | \\ \V \V / (_) | | \\__ \\
|___/\\__\\__/_|_| \\_/\\_/ \\__/_|_| |___/
__________________________________________`;
SW5E.ASCII = `
___________ ___________
/ _____/ \\ / \\ ____/ ____
\\_____ \\\\ \\/\\/ /____ \\_/ __ \\
/ \\\\ // \\ ___/
\\______ / \\__/\\ //______ /\\__ >
\\/ \\/ \\/ \\/ `;
/**
@ -315,6 +314,7 @@ SW5E.damageResistanceTypes = duplicate(SW5E.damageTypes);
/* -------------------------------------------- */
// armor Types
SW5E.armorPropertiesTypes = {
"Absorptive": "SW5E.ArmorProperAbsorptive",
@ -349,6 +349,19 @@ SW5E.armorPropertiesTypes = {
"Versatile": "SW5E.ArmorProperVersatile"
};
/**
* The valid units of measure for movement distances in the game system.
* By default this uses the imperial units of feet and miles.
* @type {Object<string,string>}
*/
SW5E.movementTypes = {
"burrow": "SW5E.MovementBurrow",
"climb": "SW5E.MovementClimb",
"fly": "SW5E.MovementFly",
"swim": "SW5E.MovementSwim",
"walk": "SW5E.MovementWalk",
}
/**
* The valid units of measure for movement distances in the game system.
* By default this uses the imperial units of feet and miles.

View file

@ -1,6 +1,5 @@
import {simplifyRollFormula, d20Roll, damageRoll} from "../dice.js";
import AbilityUseDialog from "../apps/ability-use-dialog.js";
import AbilityTemplate from "../pixi/ability-template.js";
/**
* Override and extend the basic :class:`Item` implementation
@ -419,7 +418,7 @@ export default class Item5e extends Item {
// Handle power upcasting
if ( requirePowerSlot ) {
const slotLevel = configuration.level;
const powerLevel = slotLevel === "pact" ? actor.data.data.powerss.pact.level : parseInt(slotLevel);
const powerLevel = slotLevel === "pact" ? actor.data.data.powers.pact.level : 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
@ -898,6 +897,7 @@ export default class Item5e extends Item {
* Place a damage roll using an item (weapon, feat, power, or equipment)
* Rely upon the damageRoll logic for the core implementation.
* @param {MouseEvent} [event] An event which triggered this roll, if any
* @param {boolean} [critical] Should damage be rolled as a critical hit?
* @param {number} [powerLevel] If the item is a power, override the level for damage scaling
* @param {boolean} [versatile] If the item is a weapon, roll damage using the versatile formula
* @param {object} [options] Additional options passed to the damageRoll function
@ -942,9 +942,9 @@ export default class Item5e extends Item {
// Scale damage from up-casting powers
if ( (this.data.type === "power") ) {
if ( (itemData.scaling.mode === "cantrip") ) {
if ( (itemData.scaling.mode === "atwill") ) {
const level = this.actor.data.type === "character" ? actorData.details.level : actorData.details.powerLevel;
this._scaleCantripDamage(parts, itemData.scaling.formula, level, rollData);
this._scaleAtWillDamage(parts, itemData.scaling.formula, level, rollData);
}
else if ( powerLevel && (itemData.scaling.mode === "level") && itemData.scaling.formula ) {
const scaling = itemData.scaling.formula;

View file

@ -61,6 +61,9 @@ export default class ItemSheet5e extends ItemSheet {
data.isFlatDC = getProperty(data.item.data, "save.scaling") === "flat";
data.isLine = ["line", "wall"].includes(data.item.data.target?.type);
// Original maximum uses formula
if ( this.item._data.data?.uses?.max ) data.data.uses.max = this.item._data.data.uses.max;
// Vehicles
data.isCrewed = data.item.data.activation?.type === 'crew';
data.isMountable = this._isItemMountable(data.item);
@ -91,7 +94,7 @@ export default class ItemSheet5e extends ItemSheet {
ammo[i.id] = `${i.name} (${i.data.data.quantity})`;
}
return ammo;
}, {});
}, {[item._id]: `${item.name} (${item.data.quantity})`});
}
// Attributes
@ -335,7 +338,7 @@ export default class ItemSheet5e extends ItemSheet {
// Render the Trait Selector dialog
new TraitSelector(this.item, {
name: a.dataset.edit,
name: a.dataset.target,
title: label.innerText,
choices: Object.entries(CONFIG.SW5E.skills).reduce((obj, e) => {
if ( choices.includes(e[0] ) ) obj[e[0]] = e[1];

View file

@ -127,7 +127,6 @@ export const migrateActorData = function(actor) {
const updateData = {};
// Actor Data Updates
_migrateActorBonuses(actor, updateData);
_migrateActorMovement(actor, updateData);
_migrateActorSenses(actor, updateData);
@ -229,28 +228,14 @@ export const migrateSceneData = function(scene) {
/* Low level migration utilities
/* -------------------------------------------- */
/**
* Migrate the actor bonuses object
* @private
*/
function _migrateActorBonuses(actor, updateData) {
const b = game.system.model.Actor.character.bonuses;
for ( let k of Object.keys(actor.data.bonuses || {}) ) {
if ( k in b ) updateData[`data.bonuses.${k}`] = b[k];
else updateData[`data.bonuses.-=${k}`] = null;
}
}
/* -------------------------------------------- */
/**
* Migrate the actor speed string to movement object
* @private
*/
function _migrateActorMovement(actor, updateData) {
const ad = actor.data;
const old = ad?.attributes?.speed?.value;
if ( old === undefined ) return;
const old = actor.type === 'vehicle' ? ad?.attributes?.speed : ad?.attributes?.speed?.value;
if ( typeof old !== "string" ) return;
const s = (old || "").split(" ");
if ( s.length > 0 ) updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
updateData["data.attributes.-=speed"] = null;
@ -302,7 +287,7 @@ function _migrateActorSenses(actor, updateData) {
*/
function _migrateItemAttunement(item, updateData) {
if ( item.data.attuned === undefined ) return;
updateData["data.attunement"] = 0;
updateData["data.attunement"] = CONFIG.SW5E.attunementTypes.NONE;
updateData["data.-=attuned"] = null;
return updateData;
}

View file

@ -29,8 +29,8 @@ export default class AbilityTemplate extends MeasuredTemplate {
// Additional type-specific data
switch ( templateShape ) {
case "cone": // 5e cone RAW should be 53.13 degrees
templateData.angle = 53.13;
case "cone":
templateData.angle = CONFIG.MeasuredTemplate.defaults.angle;
break;
case "rect": // 5e rectangular AoEs are always cubes
templateData.distance = Math.hypot(target.value, target.value);