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
|
@ -426,11 +426,6 @@
|
||||||
border: none;
|
border: none;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
h4 {
|
|
||||||
margin: 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1180,6 +1180,7 @@ export default class Actor5e extends Actor {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform this Actor into another one.
|
* 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
|
* Prepare the display of movement speed data for the Actor*
|
||||||
* @param {object} actorData
|
* @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}}
|
* @returns {{primary: string, special: string}}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getMovementSpeed(actorData) {
|
_getMovementSpeed(actorData, largestPrimary=false) {
|
||||||
const movement = actorData.data.attributes.movement || {};
|
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.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
|
||||||
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
|
[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.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
|
||||||
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
|
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
|
||||||
].filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
|
]
|
||||||
return {
|
if ( largestPrimary ) {
|
||||||
primary: `${movement.walk || 0} ${movement.units}`,
|
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
|
||||||
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
|
}
|
||||||
|
|
||||||
|
// 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>',
|
1: '<i class="fas fa-check"></i>',
|
||||||
2: '<i class="fas fa-check-double"></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
|
// Experience Tracking
|
||||||
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
|
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
|
||||||
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
|
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 data for rendering
|
||||||
return sheetData;
|
return sheetData;
|
||||||
|
@ -86,6 +89,18 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
|
||||||
// Item details
|
// Item details
|
||||||
item.img = item.img || DEFAULT_TOKEN;
|
item.img = item.img || DEFAULT_TOKEN;
|
||||||
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
|
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 usage
|
||||||
item.hasUses = item.data.uses && (item.data.uses.max > 0);
|
item.hasUses = item.data.uses && (item.data.uses.max > 0);
|
||||||
|
|
|
@ -115,7 +115,7 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
|
||||||
/** @override */
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.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
|
* @param {Event} event The original click event
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onRollHealthFormula(event) {
|
_onRollHPFormula(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const formula = this.actor.data.data.attributes.hp.formula;
|
const formula = this.actor.data.data.attributes.hp.formula;
|
||||||
if ( !formula ) return;
|
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
|
* Prepare items that are mounted to a vehicle and require one or more crew
|
||||||
* to operate.
|
* 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.
|
* Organize Owned Items for rendering the Vehicle sheet.
|
||||||
* @private
|
* @private
|
||||||
|
|
|
@ -119,22 +119,44 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the display of movement speed data for the Actor
|
* Prepare the display of movement speed data for the Actor*
|
||||||
* @param {object} actorData
|
* @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}}
|
* @returns {{primary: string, special: string}}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getMovementSpeed(actorData) {
|
_getMovementSpeed(actorData, largestPrimary=false) {
|
||||||
const movement = actorData.data.attributes.movement || {};
|
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.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
|
||||||
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
|
[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.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
|
||||||
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
|
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
|
||||||
].filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
|
]
|
||||||
return {
|
if ( largestPrimary ) {
|
||||||
primary: `${movement.walk || 0} ${movement.units}`,
|
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
|
||||||
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
|
}
|
||||||
|
|
||||||
|
// 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>',
|
1: '<i class="fas fa-check"></i>',
|
||||||
2: '<i class="fas fa-check-double"></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
|
// Experience Tracking
|
||||||
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
|
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
|
||||||
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
|
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 data for rendering
|
||||||
return sheetData;
|
return sheetData;
|
||||||
|
@ -76,12 +79,12 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
|
||||||
item.img = item.img || DEFAULT_TOKEN;
|
item.img = item.img || DEFAULT_TOKEN;
|
||||||
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
|
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
|
||||||
item.attunement = {
|
item.attunement = {
|
||||||
1: {
|
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
|
||||||
icon: "fa-sun",
|
icon: "fa-sun",
|
||||||
cls: "not-attuned",
|
cls: "not-attuned",
|
||||||
title: "SW5E.AttunementRequired"
|
title: "SW5E.AttunementRequired"
|
||||||
},
|
},
|
||||||
2: {
|
[CONFIG.SW5E.attunementTypes.ATTUNED]: {
|
||||||
icon: "fa-sun",
|
icon: "fa-sun",
|
||||||
cls: "attuned",
|
cls: "attuned",
|
||||||
title: "SW5E.AttunementAttuned"
|
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
|
* Prepare items that are mounted to a vehicle and require one or more crew
|
||||||
* to operate.
|
* 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.
|
* Organize Owned Items for rendering the Vehicle sheet.
|
||||||
* @private
|
* @private
|
||||||
|
|
|
@ -127,10 +127,13 @@ export default class AbilityUseDialog extends Dialog {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const canCast = powerLevels.some(l => l.hasSlots);
|
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
|
// Merge power casting data
|
||||||
data = mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
|
return mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
|
||||||
if ( !canCast ) data.errors.push("SW5E.PowerCastNoSlots");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default class TraitSelector extends FormApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return data
|
// Return data
|
||||||
return {
|
return {
|
||||||
allowCustom: this.options.allowCustom,
|
allowCustom: this.options.allowCustom,
|
||||||
choices: choices,
|
choices: choices,
|
||||||
custom: attr ? attr.custom : ""
|
custom: attr ? attr.custom : ""
|
||||||
|
@ -85,4 +85,4 @@ export default class TraitSelector extends FormApplication {
|
||||||
// Update the object
|
// Update the object
|
||||||
this.object.update(updateData);
|
this.object.update(updateData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const _getInitiativeFormula = function(combatant) {
|
||||||
let nd = 1;
|
let nd = 1;
|
||||||
let mods = "";
|
let mods = "";
|
||||||
|
|
||||||
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r=1";
|
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r1=1";
|
||||||
if (actor.getFlag("sw5e", "initiativeAdv")) {
|
if (actor.getFlag("sw5e", "initiativeAdv")) {
|
||||||
nd = 2;
|
nd = 2;
|
||||||
mods += "kh";
|
mods += "kh";
|
||||||
|
|
|
@ -4,14 +4,13 @@ import {ClassFeatures} from "./classFeatures.js"
|
||||||
export const SW5E = {};
|
export const SW5E = {};
|
||||||
|
|
||||||
// ASCII Artwork
|
// ASCII Artwork
|
||||||
SW5E.ASCII = `__________________________________________
|
SW5E.ASCII = `
|
||||||
_
|
___________ ___________
|
||||||
| |
|
/ _____/ \\ / \\ ____/ ____
|
||||||
___| |_ __ _ _ ____ ____ _ _ __ ___
|
\\_____ \\\\ \\/\\/ /____ \\_/ __ \\
|
||||||
/ __| __/ _\\ | |__\\ \\ /\\ / / _\\ | |__/ __|
|
/ \\\\ // \\ ___/
|
||||||
\\__ \\ || (_) | | \\ \V \V / (_) | | \\__ \\
|
\\______ / \\__/\\ //______ /\\__ >
|
||||||
|___/\\__\\__/_|_| \\_/\\_/ \\__/_|_| |___/
|
\\/ \\/ \\/ \\/ `;
|
||||||
__________________________________________`;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,6 +314,7 @@ SW5E.damageResistanceTypes = duplicate(SW5E.damageTypes);
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
// armor Types
|
// armor Types
|
||||||
SW5E.armorPropertiesTypes = {
|
SW5E.armorPropertiesTypes = {
|
||||||
"Absorptive": "SW5E.ArmorProperAbsorptive",
|
"Absorptive": "SW5E.ArmorProperAbsorptive",
|
||||||
|
@ -349,6 +349,19 @@ SW5E.armorPropertiesTypes = {
|
||||||
"Versatile": "SW5E.ArmorProperVersatile"
|
"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.
|
* The valid units of measure for movement distances in the game system.
|
||||||
* By default this uses the imperial units of feet and miles.
|
* By default this uses the imperial units of feet and miles.
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {simplifyRollFormula, d20Roll, damageRoll} from "../dice.js";
|
import {simplifyRollFormula, d20Roll, damageRoll} from "../dice.js";
|
||||||
import AbilityUseDialog from "../apps/ability-use-dialog.js";
|
import AbilityUseDialog from "../apps/ability-use-dialog.js";
|
||||||
import AbilityTemplate from "../pixi/ability-template.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override and extend the basic :class:`Item` implementation
|
* Override and extend the basic :class:`Item` implementation
|
||||||
|
@ -419,7 +418,7 @@ export default class Item5e extends Item {
|
||||||
// Handle power upcasting
|
// Handle power upcasting
|
||||||
if ( requirePowerSlot ) {
|
if ( requirePowerSlot ) {
|
||||||
const slotLevel = configuration.level;
|
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) {
|
if (powerLevel !== id.level) {
|
||||||
const upcastData = mergeObject(this.data, {"data.level": powerLevel}, {inplace: false});
|
const upcastData = mergeObject(this.data, {"data.level": powerLevel}, {inplace: false});
|
||||||
item = this.constructor.createOwned(upcastData, actor); // Replace the item with an upcast version
|
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)
|
* Place a damage roll using an item (weapon, feat, power, or equipment)
|
||||||
* Rely upon the damageRoll logic for the core implementation.
|
* Rely upon the damageRoll logic for the core implementation.
|
||||||
* @param {MouseEvent} [event] An event which triggered this roll, if any
|
* @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 {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 {boolean} [versatile] If the item is a weapon, roll damage using the versatile formula
|
||||||
* @param {object} [options] Additional options passed to the damageRoll function
|
* @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
|
// Scale damage from up-casting powers
|
||||||
if ( (this.data.type === "power") ) {
|
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;
|
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 ) {
|
else if ( powerLevel && (itemData.scaling.mode === "level") && itemData.scaling.formula ) {
|
||||||
const scaling = 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.isFlatDC = getProperty(data.item.data, "save.scaling") === "flat";
|
||||||
data.isLine = ["line", "wall"].includes(data.item.data.target?.type);
|
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
|
// Vehicles
|
||||||
data.isCrewed = data.item.data.activation?.type === 'crew';
|
data.isCrewed = data.item.data.activation?.type === 'crew';
|
||||||
data.isMountable = this._isItemMountable(data.item);
|
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})`;
|
ammo[i.id] = `${i.name} (${i.data.data.quantity})`;
|
||||||
}
|
}
|
||||||
return ammo;
|
return ammo;
|
||||||
}, {});
|
}, {[item._id]: `${item.name} (${item.data.quantity})`});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
|
@ -335,7 +338,7 @@ export default class ItemSheet5e extends ItemSheet {
|
||||||
|
|
||||||
// Render the Trait Selector dialog
|
// Render the Trait Selector dialog
|
||||||
new TraitSelector(this.item, {
|
new TraitSelector(this.item, {
|
||||||
name: a.dataset.edit,
|
name: a.dataset.target,
|
||||||
title: label.innerText,
|
title: label.innerText,
|
||||||
choices: Object.entries(CONFIG.SW5E.skills).reduce((obj, e) => {
|
choices: Object.entries(CONFIG.SW5E.skills).reduce((obj, e) => {
|
||||||
if ( choices.includes(e[0] ) ) obj[e[0]] = e[1];
|
if ( choices.includes(e[0] ) ) obj[e[0]] = e[1];
|
||||||
|
|
|
@ -127,7 +127,6 @@ export const migrateActorData = function(actor) {
|
||||||
const updateData = {};
|
const updateData = {};
|
||||||
|
|
||||||
// Actor Data Updates
|
// Actor Data Updates
|
||||||
_migrateActorBonuses(actor, updateData);
|
|
||||||
_migrateActorMovement(actor, updateData);
|
_migrateActorMovement(actor, updateData);
|
||||||
_migrateActorSenses(actor, updateData);
|
_migrateActorSenses(actor, updateData);
|
||||||
|
|
||||||
|
@ -229,28 +228,14 @@ export const migrateSceneData = function(scene) {
|
||||||
/* Low level migration utilities
|
/* 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
|
* Migrate the actor speed string to movement object
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function _migrateActorMovement(actor, updateData) {
|
function _migrateActorMovement(actor, updateData) {
|
||||||
const ad = actor.data;
|
const ad = actor.data;
|
||||||
const old = ad?.attributes?.speed?.value;
|
const old = actor.type === 'vehicle' ? ad?.attributes?.speed : ad?.attributes?.speed?.value;
|
||||||
if ( old === undefined ) return;
|
if ( typeof old !== "string" ) return;
|
||||||
const s = (old || "").split(" ");
|
const s = (old || "").split(" ");
|
||||||
if ( s.length > 0 ) updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
|
if ( s.length > 0 ) updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
|
||||||
updateData["data.attributes.-=speed"] = null;
|
updateData["data.attributes.-=speed"] = null;
|
||||||
|
@ -302,7 +287,7 @@ function _migrateActorSenses(actor, updateData) {
|
||||||
*/
|
*/
|
||||||
function _migrateItemAttunement(item, updateData) {
|
function _migrateItemAttunement(item, updateData) {
|
||||||
if ( item.data.attuned === undefined ) return;
|
if ( item.data.attuned === undefined ) return;
|
||||||
updateData["data.attunement"] = 0;
|
updateData["data.attunement"] = CONFIG.SW5E.attunementTypes.NONE;
|
||||||
updateData["data.-=attuned"] = null;
|
updateData["data.-=attuned"] = null;
|
||||||
return updateData;
|
return updateData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
||||||
|
|
||||||
// Additional type-specific data
|
// Additional type-specific data
|
||||||
switch ( templateShape ) {
|
switch ( templateShape ) {
|
||||||
case "cone": // 5e cone RAW should be 53.13 degrees
|
case "cone":
|
||||||
templateData.angle = 53.13;
|
templateData.angle = CONFIG.MeasuredTemplate.defaults.angle;
|
||||||
break;
|
break;
|
||||||
case "rect": // 5e rectangular AoEs are always cubes
|
case "rect": // 5e rectangular AoEs are always cubes
|
||||||
templateData.distance = Math.hypot(target.value, target.value);
|
templateData.distance = Math.hypot(target.value, target.value);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1370,7 +1370,7 @@ body {
|
||||||
}
|
}
|
||||||
.sw5e.chat-card .card-footer span {
|
.sw5e.chat-card .card-footer span {
|
||||||
border-right: 2px groove #FFF;
|
border-right: 2px groove #FFF;
|
||||||
padding: 0 5px 0 0;
|
padding: 0 3px 0 0;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
.sw5e.chat-card .card-footer span:last-child {
|
.sw5e.chat-card .card-footer span:last-child {
|
||||||
|
@ -1784,4 +1784,4 @@ a.entity-link i::before {
|
||||||
top: 2px;
|
top: 2px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
width: 15px;
|
width: 15px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,7 +392,7 @@ button:focus {
|
||||||
}
|
}
|
||||||
.sw5e.chat-card .card-footer span {
|
.sw5e.chat-card .card-footer span {
|
||||||
border-right: 2px groove #FFF;
|
border-right: 2px groove #FFF;
|
||||||
padding: 0 4px 0 0;
|
padding: 0 3px 0 0;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
.sw5e.chat-card .card-footer span:last-child {
|
.sw5e.chat-card .card-footer span:last-child {
|
||||||
|
|
11
sw5e.js
11
sw5e.js
|
@ -44,7 +44,7 @@ import * as migrations from "./module/migration.js";
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
Hooks.once("init", function() {
|
Hooks.once("init", function() {
|
||||||
console.log(`SW5e | Initializing Star Wars 5th Edition System\n${SW5E.ASCII}`);
|
console.log(`SW5e | Initializing SW5E System\n${SW5E.ASCII}`);
|
||||||
|
|
||||||
// Create a SW5E namespace within the game global
|
// Create a SW5E namespace within the game global
|
||||||
game.sw5e = {
|
game.sw5e = {
|
||||||
|
@ -80,7 +80,10 @@ Hooks.once("init", function() {
|
||||||
CONFIG.Actor.entityClass = Actor5e;
|
CONFIG.Actor.entityClass = Actor5e;
|
||||||
CONFIG.Item.entityClass = Item5e;
|
CONFIG.Item.entityClass = Item5e;
|
||||||
CONFIG.time.roundTime = 6;
|
CONFIG.time.roundTime = 6;
|
||||||
|
|
||||||
|
// 5e cone RAW should be 53.13 degrees
|
||||||
|
CONFIG.MeasuredTemplate.defaults.angle = 53.13;
|
||||||
|
|
||||||
// Add DND5e namespace for module compatability
|
// Add DND5e namespace for module compatability
|
||||||
game.dnd5e = game.sw5e;
|
game.dnd5e = game.sw5e;
|
||||||
CONFIG.DND5E = CONFIG.SW5E;
|
CONFIG.DND5E = CONFIG.SW5E;
|
||||||
|
@ -145,7 +148,7 @@ Hooks.once("setup", function() {
|
||||||
"abilities", "abilityAbbreviations", "abilityActivationTypes", "abilityConsumptionTypes", "actorSizes", "alignments",
|
"abilities", "abilityAbbreviations", "abilityActivationTypes", "abilityConsumptionTypes", "actorSizes", "alignments",
|
||||||
"armorProficiencies", "armorPropertiesTypes", "conditionTypes", "consumableTypes", "cover", "currencies", "damageResistanceTypes",
|
"armorProficiencies", "armorPropertiesTypes", "conditionTypes", "consumableTypes", "cover", "currencies", "damageResistanceTypes",
|
||||||
"damageTypes", "distanceUnits", "equipmentTypes", "healingTypes", "itemActionTypes", "languages",
|
"damageTypes", "distanceUnits", "equipmentTypes", "healingTypes", "itemActionTypes", "languages",
|
||||||
"limitedUsePeriods", "movementUnits", "polymorphSettings", "proficiencyLevels", "senses", "skills",
|
"limitedUsePeriods", "movementTypes", "movementUnits", "polymorphSettings", "proficiencyLevels", "senses", "skills",
|
||||||
"powerComponents", "powerLevels", "powerPreparationModes", "powerScalingModes", "powerSchools", "targetTypes",
|
"powerComponents", "powerLevels", "powerPreparationModes", "powerScalingModes", "powerSchools", "targetTypes",
|
||||||
"timePeriods", "toolProficiencies", "weaponProficiencies", "weaponProperties", "weaponTypes"
|
"timePeriods", "toolProficiencies", "weaponProficiencies", "weaponProperties", "weaponTypes"
|
||||||
];
|
];
|
||||||
|
@ -187,7 +190,7 @@ Hooks.once("ready", function() {
|
||||||
// Determine whether a system migration is required and feasible
|
// Determine whether a system migration is required and feasible
|
||||||
if ( !game.user.isGM ) return;
|
if ( !game.user.isGM ) return;
|
||||||
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
|
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
|
||||||
const NEEDS_MIGRATION_VERSION = "1.2.0";
|
const NEEDS_MIGRATION_VERSION = "1.2.1";
|
||||||
const COMPATIBLE_MIGRATION_VERSION = 0.80;
|
const COMPATIBLE_MIGRATION_VERSION = 0.80;
|
||||||
const needsMigration = currentVersion && isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion);
|
const needsMigration = currentVersion && isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion);
|
||||||
if ( !needsMigration ) return;
|
if ( !needsMigration ) return;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "sw5e",
|
"name": "sw5e",
|
||||||
"title": "SW 5th Edition",
|
"title": "SW 5th Edition",
|
||||||
"description": "A comprehensive game system for running games of SW 5th Edition in the Foundry VTT environment.",
|
"description": "A comprehensive game system for running games of SW 5th Edition in the Foundry VTT environment.",
|
||||||
"version": "R1-A1",
|
"version": "1.2.2",
|
||||||
"author": "Dev Team",
|
"author": "Dev Team",
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
"esmodules": ["sw5e.js"],
|
"esmodules": ["sw5e.js"],
|
||||||
|
|
|
@ -43,6 +43,15 @@
|
||||||
"init": {
|
"init": {
|
||||||
"value": 0,
|
"value": 0,
|
||||||
"bonus": 0
|
"bonus": 0
|
||||||
|
},
|
||||||
|
"movement": {
|
||||||
|
"burrow": 0,
|
||||||
|
"climb": 0,
|
||||||
|
"fly": 0,
|
||||||
|
"swim": 0,
|
||||||
|
"walk": 30,
|
||||||
|
"units": "ft",
|
||||||
|
"hover": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
|
@ -76,15 +85,6 @@
|
||||||
},
|
},
|
||||||
"creature": {
|
"creature": {
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"movement": {
|
|
||||||
"burrow": 0,
|
|
||||||
"climb": 0,
|
|
||||||
"fly": 0,
|
|
||||||
"swim": 0,
|
|
||||||
"walk": 30,
|
|
||||||
"units": "ft",
|
|
||||||
"hover": false
|
|
||||||
},
|
|
||||||
"senses": {
|
"senses": {
|
||||||
"darkvision": 0,
|
"darkvision": 0,
|
||||||
"blindsight": 0,
|
"blindsight": 0,
|
||||||
|
@ -94,9 +94,6 @@
|
||||||
"special": ""
|
"special": ""
|
||||||
},
|
},
|
||||||
"powercasting": "none",
|
"powercasting": "none",
|
||||||
"speed": {
|
|
||||||
"_deprecated": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
"alignment": "",
|
"alignment": "",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<input name="name" type="text" value="{{actor.name}}" placeholder="{{ localize 'SW5E.Name' }}" />
|
<input name="name" type="text" value="{{actor.name}}" placeholder="{{ localize 'SW5E.Name' }}" />
|
||||||
</h1>
|
</h1>
|
||||||
<div class="level-experience">
|
<div class="level-experience">
|
||||||
<div class="charlevel">
|
<div class="charlevel" title="{{multiclassLabels}}">
|
||||||
{{ localize "SW5E.Level" }} {{data.details.level}} {{classLabels}}
|
{{ localize "SW5E.Level" }} {{data.details.level}} {{classLabels}}
|
||||||
</div>
|
</div>
|
||||||
{{#unless disableExperience}}
|
{{#unless disableExperience}}
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<section>
|
<section>
|
||||||
<h1>Hit Points</h1>
|
<h1>Hit Points</h1>
|
||||||
<div class="attribute-value multiple">
|
<div class="attribute-value multiple">
|
||||||
|
<h4 class="attribute-name box-title rollable">{{ localize "SW5E.Health" }}</h4>
|
||||||
<input name="data.attributes.hp.value" type="text" value="{{data.attributes.hp.value}}"
|
<input name="data.attributes.hp.value" type="text" value="{{data.attributes.hp.value}}"
|
||||||
data-dtype="Number" placeholder="10" class="value-number" />
|
data-dtype="Number" placeholder="10" class="value-number" />
|
||||||
<span class="value-separator">/</span>
|
<span class="value-separator">/</span>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label class="{{#unless data.traits.senses}}inactive{{/unless}}">
|
<label class="{{#unless data.traits.senses}}inactive{{/unless}}">
|
||||||
{{#unless isVehicle}}
|
{{#unless isVehicle}}
|
||||||
<label>{{localize "SW5E.Senses"}}</label>
|
<label>{{localize "SW5E.Senses"}}</label>
|
||||||
<a class="config-button" data-action="senses" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
<a class="config-button" data-action="senses" title="{{localize 'SW5E.SensesConfig'}}"><i class="fas fa-cog"></i></a>
|
||||||
<ul class="traits-list">
|
<ul class="traits-list">
|
||||||
{{#each senses as |v k|}}
|
{{#each senses as |v k|}}
|
||||||
<li class="tag {{k}}">{{v}}</li>
|
<li class="tag {{k}}">{{v}}</li>
|
||||||
|
|
|
@ -55,11 +55,17 @@
|
||||||
placeholder="—" value="{{data.attributes.ac.motionless}}">
|
placeholder="—" value="{{data.attributes.ac.motionless}}">
|
||||||
</footer>
|
</footer>
|
||||||
</li>
|
</li>
|
||||||
<li class="attribute">
|
<li class="attribute movement">
|
||||||
<h4 class="attribute-name box-title">{{localize 'SW5E.Speed'}}</h4>
|
<h4 class="attribute-name box-title">
|
||||||
|
{{ localize "SW5E.Movement" }}
|
||||||
|
<a class="config-button" data-action="movement" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
||||||
|
</h4>
|
||||||
<div class="attribute-value">
|
<div class="attribute-value">
|
||||||
<input name="data.attributes.speed" type="text" placeholder="—" value="{{data.attributes.speed}}"/>
|
<span>{{movement.primary}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<footer class="attribute-footer">
|
||||||
|
<span>{{movement.special}}</span>
|
||||||
|
</footer>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<aside class="header-exp flexcol">
|
<aside class="header-exp flexcol">
|
||||||
<div class="charlevel">
|
<div class="charlevel" title="{{multiclassLabels}}">
|
||||||
<label>{{ localize "SW5E.Level" }} {{data.details.level}}</label>
|
<label>{{ localize "SW5E.Level" }} {{data.details.level}}</label>
|
||||||
<span class="levels">{{classLabels}}</span>
|
<span class="levels">{{classLabels}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
{{#unless isVehicle}}
|
{{#unless isVehicle}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{localize "SW5E.Senses"}}</label>
|
<label>{{localize "SW5E.Senses"}}</label>
|
||||||
<a class="config-button" data-action="senses" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
<a class="config-button" data-action="senses" title="{{localize 'SW5E.SensesConfig'}}"><i class="fas fa-cog"></i></a>
|
||||||
<ul class="traits-list">
|
<ul class="traits-list">
|
||||||
{{#each senses as |v k|}}
|
{{#each senses as |v k|}}
|
||||||
<li class="tag {{k}}">{{v}}</li>
|
<li class="tag {{k}}">{{v}}</li>
|
||||||
|
|
|
@ -55,11 +55,17 @@
|
||||||
placeholder="—" value="{{data.attributes.ac.motionless}}">
|
placeholder="—" value="{{data.attributes.ac.motionless}}">
|
||||||
</footer>
|
</footer>
|
||||||
</li>
|
</li>
|
||||||
<li class="attribute">
|
<li class="attribute movement">
|
||||||
<h4 class="attribute-name box-title">{{localize 'SW5E.Speed'}}</h4>
|
<h4 class="attribute-name box-title">
|
||||||
|
{{ localize "SW5E.Movement" }}
|
||||||
|
<a class="config-button" data-action="movement" title="{{localize 'SW5E.MovementConfig'}}"><i class="fas fa-cog"></i></a>
|
||||||
|
</h4>
|
||||||
<div class="attribute-value">
|
<div class="attribute-value">
|
||||||
<input name="data.attributes.speed" type="text" placeholder="—" value="{{data.attributes.speed}}"/>
|
<span>{{movement.primary}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<footer class="attribute-footer">
|
||||||
|
<span>{{movement.special}}</span>
|
||||||
|
</footer>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<p>{{ title }}</p>
|
<p>{{ title }}</p>
|
||||||
<p class="notes">{{note}}</p>
|
<p class="notes">{{note}}</p>
|
||||||
{{#each errors}}
|
{{#each errors}}
|
||||||
<p class="notification error">{{localize this}}</p>
|
<p class="notification error">{{this}}</p>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#if consumePowerSlot}}
|
{{#if consumePowerSlot}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue