diff --git a/CHANGELOG.md b/CHANGELOG.md index 21d5b577..e3709b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Version 4.0.6 (So far...) [Hero System 6e (Unofficial) v2](https://github.com/dmdorman/hero6e-foundryvtt) - Migrations are no longer supported from versions before 3.0.76. Migrate through any version prior to 4.0.6 if you find your world in this situation. +- Initial support for Only In Heroic ID. There is a checkbox on the OTHER tab. Powers/skills with OIHID will be disabled when not in heroic ID. (#232)(https://github.com/dmdorman/hero6e-foundryvtt/issues/232) ## Version 4.0.5 diff --git a/module/actor/actor-sheet.mjs b/module/actor/actor-sheet.mjs index ea36e66f..9b0a8406 100644 --- a/module/actor/actor-sheet.mjs +++ b/module/actor/actor-sheet.mjs @@ -36,6 +36,7 @@ export class HeroSystemActorSheet extends ActorSheet { /** @override */ async getData() { const data = super.getData(); + data.system = data.actor.system; try { // Show an unsupported actor warning when the sheet opens. An actor can be unsupported if: @@ -267,14 +268,6 @@ export class HeroSystemActorSheet extends ActorSheet { ); await pdAttack._postUpload(); - let { - defenseValue: _defenseValuePD, - resistantValue: _resistantValuePD /*impenetrableValue*/, - //damageReductionValue: _damageReductionValuePD, - //damageNegationValue: _damageNegationValuePD /*knockbackResistance*/, - // defenseTags: defenseTagsP, - } = determineDefense(this.actor, pdAttack, { suppressDeprecationWarn: true }); - // New PD const { defenseValue: defenseValuePD, @@ -283,12 +276,6 @@ export class HeroSystemActorSheet extends ActorSheet { damageNegationValue: damageNegationValuePD, defenseTags: defenseTagsPD, } = getActorDefensesVsAttack(this.actor, pdAttack); - if (_defenseValuePD != defenseValuePD) { - console.warn("PD Defense mismatch", _defenseValuePD, defenseValuePD); - } - if (_resistantValuePD != resistantValuePD) { - console.warn("rPD Defense mismatch", _resistantValuePD, resistantValuePD); - } defense.PD = defenseValuePD; for (const tag of defenseTagsPD.filter((o) => o.operation === "add" && !o.options?.resistant)) { defense.PDtags = `${defense.PDtags || ""}${tag.value.signedString()} ${tag.name} ${tag.shortDesc}\n`; @@ -317,14 +304,6 @@ export class HeroSystemActorSheet extends ActorSheet { ); await edAttack._postUpload(); - let { - defenseValue: _defenseValueED, - resistantValue: _resistantValueED /* impenetrableValueE */, - //damageReductionValue: _damageReductionValueED, - //damageNegationValue: _damageNegationValueED /* knockbackResistanceE */, - // defenseTags: _defenseTagsE, - } = determineDefense(this.actor, edAttack, { suppressDeprecationWarn: true }); - // New ED const { defenseValue: defenseValueED, @@ -333,12 +312,6 @@ export class HeroSystemActorSheet extends ActorSheet { damageNegationValue: damageNegationValueED, defenseTags: defenseTagsED, } = getActorDefensesVsAttack(this.actor, edAttack); - if (_defenseValueED != defenseValueED) { - console.warn("ED Defense mismatch", _defenseValueED, defenseValueED); - } - if (_resistantValueED != resistantValueED) { - console.warn("rED Defense mismatch", _defenseValueED, defenseValueED); - } defense.ED = defenseValueED; for (const tag of defenseTagsED.filter((o) => o.operation === "add" && !o.options?.resistant)) { defense.EDtags = `${defense.EDtags || ""}${tag.value.signedString()} ${tag.name} ${tag.shortDesc}\n`; @@ -368,14 +341,6 @@ export class HeroSystemActorSheet extends ActorSheet { ); await mdAttack._postUpload(); - let { - defenseValue: _defenseValueMD, - //resistantValue: _resistantValueMD /*impenetrableValueM*/, - //damageReductionValue: _damageReductionValueMD, - //damageNegationValue: _damageNegationValueMD /*knockbackResistanceM*/, - defenseTags: _defenseTagsMD, - } = determineDefense(this.actor, mdAttack, { suppressDeprecationWarn: true }); - // New MD const { defenseValue: defenseValueMD, @@ -384,9 +349,6 @@ export class HeroSystemActorSheet extends ActorSheet { damageNegationValue: damageNegationValueMD, defenseTags: defenseTagsMD, } = getActorDefensesVsAttack(this.actor, mdAttack); - if (_defenseValueMD != defenseValueMD) { - console.warn("MD Defense mismatch", _defenseValueMD, defenseValueMD, _defenseTagsMD); - } defense.MD = defenseValueMD; for (const tag of defenseTagsMD.filter((o) => o.operation === "add" && !o.options?.resistant)) { defense.MDtags = `${defense.MDtags || ""}${tag.value.signedString()} ${tag.name} ${tag.shortDesc}\n`; @@ -461,7 +423,7 @@ export class HeroSystemActorSheet extends ActorSheet { (o) => (o.system.subType || o.type) === "defense" && !o.effects.size, ); for (let d of defensePowers) { - d.disabled = !d.system.active; + d.disabled = !d.isActive; switch (getPowerInfo({ xmlid: d.system.XMLID, actor: this.actor })?.duration) { case "instant": // Might Vary @@ -849,9 +811,12 @@ export class HeroSystemActorSheet extends ActorSheet { } /** @override */ - async _updateObject(_event, formData) { + async _updateObject(event, formData) { + event.preventDefault(); + let expandedData = foundry.utils.expandObject(formData); + // Left Sidebar of actor sheet has Xsystem characteristics const characteristics = getCharacteristicInfoArrayForActor(this.actor).filter((o) => ["BODY", "STUN", "END"].includes(o.key), ); @@ -867,7 +832,7 @@ export class HeroSystemActorSheet extends ActorSheet { } } - // EndReserve + // Left Sidebar may have EndReserve if (expandedData.endReserve) { const endReserveId = Object.keys(expandedData.endReserve)?.[0]; const endReserve = this.actor.items.find((o) => o.id === endReserveId); @@ -875,20 +840,28 @@ export class HeroSystemActorSheet extends ActorSheet { await endReserve.update({ "system.value": parseInt(expandedData.endReserve[endReserveId].value || 0) }); } } - console.log(formData); this.options.itemFilters.power = expandedData.itemFilters.power; this.options.itemFilters.skill = expandedData.itemFilters.skill; this.options.itemFilters.equipment = expandedData.itemFilters.equipment; - await this.actor.update(expandedData); + // If core characteristics changed the re-calculate costs + let recalculateCosts = false; + for (const char of Object.keys(expandedData.system.characteristics)) { + if (this.actor.system.characteristics[char].core !== expandedData.system.characteristics[char].core) { + recalculateCosts = true; + } + } + + // Do all the standard things like updating item properties that match the name of input boxes + await super._updateObject(event, formData); - if (expandedData.system.characteristics) { + if (recalculateCosts) { await this.actor.calcCharacteristicsCost(); await this.actor.CalcActorRealAndActivePoints(); } - this.render(); + await this.render(); } async _onItemRoll(event) { diff --git a/module/actor/actor.mjs b/module/actor/actor.mjs index ef2124ca..62e7a2e9 100644 --- a/module/actor/actor.mjs +++ b/module/actor/actor.mjs @@ -276,6 +276,42 @@ export class HeroSystem6eActor extends Actor { await this.update(changes); } + // Heroic ID + if (data.system?.heroicIdentity !== undefined) { + // Loop thru all the active effects, checking if source has OIHID + const allEffects = await this.allApplicableEffects(); + for (const ae of allEffects) { + const item = ae.parent; + if (!item) continue; + if (item instanceof HeroSystem6eItem === false) continue; + if (item.findModsByXmlid("OIHID")) { + await ae.update({ disabled: !data.system.heroicIdentity }); + + // Modify characteristics as appropriate + for (const change of ae.changes) { + if (change.key.match(/max$/) && change.mode === 2 && change.value > 0) { + const valueKey = change.key.replace(/.max$/, ".value"); + let max = this; + valueKey.split(".").forEach((subPath) => { + max = max[subPath] || null; + }); + if (parseInt(max || 0) > 0) { + if (ae.disabled) { + await this.update({ + [valueKey]: max - parseInt(change.value), + }); + } else { + await this.update({ + [valueKey]: max + parseInt(change.value), + }); + } + } + } + } + } + } + } + // Display changes from _preUpdate for (let d of options.displayScrollingChanges) { this._displayScrollingChange(d.value, d.options); @@ -804,7 +840,7 @@ export class HeroSystem6eActor extends Actor { (o) => o.system.XMLID === "PENALTY_SKILL_LEVELS" && o.system.penalty === "encumbrance" && - (o.type === "skill" || o.system.active), + (o.type === "skill" || o.isActive), )) { dcvDex = Math.min(0, dcvDex + parseInt(pslEncumbrance.system.LEVELS)); } @@ -922,7 +958,7 @@ export class HeroSystem6eActor extends Actor { // 0 on movement and DCV occur 5 points of STR // sooner. const massMultiplier = this.items - .filter((o) => o.system.XMLID === "DENSITYINCREASE" && o.system.active) + .filter((o) => o.system.XMLID === "DENSITYINCREASE" && o.isActive) .reduce((p, a) => p + parseInt(a.system.LEVELS), 0); const minStr = massMultiplier * 5; @@ -1233,7 +1269,7 @@ export class HeroSystem6eActor extends Actor { getActiveConstantItems() { let results = []; - for (let item of this.items.filter((o) => o.system.active)) { + for (let item of this.items.filter((o) => o.isActive)) { let duration = getPowerInfo({ xmlid: item.system.XMLID, actor: this, @@ -1999,6 +2035,13 @@ export class HeroSystem6eActor extends Actor { await this.update({ [`system.is5e`]: this.system.is5e }); } + // ONLY IN ALTERNATE IDENTITY (OIAID) + // Assume we are in our super/heroic identity + if (this.system.heroicIdentity === undefined) { + this.system.heroicIdentity = false; + changes[`system.heroicIdentity`] = true; + } + // isHeroic // Need to be a careful as there are custom templates ('Nekhbet Vulture Child Goddess') // that we are unlikely able to decode heroic status. @@ -2295,7 +2338,7 @@ export class HeroSystem6eActor extends Actor { // Hero Designer appears to store WEIGHT as LBS instead of KG. const equipment = this.items.filter( - (o) => o.type === "equipment" && (o.parentItem ? o.parentItem.system.active : o.system.active), + (o) => o.type === "equipment" && (o.parentItem ? o.parentItem.isActive : o.isActive), ); const weightLbs = equipment.reduce((a, b) => a + parseFloat(b.system?.WEIGHT || 0), 0); const weightKg = (weightLbs / 2.2046226218) * equipmentWeightPercentage; @@ -2304,7 +2347,7 @@ export class HeroSystem6eActor extends Actor { } get netWorth() { - const equipment = this.items.filter((o) => o.type === "equipment" && o.system.active); + const equipment = this.items.filter((o) => o.type === "equipment" && o.isActive); const price = equipment.reduce((a, b) => a + parseFloat(b.system.PRICE), 0); return price.toFixed(2); } diff --git a/module/combat.mjs b/module/combat.mjs index cf31c31d..074a9b0f 100644 --- a/module/combat.mjs +++ b/module/combat.mjs @@ -489,7 +489,7 @@ export class HeroSystem6eCombat extends Combat { for (const powerUsingResourcesToContinue of combatant.actor.items.filter( (item) => - item.system.active === true && // Is the power active? + item.isActive === true && // Is the power active? item.baseInfo.duration !== "instant" && // Is the power non instant ((parseInt(item.system.end || 0) > 0 && // Does the power use END? !item.system.MODIFIER?.find((o) => o.XMLID === "COSTSEND" && o.OPTION === "ACTIVATE")) || // Does the power use END continuously? @@ -541,7 +541,11 @@ export class HeroSystem6eCombat extends Combat { if (content !== "" && (spentResources.totalEnd > 0 || spentResources.charges > 0)) { const segment = this.combatant.flags.segment; - content = `Spent ${spentResources.end} END, ${spentResources.reserveEnd} reserve END, and ${spentResources.charges} charge${spentResources.charges > 1 ? "s" : ""} on turn ${this.round} segment ${segment}:`; + content = `Spent ${spentResources.end} END, ${spentResources.reserveEnd} reserve END, and ${ + spentResources.charges + } charge${spentResources.charges > 1 ? "s" : ""} on turn ${ + this.round + } segment ${segment}:`; const token = combatant.token; const speaker = ChatMessage.getSpeaker({ diff --git a/module/herosystem6e.mjs b/module/herosystem6e.mjs index 39279bdc..37a7b411 100644 --- a/module/herosystem6e.mjs +++ b/module/herosystem6e.mjs @@ -721,7 +721,7 @@ Hooks.on("updateWorldTime", async (worldTime, options) => { for (const aeWithCharges of actor.temporaryEffects.filter((o) => o.parent instanceof HeroSystem6eItem ? o.parent.findModsByXmlid("CONTINUING") : false, )) { - if (!aeWithCharges.parent.system.active) { + if (!aeWithCharges.parent.isActive) { console.error(`${aeWithCharges.name} is inactive and will not expire.`); continue; } diff --git a/module/item/item-attack.mjs b/module/item/item-attack.mjs index c2ee7f38..7cefd826 100644 --- a/module/item/item-attack.mjs +++ b/module/item/item-attack.mjs @@ -153,7 +153,7 @@ export async function AttackAoeToHit(item, options) { const hitCharacteristic = actor.system.characteristics.ocv.value; const setManeuver = item.actor.items.find( - (item) => item.type == "maneuver" && item.name === "Set" && item.system.active, + (item) => item.type == "maneuver" && item.name === "Set" && item.isActive, ); const attackHeroRoller = new HeroRoller() @@ -200,7 +200,7 @@ export async function AttackAoeToHit(item, options) { // Brace (+2 OCV only to offset the Range Modifier) const braceManeuver = item.actor.items.find( - (item) => item.type == "maneuver" && item.name === "Brace" && item.system.active, + (item) => item.type == "maneuver" && item.name === "Brace" && item.isActive, ); if (braceManeuver) { let brace = Math.min(-rangePenalty, braceManeuver.system.ocv); @@ -276,7 +276,7 @@ export async function AttackAoeToHit(item, options) { cvModifiers.push(cvMod); }); // Haymaker -5 DCV - const haymakerManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Haymaker" && o.system.active); + const haymakerManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Haymaker" && o.isActive); if (haymakerManeuver) { //todo: if it is -5 , then why -4? dcv -= 4; @@ -467,7 +467,7 @@ export async function AttackToHit(item, options) { // ------------------------------------------------- // attack roll // ------------------------------------------------- - const setManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Set" && o.system.active); + const setManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Set" && o.isActive); let stunForEndHeroRoller = null; @@ -533,9 +533,7 @@ export async function AttackToHit(item, options) { } // Brace (+2 OCV only to offset the Range Modifier) - const braceManeuver = item.actor.items.find( - (o) => o.type == "maneuver" && o.name === "Brace" && o.system.active, - ); + const braceManeuver = item.actor.items.find((o) => o.type == "maneuver" && o.name === "Brace" && o.isActive); if (braceManeuver) { let brace = Math.min(-rangePenalty, braceManeuver.system.ocv); if (brace > 0) { @@ -610,7 +608,7 @@ export async function AttackToHit(item, options) { cvModifiers.push(cvMod); }); // Haymaker -5 DCV - const haymakerManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Haymaker" && o.system.active); + const haymakerManeuver = actor.items.find((o) => o.type == "maneuver" && o.name === "Haymaker" && o.isActive); if (haymakerManeuver) { //todo: if it is -5 , then why -4? dcv -= 4; @@ -1934,7 +1932,7 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) { let conditionalDefenses = token.actor.items.filter( (o) => (o.system.subType || o.system.type) === "defense" && - (o.system.active || o.effects.find(() => true)?.disabled === false) && + (o.isActive || o.effects.find(() => true)?.disabled === false) && ((o.system.MODIFIER || []).find((p) => ["ONLYAGAINSTLIMITEDTYPE", "CONDITIONALPOWER"].includes(p.XMLID)) || avad), ); @@ -2141,7 +2139,7 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) { const defenseEveryPhase = token.actor.items.filter( (o) => (o.system.subType || o.system.type) === "defense" && - o.system.active && + o.isActive && (o.findModsByXmlid("EVERYPHASE") || o.findModsByXmlid("ACTIVATIONROLL")), ); @@ -2647,7 +2645,7 @@ async function _performAbsorptionForToken(token, absorptionItems, damageDetail, // Match attack against absorption type. If we match we can do some absorption. for (const absorptionItem of absorptionItems) { - if (absorptionItem.system.OPTION === attackType.toUpperCase() && absorptionItem.system.active) { + if (absorptionItem.system.OPTION === attackType.toUpperCase() && absorptionItem.isActive) { const actor = absorptionItem.actor; let maxAbsorption; if (actor.system.is5e) { @@ -2882,7 +2880,7 @@ async function _onApplySenseAffectingToSpecificToken(senseAffectingItem, token, let totalDefense = 0; // FLASHDEFENSE - for (const flashDefense of token.actor.items.filter((o) => o.system.XMLID === "FLASHDEFENSE" && o.system.active)) { + for (const flashDefense of token.actor.items.filter((o) => o.system.XMLID === "FLASHDEFENSE" && o.isActive)) { if ( senseAffectingItem.system.OPTIONID === flashDefense.system.OPTIONID || flashDefense.system.OPTIONID.includes(senseAffectingItem.system.INPUT?.toUpperCase()) @@ -3216,7 +3214,7 @@ async function _calcKnockback(body, item, options, knockbackMultiplier) { // Double check to make sure FLIGHT or GLIDING is still on if ( options.targetToken.actor.items.find( - (o) => o.system.XMLID === activeMovement.toUpperCase() && o.system.active, + (o) => o.system.XMLID === activeMovement.toUpperCase() && o.isActive, ) ) { knockbackDice -= 1; @@ -3245,7 +3243,7 @@ async function _calcKnockback(body, item, options, knockbackMultiplier) { // Target is using Clinging +1d6 const clinging = options.targetToken?.actor?.items.find((o) => o.system.XMLID === "CLINGING"); - if (clinging && clinging.system.active) { + if (clinging && clinging.isActive) { knockbackDice += 1; knockbackTags.push({ value: "+1d6KB", diff --git a/module/item/item.mjs b/module/item/item.mjs index 990731db..a1c7119e 100644 --- a/module/item/item.mjs +++ b/module/item/item.mjs @@ -4965,6 +4965,24 @@ export class HeroSystem6eItem extends Item { const price = parseFloat(this.system.PRICE) || 0; return `$${price.toFixed(2)}`; } + + // Is this power disabled because we are not in our superheroic identity? + get disabledOIHID() { + if (!this.actor) return false; + if (this.actor.system.heroicIdentity) return false; + if (this.findModsByXmlid("OIHID")) return true; + return false; + } + + get isActive() { + try { + if (this.disabledOIHID) return false; + } catch (e) { + console.error(e); + } + + return this.system.active; + } } export function getItem(id) { diff --git a/module/utility/damage.mjs b/module/utility/damage.mjs index dafbe8fa..832c5041 100644 --- a/module/utility/damage.mjs +++ b/module/utility/damage.mjs @@ -566,7 +566,7 @@ export function CombatSkillLevelsForAttack(item) { (o) => ["MENTAL_COMBAT_LEVELS", "COMBAT_LEVELS"].includes(o.system.XMLID) && (o.system.ADDER || []).find((p) => p.ALIAS === item.system.ALIAS || p.ALIAS === item.name) && - o.system.active != false, + o.isActive != false, ); for (const cslSkill of cslSkills) { @@ -605,7 +605,7 @@ export function PenaltySkillLevelsForAttack(item) { (o) => ["PENALTY_SKILL_LEVELS"].includes(o.system.XMLID) && (o.system.ADDER || []).find((p) => p.ALIAS === item.system.ALIAS || p.ALIAS === item.name) && - o.system.active != false, + o.isActive != false, ); return psls; diff --git a/module/utility/defense.mjs b/module/utility/defense.mjs index a25dc559..aabc158d 100644 --- a/module/utility/defense.mjs +++ b/module/utility/defense.mjs @@ -133,7 +133,7 @@ export function getActorDefensesVsAttack(targetActor, attackItem, options = {}) } // back out 5e DAMAGERESISTANCE for (const damageResistance of targetActor.items.filter( - (o) => o.system.XMLID === "DAMAGERESISTANCE" && o.system.active, + (o) => o.system.XMLID === "DAMAGERESISTANCE" && o.isActive, )) { switch (attackDefenseVs.toUpperCase()) { case "PD": @@ -178,7 +178,7 @@ export function getActorDefensesVsAttack(targetActor, attackItem, options = {}) const activeDefenses = targetActor.items.filter( (o) => (o.system.subType === "defense" || o.type === "defense" || o.baseInfo?.type?.includes("defense")) && - (o.system.active || o.effects.find(() => true)?.disabled === false) && + o.isActive && !(options?.ignoreDefenseIds || []).includes(o.id), ); for (const defenseItem of activeDefenses) { @@ -296,7 +296,7 @@ export function determineDefense(targetActor, attackItem, options) { : targetActor.items.filter( (o) => (o.system.subType === "defense" || o.type === "defense" || o.baseInfo?.type?.includes("defense")) && - (o.system.active || o.effects.find(() => true)?.disabled === false) && + (o.isActive || o.effects.find(() => true)?.disabled === false) && !(options?.ignoreDefenseIds || []).includes(o.id), ); @@ -372,7 +372,7 @@ export function determineDefense(targetActor, attackItem, options) { } // PD bought as hardened - for (const item of activeDefenses.filter((o) => o.system.XMLID == "PD" && o.system.active)) { + for (const item of activeDefenses.filter((o) => o.system.XMLID == "PD" && o.isActive)) { if (item.findModsByXmlid("HARDENED")) { const levels = parseInt(item.system.value) || 0; PD -= levels; @@ -380,7 +380,7 @@ export function determineDefense(targetActor, attackItem, options) { } // ED bought as hardened - for (const item of activeDefenses.filter((o) => o.system.XMLID == "ED" && o.system.active)) { + for (const item of activeDefenses.filter((o) => o.system.XMLID == "ED" && o.isActive)) { if (item.findModsByXmlid("HARDENED")) { const levels = parseInt(item.system.value) || 0; ED -= levels; diff --git a/scss/components/_actor-sheet.scss b/scss/components/_actor-sheet.scss index ce3e4318..58e28f7a 100644 --- a/scss/components/_actor-sheet.scss +++ b/scss/components/_actor-sheet.scss @@ -436,3 +436,7 @@ form div.attack-card div.description { #item-attack-form-application input[type="checkbox"] { margin-left: -2px; } + +.item-oihid { + color: rgba(200, 0, 0, 0.8); +} diff --git a/templates/actor/actor-sheet-partial-powers-item.hbs b/templates/actor/actor-sheet-partial-powers-item.hbs index b0c0dc34..d8fc1be6 100644 --- a/templates/actor/actor-sheet-partial-powers-item.hbs +++ b/templates/actor/actor-sheet-partial-powers-item.hbs @@ -35,13 +35,21 @@ {{#if (or (eq this.system.subType "attack") this.system.roll)}} - + {{#if this.disabledOIHID}} + + {{else}} + + {{/if}} {{/if}} {{#if this.system.showToggle}} - + {{else}} + + {{/if}} {{/if}} diff --git a/templates/actor/actor-sheet.hbs b/templates/actor/actor-sheet.hbs index 8e17916f..209e123a 100644 --- a/templates/actor/actor-sheet.hbs +++ b/templates/actor/actor-sheet.hbs @@ -237,7 +237,11 @@ {{/if}} - + {{#if this.disabledOIHID}} + + {{else}} + + {{/if}}
@@ -283,8 +287,15 @@ {{item.system.end}} - + {{#if this.system.showToggle}} + {{#if this.disabledOIHID}} + + {{else}} + + {{/if}} + {{/if}} {{#if item.system.roll}} - + {{/if}} {{/if}} @@ -454,9 +469,14 @@ {{item.system.value}} {{item.system.velValue}} - {{#if item.system.showToggle}} + {{else}} + + {{/if}} {{/if}} @@ -564,8 +584,14 @@
+ +
+ + +

+