forked from GitHub-Mirrors/foundry-sw5e
Formatted js files
This commit is contained in:
parent
d1b123100e
commit
584767b352
41 changed files with 13450 additions and 12704 deletions
|
@ -3,220 +3,225 @@
|
|||
* @type {Dialog}
|
||||
*/
|
||||
export default class AbilityUseDialog extends Dialog {
|
||||
constructor(item, dialogData={}, options={}) {
|
||||
super(dialogData, options);
|
||||
this.options.classes = ["sw5e", "dialog"];
|
||||
constructor(item, dialogData = {}, options = {}) {
|
||||
super(dialogData, options);
|
||||
this.options.classes = ["sw5e", "dialog"];
|
||||
|
||||
/**
|
||||
* Store a reference to the Item entity being used
|
||||
* @type {Item5e}
|
||||
*/
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Rendering */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Store a reference to the Item entity being used
|
||||
* @type {Item5e}
|
||||
* A constructor function which displays the Power Cast Dialog app for a given Actor and Item.
|
||||
* Returns a Promise which resolves to the dialog FormData once the workflow has been completed.
|
||||
* @param {Item5e} item
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.item = item;
|
||||
}
|
||||
static async create(item) {
|
||||
if (!item.isOwned) throw new Error("You cannot display an ability usage dialog for an unowned item");
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Rendering */
|
||||
/* -------------------------------------------- */
|
||||
// Prepare data
|
||||
const actorData = item.actor.data.data;
|
||||
const itemData = item.data.data;
|
||||
const uses = itemData.uses || {};
|
||||
const quantity = itemData.quantity || 0;
|
||||
const recharge = itemData.recharge || {};
|
||||
const recharges = !!recharge.value;
|
||||
const sufficientUses = (quantity > 0 && !uses.value) || uses.value > 0;
|
||||
|
||||
/**
|
||||
* A constructor function which displays the Power Cast Dialog app for a given Actor and Item.
|
||||
* Returns a Promise which resolves to the dialog FormData once the workflow has been completed.
|
||||
* @param {Item5e} item
|
||||
* @return {Promise}
|
||||
*/
|
||||
static async create(item) {
|
||||
if ( !item.isOwned ) throw new Error("You cannot display an ability usage dialog for an unowned item");
|
||||
// Prepare dialog form data
|
||||
const data = {
|
||||
item: item.data,
|
||||
title: game.i18n.format("SW5E.AbilityUseHint", {
|
||||
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
|
||||
name: item.name
|
||||
}),
|
||||
note: this._getAbilityUseNote(item.data, uses, recharge),
|
||||
consumePowerSlot: false,
|
||||
consumeRecharge: recharges,
|
||||
consumeResource: !!itemData.consume.target,
|
||||
consumeUses: uses.per && uses.max > 0,
|
||||
canUse: recharges ? recharge.charged : sufficientUses,
|
||||
createTemplate: game.user.can("TEMPLATE_CREATE") && item.hasAreaTarget,
|
||||
errors: []
|
||||
};
|
||||
if (item.data.type === "power") this._getPowerData(actorData, itemData, data);
|
||||
|
||||
// Prepare data
|
||||
const actorData = item.actor.data.data;
|
||||
const itemData = item.data.data;
|
||||
const uses = itemData.uses || {};
|
||||
const quantity = itemData.quantity || 0;
|
||||
const recharge = itemData.recharge || {};
|
||||
const recharges = !!recharge.value;
|
||||
const sufficientUses = (quantity > 0 && !uses.value) || uses.value > 0;
|
||||
// Render the ability usage template
|
||||
const html = await renderTemplate("systems/sw5e/templates/apps/ability-use.html", data);
|
||||
|
||||
// Prepare dialog form data
|
||||
const data = {
|
||||
item: item.data,
|
||||
title: game.i18n.format("SW5E.AbilityUseHint", {type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`), name: item.name}),
|
||||
note: this._getAbilityUseNote(item.data, uses, recharge),
|
||||
consumePowerSlot: false,
|
||||
consumeRecharge: recharges,
|
||||
consumeResource: !!itemData.consume.target,
|
||||
consumeUses: uses.per && (uses.max > 0),
|
||||
canUse: recharges ? recharge.charged : sufficientUses,
|
||||
createTemplate: game.user.can("TEMPLATE_CREATE") && item.hasAreaTarget,
|
||||
errors: []
|
||||
};
|
||||
if ( item.data.type === "power" ) this._getPowerData(actorData, itemData, data);
|
||||
// Create the Dialog and return data as a Promise
|
||||
const icon = data.isPower ? "fa-magic" : "fa-fist-raised";
|
||||
const label = game.i18n.localize("SW5E.AbilityUse" + (data.isPower ? "Cast" : "Use"));
|
||||
return new Promise((resolve) => {
|
||||
const dlg = new this(item, {
|
||||
title: `${item.name}: ${game.i18n.localize("SW5E.AbilityUseConfig")}`,
|
||||
content: html,
|
||||
buttons: {
|
||||
use: {
|
||||
icon: `<i class="fas ${icon}"></i>`,
|
||||
label: label,
|
||||
callback: (html) => {
|
||||
const fd = new FormDataExtended(html[0].querySelector("form"));
|
||||
resolve(fd.toObject());
|
||||
}
|
||||
}
|
||||
},
|
||||
default: "use",
|
||||
close: () => resolve(null)
|
||||
});
|
||||
dlg.render(true);
|
||||
});
|
||||
}
|
||||
|
||||
// Render the ability usage template
|
||||
const html = await renderTemplate("systems/sw5e/templates/apps/ability-use.html", data);
|
||||
/* -------------------------------------------- */
|
||||
/* Helpers */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// Create the Dialog and return data as a Promise
|
||||
const icon = data.isPower ? "fa-magic" : "fa-fist-raised";
|
||||
const label = game.i18n.localize("SW5E.AbilityUse" + (data.isPower ? "Cast" : "Use"));
|
||||
return new Promise((resolve) => {
|
||||
const dlg = new this(item, {
|
||||
title: `${item.name}: ${game.i18n.localize("SW5E.AbilityUseConfig")}`,
|
||||
content: html,
|
||||
buttons: {
|
||||
use: {
|
||||
icon: `<i class="fas ${icon}"></i>`,
|
||||
label: label,
|
||||
callback: html => {
|
||||
const fd = new FormDataExtended(html[0].querySelector("form"));
|
||||
resolve(fd.toObject());
|
||||
/**
|
||||
* Get dialog data related to limited power slots
|
||||
* @private
|
||||
*/
|
||||
static _getPowerData(actorData, itemData, data) {
|
||||
// Determine whether the power may be up-cast
|
||||
const lvl = itemData.level;
|
||||
const consumePowerSlot = lvl > 0 && CONFIG.SW5E.powerUpcastModes.includes(itemData.preparation.mode);
|
||||
|
||||
// If can't upcast, return early and don't bother calculating available power slots
|
||||
if (!consumePowerSlot) {
|
||||
mergeObject(data, {isPower: true, consumePowerSlot});
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the levels which are feasible
|
||||
let lmax = 0;
|
||||
let points;
|
||||
let powerType;
|
||||
switch (itemData.school) {
|
||||
case "lgt":
|
||||
case "uni":
|
||||
case "drk": {
|
||||
powerType = "force";
|
||||
points = actorData.attributes.force.points.value + actorData.attributes.force.points.temp;
|
||||
break;
|
||||
}
|
||||
case "tec": {
|
||||
powerType = "tech";
|
||||
points = actorData.attributes.tech.points.value + actorData.attributes.tech.points.temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
default: "use",
|
||||
close: () => resolve(null)
|
||||
});
|
||||
dlg.render(true);
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Helpers */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get dialog data related to limited power slots
|
||||
* @private
|
||||
*/
|
||||
static _getPowerData(actorData, itemData, data) {
|
||||
|
||||
// Determine whether the power may be up-cast
|
||||
const lvl = itemData.level;
|
||||
const consumePowerSlot = (lvl > 0) && CONFIG.SW5E.powerUpcastModes.includes(itemData.preparation.mode);
|
||||
|
||||
// If can't upcast, return early and don't bother calculating available power slots
|
||||
if (!consumePowerSlot) {
|
||||
mergeObject(data, { isPower: true, consumePowerSlot });
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the levels which are feasible
|
||||
let lmax = 0;
|
||||
let points;
|
||||
let powerType;
|
||||
switch (itemData.school){
|
||||
case "lgt":
|
||||
case "uni":
|
||||
case "drk": {
|
||||
powerType = "force"
|
||||
points = actorData.attributes.force.points.value + actorData.attributes.force.points.temp;
|
||||
break;
|
||||
}
|
||||
case "tec": {
|
||||
powerType = "tech"
|
||||
points = actorData.attributes.tech.points.value + actorData.attributes.tech.points.temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// eliminate point usage for innate casters
|
||||
if (actorData.attributes.powercasting === 'innate') points = 999;
|
||||
|
||||
|
||||
let powerLevels
|
||||
if (powerType === "force"){
|
||||
powerLevels = Array.fromRange(10).reduce((arr, i) => {
|
||||
if ( i < lvl ) return arr;
|
||||
const label = CONFIG.SW5E.powerLevels[i];
|
||||
const l = actorData.powers["power"+i] || {fmax: 0, foverride: null};
|
||||
let max = parseInt(l.foverride || l.fmax || 0);
|
||||
let slots = Math.clamped(parseInt(l.fvalue || 0), 0, max);
|
||||
if ( max > 0 ) lmax = i;
|
||||
if ((max > 0) && (slots > 0) && (points > i)){
|
||||
arr.push({
|
||||
level: i,
|
||||
label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label,
|
||||
canCast: max > 0,
|
||||
hasSlots: slots > 0
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}, []).filter(sl => sl.level <= lmax);
|
||||
}else if (powerType === "tech"){
|
||||
powerLevels = Array.fromRange(10).reduce((arr, i) => {
|
||||
if ( i < lvl ) return arr;
|
||||
const label = CONFIG.SW5E.powerLevels[i];
|
||||
const l = actorData.powers["power"+i] || {tmax: 0, toverride: null};
|
||||
let max = parseInt(l.override || l.tmax || 0);
|
||||
let slots = Math.clamped(parseInt(l.tvalue || 0), 0, max);
|
||||
if ( max > 0 ) lmax = i;
|
||||
if ((max > 0) && (slots > 0) && (points > i)){
|
||||
arr.push({
|
||||
level: i,
|
||||
label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label,
|
||||
canCast: max > 0,
|
||||
hasSlots: slots > 0
|
||||
});
|
||||
|
||||
// eliminate point usage for innate casters
|
||||
if (actorData.attributes.powercasting === "innate") points = 999;
|
||||
|
||||
let powerLevels;
|
||||
if (powerType === "force") {
|
||||
powerLevels = Array.fromRange(10)
|
||||
.reduce((arr, i) => {
|
||||
if (i < lvl) return arr;
|
||||
const label = CONFIG.SW5E.powerLevels[i];
|
||||
const l = actorData.powers["power" + i] || {fmax: 0, foverride: null};
|
||||
let max = parseInt(l.foverride || l.fmax || 0);
|
||||
let slots = Math.clamped(parseInt(l.fvalue || 0), 0, max);
|
||||
if (max > 0) lmax = i;
|
||||
if (max > 0 && slots > 0 && points > i) {
|
||||
arr.push({
|
||||
level: i,
|
||||
label: i > 0 ? game.i18n.format("SW5E.PowerLevelSlot", {level: label, n: slots}) : label,
|
||||
canCast: max > 0,
|
||||
hasSlots: slots > 0
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}, [])
|
||||
.filter((sl) => sl.level <= lmax);
|
||||
} else if (powerType === "tech") {
|
||||
powerLevels = Array.fromRange(10)
|
||||
.reduce((arr, i) => {
|
||||
if (i < lvl) return arr;
|
||||
const label = CONFIG.SW5E.powerLevels[i];
|
||||
const l = actorData.powers["power" + i] || {tmax: 0, toverride: null};
|
||||
let max = parseInt(l.override || l.tmax || 0);
|
||||
let slots = Math.clamped(parseInt(l.tvalue || 0), 0, max);
|
||||
if (max > 0) lmax = i;
|
||||
if (max > 0 && slots > 0 && points > i) {
|
||||
arr.push({
|
||||
level: i,
|
||||
label: i > 0 ? game.i18n.format("SW5E.PowerLevelSlot", {level: label, n: slots}) : label,
|
||||
canCast: max > 0,
|
||||
hasSlots: slots > 0
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}, [])
|
||||
.filter((sl) => sl.level <= lmax);
|
||||
}
|
||||
return arr;
|
||||
}, []).filter(sl => sl.level <= lmax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
}));
|
||||
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
|
||||
})
|
||||
);
|
||||
|
||||
// Merge power casting data
|
||||
return foundry.utils.mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the ability usage note that is displayed
|
||||
* @private
|
||||
*/
|
||||
static _getAbilityUseNote(item, uses, recharge) {
|
||||
|
||||
// Zero quantity
|
||||
const quantity = item.data.quantity;
|
||||
if ( quantity <= 0 ) return game.i18n.localize("SW5E.AbilityUseUnavailableHint");
|
||||
|
||||
// Abilities which use Recharge
|
||||
if ( !!recharge.value ) {
|
||||
return game.i18n.format(recharge.charged ? "SW5E.AbilityUseChargedHint" : "SW5E.AbilityUseRechargeHint", {
|
||||
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
|
||||
})
|
||||
// Merge power casting data
|
||||
return foundry.utils.mergeObject(data, {isPower: true, consumePowerSlot, powerLevels});
|
||||
}
|
||||
|
||||
// Does not use any resource
|
||||
if ( !uses.per || !uses.max ) return "";
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// Consumables
|
||||
if ( item.type === "consumable" ) {
|
||||
let str = "SW5E.AbilityUseNormalHint";
|
||||
if ( uses.value > 1 ) str = "SW5E.AbilityUseConsumableChargeHint";
|
||||
else if ( item.data.quantity === 1 && uses.autoDestroy ) str = "SW5E.AbilityUseConsumableDestroyHint";
|
||||
else if ( item.data.quantity > 1 ) str = "SW5E.AbilityUseConsumableQuantityHint";
|
||||
return game.i18n.format(str, {
|
||||
type: game.i18n.localize(`SW5E.Consumable${item.data.consumableType.capitalize()}`),
|
||||
value: uses.value,
|
||||
quantity: item.data.quantity,
|
||||
max: uses.max,
|
||||
per: CONFIG.SW5E.limitedUsePeriods[uses.per]
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get the ability usage note that is displayed
|
||||
* @private
|
||||
*/
|
||||
static _getAbilityUseNote(item, uses, recharge) {
|
||||
// Zero quantity
|
||||
const quantity = item.data.quantity;
|
||||
if (quantity <= 0) return game.i18n.localize("SW5E.AbilityUseUnavailableHint");
|
||||
|
||||
// Other Items
|
||||
else {
|
||||
return game.i18n.format("SW5E.AbilityUseNormalHint", {
|
||||
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
|
||||
value: uses.value,
|
||||
max: uses.max,
|
||||
per: CONFIG.SW5E.limitedUsePeriods[uses.per]
|
||||
});
|
||||
// Abilities which use Recharge
|
||||
if (!!recharge.value) {
|
||||
return game.i18n.format(recharge.charged ? "SW5E.AbilityUseChargedHint" : "SW5E.AbilityUseRechargeHint", {
|
||||
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`)
|
||||
});
|
||||
}
|
||||
|
||||
// Does not use any resource
|
||||
if (!uses.per || !uses.max) return "";
|
||||
|
||||
// Consumables
|
||||
if (item.type === "consumable") {
|
||||
let str = "SW5E.AbilityUseNormalHint";
|
||||
if (uses.value > 1) str = "SW5E.AbilityUseConsumableChargeHint";
|
||||
else if (item.data.quantity === 1 && uses.autoDestroy) str = "SW5E.AbilityUseConsumableDestroyHint";
|
||||
else if (item.data.quantity > 1) str = "SW5E.AbilityUseConsumableQuantityHint";
|
||||
return game.i18n.format(str, {
|
||||
type: game.i18n.localize(`SW5E.Consumable${item.data.consumableType.capitalize()}`),
|
||||
value: uses.value,
|
||||
quantity: item.data.quantity,
|
||||
max: uses.max,
|
||||
per: CONFIG.SW5E.limitedUsePeriods[uses.per]
|
||||
});
|
||||
}
|
||||
|
||||
// Other Items
|
||||
else {
|
||||
return game.i18n.format("SW5E.AbilityUseNormalHint", {
|
||||
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
|
||||
value: uses.value,
|
||||
max: uses.max,
|
||||
per: CONFIG.SW5E.limitedUsePeriods[uses.per]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue