forked from GitHub-Mirrors/foundry-sw5e
Update Core to 1.4.2
Update Core to 1.4.2 and internal Version to 1.4.2.R1-A8
This commit is contained in:
parent
48b6ab8e18
commit
76e4d74508
10 changed files with 146 additions and 70 deletions
|
@ -146,11 +146,6 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
// Prepare warnings
|
// Prepare warnings
|
||||||
data.warnings = this.actor._preparationWarnings;
|
data.warnings = this.actor._preparationWarnings;
|
||||||
|
|
||||||
// Prepare property attributions
|
|
||||||
this.attribution = {
|
|
||||||
"attributes.ac": this._prepareArmorClassAttribution(actorData.data)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return data to the sheet
|
// Return data to the sheet
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -217,6 +212,30 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break down all of the Active Effects affecting a given target property.
|
||||||
|
* @param {string} target The data property being targeted.
|
||||||
|
* @return {AttributionDescription[]}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_prepareActiveEffectAttributions(target) {
|
||||||
|
return this.actor.effects.reduce((arr, e) => {
|
||||||
|
let source = e.sourceName;
|
||||||
|
if (e.data.origin === this.actor.uuid) source = e.data.label;
|
||||||
|
if (!source) return arr;
|
||||||
|
const value = e.data.changes.reduce((n, change) => {
|
||||||
|
if (change.key !== target || !Number.isNumeric(change.value)) return n;
|
||||||
|
if (change.mode !== CONST.ACTIVE_EFFECT_MODES.ADD) return n;
|
||||||
|
return n + Number(change.value);
|
||||||
|
}, 0);
|
||||||
|
if (!value) return arr;
|
||||||
|
arr.push({value, label: source, mode: CONST.ACTIVE_EFFECT_MODES.ADD});
|
||||||
|
return arr;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -299,12 +318,7 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bonus
|
// Bonus
|
||||||
if (ac.bonus !== 0)
|
if (ac.bonus !== 0) attribution.push(...this._prepareActiveEffectAttributions("data.attributes.ac.bonus"));
|
||||||
attribution.push({
|
|
||||||
label: game.i18n.localize("SW5E.Bonus"),
|
|
||||||
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
|
|
||||||
value: ac.bonus
|
|
||||||
});
|
|
||||||
|
|
||||||
// Cover
|
// Cover
|
||||||
if (ac.cover !== 0)
|
if (ac.cover !== 0)
|
||||||
|
@ -1036,9 +1050,16 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
async _onPropertyAttribution(event) {
|
async _onPropertyAttribution(event) {
|
||||||
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
||||||
const property = event.currentTarget.dataset.property;
|
const property = event.currentTarget.dataset.property;
|
||||||
if (existingTooltip || !property || !this.attribution) return;
|
if (existingTooltip || !property) return;
|
||||||
|
const data = this.actor.data.data;
|
||||||
let html = await new PropertyAttribution(this.object, this.attribution, property).renderTooltip();
|
let attributions;
|
||||||
|
switch (property) {
|
||||||
|
case "attributes.ac":
|
||||||
|
attributions = this._prepareArmorClassAttribution(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!attributions) return;
|
||||||
|
const html = await new PropertyAttribution(this.actor, attributions, property).renderTooltip();
|
||||||
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,11 +138,6 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
// Prepare warnings
|
// Prepare warnings
|
||||||
data.warnings = this.actor._preparationWarnings;
|
data.warnings = this.actor._preparationWarnings;
|
||||||
|
|
||||||
// Prepare property attributions
|
|
||||||
this.attribution = {
|
|
||||||
"attributes.ac": this._prepareArmorClassAttribution(actorData.data)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return data to the sheet
|
// Return data to the sheet
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -209,6 +204,30 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break down all of the Active Effects affecting a given target property.
|
||||||
|
* @param {string} target The data property being targeted.
|
||||||
|
* @return {AttributionDescription[]}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_prepareActiveEffectAttributions(target) {
|
||||||
|
return this.actor.effects.reduce((arr, e) => {
|
||||||
|
let source = e.sourceName;
|
||||||
|
if (e.data.origin === this.actor.uuid) source = e.data.label;
|
||||||
|
if (!source) return arr;
|
||||||
|
const value = e.data.changes.reduce((n, change) => {
|
||||||
|
if (change.key !== target || !Number.isNumeric(change.value)) return n;
|
||||||
|
if (change.mode !== CONST.ACTIVE_EFFECT_MODES.ADD) return n;
|
||||||
|
return n + Number(change.value);
|
||||||
|
}, 0);
|
||||||
|
if (!value) return arr;
|
||||||
|
arr.push({value, label: source, mode: CONST.ACTIVE_EFFECT_MODES.ADD});
|
||||||
|
return arr;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -291,12 +310,7 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bonus
|
// Bonus
|
||||||
if (ac.bonus !== 0)
|
if (ac.bonus !== 0) attribution.push(...this._prepareActiveEffectAttributions("data.attributes.ac.bonus"));
|
||||||
attribution.push({
|
|
||||||
label: game.i18n.localize("SW5E.Bonus"),
|
|
||||||
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
|
|
||||||
value: ac.bonus
|
|
||||||
});
|
|
||||||
|
|
||||||
// Cover
|
// Cover
|
||||||
if (ac.cover !== 0)
|
if (ac.cover !== 0)
|
||||||
|
@ -967,9 +981,16 @@ export default class ActorSheet5e extends ActorSheet {
|
||||||
async _onPropertyAttribution(event) {
|
async _onPropertyAttribution(event) {
|
||||||
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
const existingTooltip = event.currentTarget.querySelector("div.tooltip");
|
||||||
const property = event.currentTarget.dataset.property;
|
const property = event.currentTarget.dataset.property;
|
||||||
if (existingTooltip || !property || !this.attribution) return;
|
if (existingTooltip || !property) return;
|
||||||
|
const data = this.actor.data.data;
|
||||||
let html = await new PropertyAttribution(this.object, this.attribution, property).renderTooltip();
|
let attributions;
|
||||||
|
switch (property) {
|
||||||
|
case "attributes.ac":
|
||||||
|
attributions = this._prepareArmorClassAttribution(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!attributions) return;
|
||||||
|
const html = await new PropertyAttribution(this.actor, attributions, property).renderTooltip();
|
||||||
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
event.currentTarget.insertAdjacentElement("beforeend", html[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
*/
|
*/
|
||||||
export default class PropertyAttribution extends Application {
|
export default class PropertyAttribution extends Application {
|
||||||
/**
|
/**
|
||||||
* @param {Document} object - Object containing the property to be attributed.
|
* @param {Document} object The Document that owns the property being attributed.
|
||||||
* @param {object.<string, AttributionDescription[]>} attribution - Object containing all of the attribution data.
|
* @param {AttributionDescription[]} attributions An array of all the attribution data.
|
||||||
* @param {string} property - Dot separated path to the property.
|
* @param {string} property Dot separated path to the property.
|
||||||
*/
|
*/
|
||||||
constructor(object, attribution, property, options = {}) {
|
constructor(object, attributions, property, options = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
this.object = object;
|
this.object = object;
|
||||||
this.attribution = attribution;
|
this.attributions = attributions;
|
||||||
this.property = property;
|
this.property = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ export default class PropertyAttribution extends Application {
|
||||||
total = property.value;
|
total = property.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sources = foundry.utils.duplicate(this.attribution[this.property]);
|
const sources = foundry.utils.duplicate(this.attributions);
|
||||||
return {
|
return {
|
||||||
sources: sources.map((entry) => {
|
sources: sources.map((entry) => {
|
||||||
if (entry.label.startsWith("@")) {
|
if (entry.label.startsWith("@")) {
|
||||||
|
|
|
@ -70,6 +70,10 @@ export default class ItemSheet5e extends ItemSheet {
|
||||||
data.isCrewed = itemData.data.activation?.type === "crew";
|
data.isCrewed = itemData.data.activation?.type === "crew";
|
||||||
data.isMountable = this._isItemMountable(itemData);
|
data.isMountable = this._isItemMountable(itemData);
|
||||||
|
|
||||||
|
// Armor Class
|
||||||
|
data.isArmor = itemData.data.armor?.type in data.config.armorTypes;
|
||||||
|
data.hasAC = data.isArmor || data.isMountable;
|
||||||
|
|
||||||
// Prepare Active Effects
|
// Prepare Active Effects
|
||||||
data.effects = ActiveEffect5e.prepareActiveEffectCategories(this.item.effects);
|
data.effects = ActiveEffect5e.prepareActiveEffectCategories(this.item.effects);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const migrateWorld = async function () {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Migrate World Actors
|
// Migrate World Actors
|
||||||
for await (let a of game.actors.contents) {
|
for await (let a of game.actors) {
|
||||||
try {
|
try {
|
||||||
console.log(`Checking Actor entity ${a.name} for migration needs`);
|
console.log(`Checking Actor entity ${a.name} for migration needs`);
|
||||||
const updateData = await migrateActorData(a.toObject());
|
const updateData = await migrateActorData(a.toObject());
|
||||||
|
@ -24,7 +24,7 @@ export const migrateWorld = async function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate World Items
|
// Migrate World Items
|
||||||
for (let i of game.items.contents) {
|
for (let i of game.items) {
|
||||||
try {
|
try {
|
||||||
const updateData = migrateItemData(i.toObject());
|
const updateData = migrateItemData(i.toObject());
|
||||||
if (!foundry.utils.isObjectEmpty(updateData)) {
|
if (!foundry.utils.isObjectEmpty(updateData)) {
|
||||||
|
@ -38,7 +38,7 @@ export const migrateWorld = async function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate Actor Override Tokens
|
// Migrate Actor Override Tokens
|
||||||
for (let s of game.scenes.contents) {
|
for (let s of game.scenes) {
|
||||||
try {
|
try {
|
||||||
const updateData = await migrateSceneData(s.data);
|
const updateData = await migrateSceneData(s.data);
|
||||||
if (!foundry.utils.isObjectEmpty(updateData)) {
|
if (!foundry.utils.isObjectEmpty(updateData)) {
|
||||||
|
@ -46,7 +46,7 @@ export const migrateWorld = async function () {
|
||||||
await s.update(updateData, {enforceTypes: false});
|
await s.update(updateData, {enforceTypes: false});
|
||||||
// If we do not do this, then synthetic token actors remain in cache
|
// If we do not do this, then synthetic token actors remain in cache
|
||||||
// with the un-updated actorData.
|
// with the un-updated actorData.
|
||||||
s.tokens.contents.forEach((t) => (t._actor = null));
|
s.tokens.forEach((t) => (t._actor = null));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
err.message = `Failed sw5e system migration for Scene ${s.name}: ${err.message}`;
|
err.message = `Failed sw5e system migration for Scene ${s.name}: ${err.message}`;
|
||||||
|
@ -260,6 +260,7 @@ export const migrateItemData = function (item) {
|
||||||
_migrateItemClassPowerCasting(item, updateData);
|
_migrateItemClassPowerCasting(item, updateData);
|
||||||
_migrateItemAttunement(item, updateData);
|
_migrateItemAttunement(item, updateData);
|
||||||
_migrateItemRarity(item, updateData);
|
_migrateItemRarity(item, updateData);
|
||||||
|
_migrateArmorType(item, updateData);
|
||||||
return updateData;
|
return updateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -276,6 +277,7 @@ export const migrateActorItemData = async function (item, actor) {
|
||||||
_migrateItemAttunement(item, updateData);
|
_migrateItemAttunement(item, updateData);
|
||||||
_migrateItemRarity(item, updateData);
|
_migrateItemRarity(item, updateData);
|
||||||
await _migrateItemPower(item, actor, updateData);
|
await _migrateItemPower(item, actor, updateData);
|
||||||
|
_migrateArmorType(item, updateData);
|
||||||
return updateData;
|
return updateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -601,6 +603,7 @@ function _migrateActorType(actor, updateData) {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Migrate the Class item powercasting field to allow powercasting to properly calculate
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function _migrateItemClassPowerCasting(item, updateData) {
|
function _migrateItemClassPowerCasting(item, updateData) {
|
||||||
|
@ -649,9 +652,18 @@ function _migrateItemClassPowerCasting(item, updateData) {
|
||||||
*/
|
*/
|
||||||
function _migrateActorAC(actorData, updateData) {
|
function _migrateActorAC(actorData, updateData) {
|
||||||
const ac = actorData.data?.attributes?.ac;
|
const ac = actorData.data?.attributes?.ac;
|
||||||
if (!Number.isNumeric(ac?.value)) return;
|
// If the actor has a numeric ac.value, then their AC has not been migrated to the auto-calculation schema yet.
|
||||||
updateData["data.attributes.ac.flat"] = ac.value;
|
if (Number.isNumeric(ac?.value)) {
|
||||||
updateData["data.attributes.ac.-=value"] = null;
|
updateData["data.attributes.ac.flat"] = ac.value;
|
||||||
|
updateData["data.attributes.ac.calc"] = actorData.type === "npc" ? "natural" : "flat";
|
||||||
|
updateData["data.attributes.ac.-=value"] = null;
|
||||||
|
return updateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the actor is already on the AC auto-calculation schema, but is using a flat value, they must now have their
|
||||||
|
// calculation updated to an appropriate value.
|
||||||
|
if (!Number.isNumeric(ac?.flat)) return updateData;
|
||||||
|
updateData["data.attributes.ac.calc"] = actorData.type === "npc" ? "natural" : "flat";
|
||||||
return updateData;
|
return updateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,6 +754,22 @@ function _migrateItemRarity(item, updateData) {
|
||||||
return updateData;
|
return updateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert equipment items of type 'bonus' to 'trinket'.
|
||||||
|
*
|
||||||
|
* @param {object} item Item data to migrate
|
||||||
|
* @param {object} updateData Existing update to expand upon
|
||||||
|
* @return {object} The updateData to apply
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _migrateArmorType(item, updateData) {
|
||||||
|
if (item.type !== "equipment") return updateData;
|
||||||
|
if (item.data?.armor?.type === "bonus") updateData["data.armor.type"] = "trinket";
|
||||||
|
return updateData;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
||||||
// Prepare template data
|
// Prepare template data
|
||||||
const templateData = {
|
const templateData = {
|
||||||
t: templateShape,
|
t: templateShape,
|
||||||
user: game.user.data._id,
|
user: game.user.id,
|
||||||
distance: target.value,
|
distance: target.value,
|
||||||
direction: 0,
|
direction: 0,
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -96,7 +96,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
|
||||||
|
|
||||||
// Cancel the workflow (right-click)
|
// Cancel the workflow (right-click)
|
||||||
handlers.rc = (event) => {
|
handlers.rc = (event) => {
|
||||||
this.layer.preview.removeChildren();
|
this.layer._onDragLeftCancel(event);
|
||||||
canvas.stage.off("mousemove", handlers.mm);
|
canvas.stage.off("mousemove", handlers.mm);
|
||||||
canvas.stage.off("mousedown", handlers.lc);
|
canvas.stage.off("mousedown", handlers.lc);
|
||||||
canvas.app.view.oncontextmenu = null;
|
canvas.app.view.oncontextmenu = null;
|
||||||
|
|
2
sw5e.js
2
sw5e.js
|
@ -290,7 +290,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.4.1.R1-A8";
|
const NEEDS_MIGRATION_VERSION = "1.4.2.R1-A8";
|
||||||
// Check for R1 SW5E versions
|
// Check for R1 SW5E versions
|
||||||
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A8";
|
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A8";
|
||||||
const COMPATIBLE_MIGRATION_VERSION = 0.8;
|
const COMPATIBLE_MIGRATION_VERSION = 0.8;
|
||||||
|
|
|
@ -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": "1.4.1.R1-A8",
|
"version": "1.4.2.R1-A8",
|
||||||
"author": "Dev Team",
|
"author": "Dev Team",
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
"esmodules": ["sw5e.js"],
|
"esmodules": ["sw5e.js"],
|
||||||
|
|
|
@ -945,7 +945,7 @@
|
||||||
],
|
],
|
||||||
"armor": {
|
"armor": {
|
||||||
"type": "light",
|
"type": "light",
|
||||||
"value": 10,
|
"value": null,
|
||||||
"dex": null
|
"dex": null
|
||||||
},
|
},
|
||||||
"speed": {
|
"speed": {
|
||||||
|
|
|
@ -121,36 +121,38 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Armor Class --}}
|
{{!-- Armor Class --}}
|
||||||
<div class="form-group">
|
{{#if hasAC}}
|
||||||
<label>{{ localize "SW5E.ArmorClass" }}</label>
|
<div class="form-group">
|
||||||
<div class="form-fields">
|
<label>{{ localize "SW5E.ArmorClass" }}</label>
|
||||||
<input type="text" name="data.armor.value" value="{{data.armor.value}}" data-dtype="Number"/>
|
<div class="form-fields">
|
||||||
|
<input type="text" name="data.armor.value" value="{{data.armor.value}}" data-dtype="Number"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/if}}
|
||||||
|
|
||||||
{{#unless isMountable}}
|
{{#if isArmor}}
|
||||||
{{!-- Dexterity Modifier --}}
|
{{!-- Dexterity Modifier --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize "SW5E.ItemEquipmentDexMod" }}</label>
|
<label>{{ localize "SW5E.ItemEquipmentDexMod" }}</label>
|
||||||
<div class="form-fields">
|
<div class="form-fields">
|
||||||
<input type="text" name="data.armor.dex" value="{{data.armor.dex}}" data-dtype="Number" placeholder="{{ localize 'SW5E.Unlimited' }}"/>
|
<input type="text" name="data.armor.dex" value="{{data.armor.dex}}" data-dtype="Number" placeholder="{{ localize 'SW5E.Unlimited' }}"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Required Strength --}}
|
{{!-- Required Strength --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize "SW5E.ItemRequiredStr" }}</label>
|
<label>{{ localize "SW5E.ItemRequiredStr" }}</label>
|
||||||
<div class="form-fields">
|
<div class="form-fields">
|
||||||
<input type="text" name="data.strength" value="{{data.strength}}" data-dtype="Number" placeholder="{{ localize 'SW5E.None' }}"/>
|
<input type="text" name="data.strength" value="{{data.strength}}" data-dtype="Number" placeholder="{{ localize 'SW5E.None' }}"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- Stealth Disadvantage --}}
|
{{!-- Stealth Disadvantage --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize "SW5E.ItemEquipmentStealthDisav" }}</label>
|
<label>{{ localize "SW5E.ItemEquipmentStealthDisav" }}</label>
|
||||||
<input type="checkbox" name="data.stealth" value="1" {{checked data.stealth}}/>
|
<input type="checkbox" name="data.stealth" value="1" {{checked data.stealth}}/>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isMountable}}
|
{{#if isMountable}}
|
||||||
{{> 'systems/sw5e/templates/items/parts/item-mountable.html'}}
|
{{> 'systems/sw5e/templates/items/parts/item-mountable.html'}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue