forked from GitHub-Mirrors/foundry-sw5e
Update Core 1.2.2
Update core to 1.2.2. Sheets are broken
This commit is contained in:
parent
8f2b0488a4
commit
9c6bd3873e
31 changed files with 189 additions and 114 deletions
|
@ -1180,6 +1180,7 @@ export default class Actor5e extends Actor {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Transform this Actor into another one.
|
||||
*
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue