diff --git a/src/lang/en.json b/src/lang/en.json index d72012ba..84c6c424 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -174,9 +174,9 @@ "DL.AvailabilityR": "Rare", "DL.AvailabilityU": "Uncommon", "DL.BackgroundTitle": "Background", - "DL.BecomeFrightenedForRound" : "You become frightened for {round} round.", - "DL.BecomeFrightenedForRounds" : "You become frightened for {round} rounds.", - "DL.BecomeStunned" : "You become stunned for {round} round.", + "DL.BecomeFrightenedForRound": "You become frightened for {round} round.", + "DL.BecomeFrightenedForRounds": "You become frightened for {round} rounds.", + "DL.BecomeStunned": "You become stunned for {round} round.", "DL.ButtonEdit": "Edit", "DL.ButtonView": "View", "DL.ChallengeRequestRollText": "Request Challenge Roll", @@ -308,6 +308,7 @@ "DL.DialogDeleteSpellText": "The Spell will be permanently deleted.", "DL.DialogDeleteTraditionText": "The Tradition and all spells attached will be permanently deleted.", "DL.DialogDeleteTraitText": "The Trait will be permanently deleted.", + "DL.DialogDeleteCreatureRoleText": "The Creature Role will be permanently deleted.", "DL.DialogFortuneAwarded": "Awarded a Fortune point.", "DL.DialogFortuneExpended": "Expended a Fortune point.", "DL.DialogHealedFor": "Healed ", @@ -356,6 +357,7 @@ "DL.DialogWarningActorDamageImmune": "Actor is immune to this type of damage.", "DL.DialogWarningActorsNotSelected": "Actor(s) not selected", "DL.DialogWarningActorsNotTargeted": "Actor(s) not targeted", + "DL.DialogWarningAfflictionFromEffect": "Affliction is applied from effect. Remove the effect to remove the affliction.", "DL.DialogWarningBlindedChallengeFailer": "You're blinded and perception challenge rolls result in failure.", "DL.DialogWarningCreatureArmor": "You can't add armor to a creature. Change the Defense value manually.", "DL.DialogWarningDazedFailer": "You're dazed and cannot use actions.", @@ -391,8 +393,8 @@ "DL.FeaturesTitle": "Features", "DL.FourOrMoreCreatures": "Four or more creatures at once", "DL.FourOrMoreCreaturesInSight": "Sees four or more creatures at once", - "DL.GainedInsanity" : "You gain {insanity} Insanity.", - "DL.GainedInsanityAndGoMad" : "You gain {insanity} Insanity and go mad.", + "DL.GainedInsanity": "You gain {insanity} Insanity.", + "DL.GainedInsanityAndGoMad": "You gain {insanity} Insanity and go mad.", "DL.GMTools": "GM Tools", "DL.GMnote": "GM Notes", "DL.GMnoteEdit": "Edit GM Note", @@ -401,6 +403,7 @@ "DL.ImmuneAffliction": "Immune to Affliction", "DL.ImmuneAttribute": "Immune Attribute", "DL.ImmuneCharacteristic": "Immune Characteristic", + "DL.AfflictionImmunityEffectName": "{affliction} Immunity", "DL.IsFrightening": "Is Frightening", "DL.IsHorrifying": "Is Horrifying", "DL.ItemAddItem": "Add item", @@ -591,6 +594,8 @@ "DL.SettingConcentrationEffectHint": "Apply effect with duration when casting a spell which requires concentration.", "DL.SettingConfirmAncestryPathRemoval": "Confirm ancestry/path removal", "DL.SettingConfirmAncestryPathRemovalHint": "Show a confirmation dialog when attempting to remove an ancestry or path from a character of level 1 or higher.", + "DL.SettingConfirmCreatureRoleRemoval": "Confirm creature role removal", + "DL.SettingConfirmCreatureRoleRemovalHint": "Show a confirmation dialog when attempting to remove a creature role from a character of level 1 or higher.", "DL.SettingConvertIntoBadge": "Convert icons into badges.", "DL.SettingConvertIntoBadgeHint": "Surround ancestry and path icons with a badge background.", "DL.SettingDSN": "Dice So Nice! Configuration", diff --git a/src/lang/es.json b/src/lang/es.json index 4cca37fa..a7b2cfd6 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -302,6 +302,7 @@ "DL.DialogDeleteSpellText": "El Hechizo será borrado permanentemente.", "DL.DialogDeleteTraditionText": "La Tradición y todos los conjuros vinculados serán borrados permanentemente.", "DL.DialogDeleteTraitText": "El Rasgo será borrado permanentemente.", + "DL.DialogDeleteCreatureRoleText": "El Rol de Criatura será borrado permanentemente.", "DL.DialogFortuneAwarded": "Punto de Fortuna otorgado.", "DL.DialogFortuneExpended": "Punto de Fortuna consumido.", "DL.DialogHealedFor": "Curado(s) ", @@ -344,10 +345,11 @@ "DL.DialogUseItemHealingPotion": "Poción de Curación", "DL.DialogUseItemHealingPotionText": "Cura # puntos de daño.", "DL.DialogUseTalent": "Usar Talento", - "DL.DialogWarningActorImmune": "Eres inmune a este estado.", + "DL.DialogWarningActorImmune": "Eres inmune a esta aflicción.", "DL.DialogWarningActorDamageImmune": "Actor es inmune a este tipo de daño.", "DL.DialogWarningActorsNotSelected": "Actor(es) no seleccionados", "DL.DialogWarningActorsNotTargeted": "Actor(es) no marcado(s) como Objetivo", + "DL.DialogWarningAfflictionFromEffect": "Esta aflicción fue aplicado por un efecto. Elimina el efecto para eliminar la aflicción.", "DL.DialogWarningBlindedChallengeFailer": "Estás cegado y todas tus pruebas de percepción fallan automáticamente.", "DL.DialogWarningCreatureArmor": "No puedes añadir una armadura a una criatura. Cambia el valor de Defensa manualmente.", "DL.DialogWarningDazedFailer": "Estás desorientado y no puedes realizar acciones.", @@ -389,6 +391,7 @@ "DL.ImmuneAffliction": "Inmune a Aflicción", "DL.ImmuneAttribute": "Atributo Inmune", "DL.ImmuneCharacteristic": "Característica Inmune", + "DL.AfflictionImmunityEffectName": "Inmunidad a {affliction}", "DL.IsFrightening": "Es Aterradora", "DL.IsHorrifying": "Es Horripilante", "DL.ItemAddItem": "Añadir Objeto", @@ -569,6 +572,8 @@ "DL.SettingConcentrationEffectHint": "Aplicar efecto con la duración cuandose lance un hechizo que requiera concentración.", "DL.SettingConfirmAncestryPathRemoval": "Confirmar eliminación de linaje/senda", "DL.SettingConfirmAncestryPathRemovalHint": "Muestra un diálogo de confirmación al intentar borrar un linaje o una senda de un personaje de nivel 1 o mayor.", + "DL.SettingConfirmCreatureRoleRemoval": "Confirmar eliminación de rol de criatura", + "DL.SettingConfirmCreatureRoleRemovalHint": "Muestra un diálogo de confirmación al intentar borrar un rol de criatura de una criatura.", "DL.SettingConvertIntoBadge": "Convertir en insignia.", "DL.SettingConvertIntoBadgeHint": "Rodear los icono de linaje y senda con un fondo de insignia.", "DL.SettingDSN": "Configuración de Dice So Nice!", diff --git a/src/module/actor/actor.js b/src/module/actor/actor.js index f367f1ed..49fb3948 100644 --- a/src/module/actor/actor.js +++ b/src/module/actor/actor.js @@ -19,6 +19,7 @@ import { import {handleCreateAncestry, handleCreatePath, handleCreateRole, handleCreateRelic } from '../item/nested-objects' import {TokenManager} from '../pixi/token-manager' import {findAddEffect, findDeleteEffect} from "../demonlord"; +import { createActorNestedItems } from '../item/nested-objects' const tokenManager = new TokenManager() @@ -344,6 +345,80 @@ export class DemonlordActor extends Actor { // Don't need to update anything if the only change is the edit item state const isNameChange = documents.length === 1 && data[0].name !== undefined + const documentChanges = {} + + // Make a list of the necessary changes to the levels, which we will update afterwards + for (const sourceDocument of documents) { + if (sourceDocument.type === 'ancestry' || sourceDocument.type === 'path') { + // Property will be the level and value is an array of stuff + const addedItems = {} + let updateDocument = data.find(d => d._id === sourceDocument._id) + + if (!updateDocument.system.levels?.length) continue // Didn't change the levels, nothing to do + + const itemsFromThisDocument = this.items.filter(i => i.flags.demonlord?.parentItemId === sourceDocument._id) + + documentChanges[sourceDocument._id] = { + } + + // Now go through each level and search for the items + for (const level of updateDocument.system.levels.filter(l => parseInt(l.level) <= this.system.level)) { + addedItems[level.level] = { + languages: [], + spells: [], + talents: [], + talentspick: [], + talentsSelected: [] + } + + // Languages + for (const item of level.languages) { + const foundItem = itemsFromThisDocument.find(i => i.flags.demonlord?.levelRequired === level.level && i.flags.demonlord?.nestedItemId === item.id) + + if (!foundItem) { + addedItems[level.level].languages.push(item) + } else { + itemsFromThisDocument.splice(itemsFromThisDocument.indexOf(foundItem), 1) + } + } + + // Spells + for (const item of level.spells) { + const foundItem = itemsFromThisDocument.find(i => i.flags.demonlord?.levelRequired === level.level && i.flags.demonlord?.nestedItemId === item.id) + + if (!foundItem) { + addedItems[level.level].spells.push(item) + } else { + itemsFromThisDocument.splice(itemsFromThisDocument.indexOf(foundItem), 1) + } + } + + // Talents + for (const item of level.talents.concat(level.talentspick, level.talentsSelected)) { + const foundItem = itemsFromThisDocument.find(i => i.flags.demonlord?.levelRequired === level.level && i.flags.demonlord?.nestedItemId === item.id) + + if (!foundItem) { + addedItems[level.level].talents.push(item) + } else { + itemsFromThisDocument.splice(itemsFromThisDocument.indexOf(foundItem), 1) + } + } + + documentChanges[sourceDocument._id][level.level] = { + toRemove: itemsFromThisDocument, + toAdd: addedItems[level.level].languages.concat(addedItems[level.level].spells, addedItems[level.level].talents) + } + } + + this.deleteEmbeddedDocuments('Item', Object.values(documentChanges).map(o => Object.values(o)).flat()[0].toRemove.map(i => i.id)) + + for (const documentSource in documentChanges) { + for (const level in documentChanges[documentSource]) + await createActorNestedItems(this, documentChanges[documentSource][level].toAdd, documentSource, level) + } + } + } + if ((collection === 'items' || collection === 'effects') && userId === game.userId && !options.noEmbedEffects) await this._handleOnUpdateDescendant(documents, isNameChange).then(_ => this.sheet.render()) } @@ -572,7 +647,7 @@ export class DemonlordActor extends Actor { await challengeRoll.evaluate() if (mode) postCustomTextToChat(this, challengeRoll, mode, attribute.key) - else + else postAttributeToChat(this, attribute.key, challengeRoll, parseInt(inputBoons) || 0, parseInt(inputModifier) || 0) for (let effect of this.appliedEffects) { diff --git a/src/module/actor/sheets/base-actor-sheet.js b/src/module/actor/sheets/base-actor-sheet.js index 925d1eb7..299c934f 100644 --- a/src/module/actor/sheets/base-actor-sheet.js +++ b/src/module/actor/sheets/base-actor-sheet.js @@ -10,7 +10,7 @@ import tippy from "tippy.js"; import { buildDropdownListHover } from "../../utils/handlebars-helpers"; import { DLAfflictions } from '../../active-effects/afflictions' import launchRollDialog from '../../dialog/roll-dialog' -import {TokenManager} from '../../pixi/token-manager' +import { TokenManager } from '../../pixi/token-manager' const tokenManager = new TokenManager() @@ -129,6 +129,7 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh context.generalEffects = prepareActiveEffectCategories(Array.from(this.document.allApplicableEffects()), true) context.effectsOverview = buildOverview(this.document) context.flags = this.document.flags + context.immunities = this.getImmunities() context.addCreatureInventoryTab = game.settings.get('demonlord', 'addCreatureInventoryTab') context.hideTurnMode = game.settings.get('demonlord', 'optionalRuleInitiativeMode') === 's' ? false : true context.hideFortune = game.settings.get('demonlord', 'fortuneHide') ? true : false @@ -477,74 +478,109 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh }) // Affliction checkboxes - e.querySelectorAll('[data-tab="afflictions"] .item-group-affliction.checkable')?.forEach(el => el.addEventListener('click', async ev => { - const input = ev.target.parentElement.firstElementChild + e.querySelectorAll('[data-tab="afflictions"] .item-group-affliction.checkable')?.forEach(el => el.addEventListener('mousedown', async ev => { + const input = ev.target.closest('.checkable').querySelector('input') const checked = input.checked const afflictionId = input.dataset.name - if (checked) { - input.checked = false - const affliction = this.actor.effects.find(ef => ef?.statuses?.has(afflictionId)) - if (!affliction) return false - await affliction.delete() - } else { - input.checked = true - if (this.actor.isImmuneToAffliction(afflictionId)) { - ui.notifications.warn(game.i18n.localize('DL.DialogWarningActorImmune')); - return false; - } - const affliction = CONFIG.statusEffects.find(a => a.id === afflictionId) - if (!affliction) return false - affliction['statuses'] = [affliction.id] - await ActiveEffect.create(affliction, { parent: this.actor }) - const targets = tokenManager.targets - switch (afflictionId) { + if (ev.button == 0) { + if (checked) { + + // Ignore if there's an active effect that sets this condition (except for the status effects) + const effect = this.actor.appliedEffects.find(ae => ae.statuses.size === 0 && ae.changes.some(c => c.key === 'system.maluses.affliction' && c.value === afflictionId)) + + if (effect) { + ui.notifications.warn(game.i18n.localize('DL.DialogWarningAfflictionFromEffect')) + } else { + input.checked = false + const affliction = this.actor.effects.find(ef => ef?.statuses?.has(afflictionId)) + if (!affliction) return false + await affliction.delete() + } + } else { + if (this.actor.isImmuneToAffliction(afflictionId)) { + ui.notifications.warn(game.i18n.localize('DL.DialogWarningActorImmune')); + return false; + } + + input.checked = true + const affliction = CONFIG.statusEffects.find(a => a.id === afflictionId) + if (!affliction) return false + affliction['statuses'] = [affliction.id] + await ActiveEffect.create(affliction, { parent: this.actor }) + const targets = tokenManager.targets + switch (afflictionId) { case 'help': { - const attribute = this.actor.system.attributes.intellect - if (!DLAfflictions.isActorBlocked(this.actor, 'challenge', attribute.key) && targets.length === 1) - launchRollDialog(this.actor.name + ' - ' + game.i18n.localize('DL.DialogChallengeRoll') + attribute.label, async (event, html) => { - let result = await this.actor.rollAttributeChallenge(attribute, html.form.elements.boonsbanes.value, html.form.elements.modifier.value) - if (result._total >= 10 || game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' && result._total >= 11) { - affliction['statuses'] = [affliction.id] - const effect = CONFIG.statusEffects.find(a => a.id === "helped") - effect['statuses'] = [effect.id] - if (game.user.isGM) { - await ActiveEffect.create(effect, { - parent: targets[0].actor - }) - } else { - game.socket.emit('system.demonlord', { - request: "createEffect", - tokenuuid: targets[0].document.uuid, - effectData: effect - }) - } - } - }) - break; + const attribute = this.actor.system.attributes.intellect + if (!DLAfflictions.isActorBlocked(this.actor, 'challenge', attribute.key) && targets.length === 1) + launchRollDialog(this.actor.name + ' - ' + game.i18n.localize('DL.DialogChallengeRoll') + attribute.label, async (event, html) => { + let result = await this.actor.rollAttributeChallenge(attribute, html.form.elements.boonsbanes.value, html.form.elements.modifier.value) + if (result._total >= 10 || game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' && result._total >= 11) { + affliction['statuses'] = [affliction.id] + const effect = CONFIG.statusEffects.find(a => a.id === "helped") + effect['statuses'] = [effect.id] + if (game.user.isGM) { + await ActiveEffect.create(effect, { + parent: targets[0].actor + }) + } else { + game.socket.emit('system.demonlord', { + request: "createEffect", + tokenuuid: targets[0].document.uuid, + effectData: effect + }) + } + } + }) + break; } case 'stabilize': { - const attribute = this.actor.system.attributes.intellect - const isIncapacitated = targets.length === 1 ? targets[0].actor.appliedEffects.find(ef => ef?.statuses?.has('incapacitated')) : false - if (!DLAfflictions.isActorBlocked(this.actor, 'challenge', attribute.key) && isIncapacitated) - launchRollDialog(this.actor.name + ' - ' + game.i18n.localize('DL.DialogChallengeRoll') + attribute.label, async (event, html) => { - let result = await this.actor.rollAttributeChallenge(attribute, html.form.elements.boonsbanes.value, html.form.elements.modifier.value) - if (result._total >= 10 || game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' && result._total >= 11) { - if (game.user.isGM) { - await targets[0].actor.increaseDamage(-1) - } else { - game.socket.emit('system.demonlord', { - request: "increaseDamage", - tokenuuid: targets[0].document.uuid, - increment: -1 - }) - } - } - }) - break; + const attribute = this.actor.system.attributes.intellect + const isIncapacitated = targets.length === 1 ? targets[0].actor.appliedEffects.find(ef => ef?.statuses?.has('incapacitated')) : false + if (!DLAfflictions.isActorBlocked(this.actor, 'challenge', attribute.key) && isIncapacitated) + launchRollDialog(this.actor.name + ' - ' + game.i18n.localize('DL.DialogChallengeRoll') + attribute.label, async (event, html) => { + let result = await this.actor.rollAttributeChallenge(attribute, html.form.elements.boonsbanes.value, html.form.elements.modifier.value) + if (result._total >= 10 || game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' && result._total >= 11) { + if (game.user.isGM) { + await targets[0].actor.increaseDamage(-1) + } else { + game.socket.emit('system.demonlord', { + request: "increaseDamage", + tokenuuid: targets[0].document.uuid, + increment: -1 + }) + } + } + }) + break; + } + } + } + return true + } else if (ev.button == 2) { + // Toggle immunity + const effectName = game.i18n.format('DL.AfflictionImmunityEffectName', { affliction: game.i18n.localize(`DL.${afflictionId}`) }) + const immuneEffects = this.actor.appliedEffects.filter(a => !a.disabled).filter(a => a.name === effectName && a.changes.length === 1 && a.changes[0].key === 'system.bonuses.immune.affliction' && a.changes[0].value === afflictionId) + if (immuneEffects?.length) { + await immuneEffects[0].delete() + } else { + await this.actor.createEmbeddedDocuments('ActiveEffect', [ + { + name: effectName, + icon: this.actor.img, + origin: this.actor.uuid, + transfer: false, + flags: { demonlord: { sourceType: this.actor.type } }, + changes: [ + { + key: 'system.bonuses.immune.affliction', + value: afflictionId, + mode: 2 + } + ] } + ]) } } - return true })) // Toggle accordion @@ -836,4 +872,13 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh }) return incantation } + + getImmunities() { + const immunities = {} + + for (let immunityEffect of this.actor.appliedEffects.flatMap(e => e.changes).filter(c => c.key === 'system.bonuses.immune.affliction')) { + immunities[immunityEffect.value] = true + } + return immunities + } } diff --git a/src/module/actor/sheets/creature-sheet.js b/src/module/actor/sheets/creature-sheet.js index cb5f1a9a..69ce6128 100644 --- a/src/module/actor/sheets/creature-sheet.js +++ b/src/module/actor/sheets/creature-sheet.js @@ -119,11 +119,17 @@ export default class DLCreatureSheet extends DLBaseActorSheet { /* -------------------------------------------- */ async onEditRole(ev) { - const div = $(ev.currentTarget) - const role = this.actor.getEmbeddedDocument('Item', div.data('itemId')) + const div = ev.target.closest('.role-edit') + const role = this.actor.getEmbeddedDocument('Item', div.dataset.itemId) if (ev.button == 0) role.sheet.render(true) - else if (ev.button == 2) await role.delete({ parent: this.actor }) + else if (ev.button == 2) { + if (game.settings.get('demonlord', 'confirmCreatureRoleRemoval')) { + await this.showDeleteDialog(game.i18n.localize('DL.DialogAreYouSure'), game.i18n.localize('DL.DialogDeleteCreatureRoleText'), div) + } else { + await role.delete({ parent: this.actor }) + } + } } async onEditRelic(ev) { diff --git a/src/module/settings.js b/src/module/settings.js index 1d7318d8..5619fdef 100644 --- a/src/module/settings.js +++ b/src/module/settings.js @@ -841,6 +841,14 @@ export const registerSettings = function () { type: Boolean, config: true, }) + game.settings.register('demonlord', 'confirmCreatureRoleRemoval', { + name: game.i18n.localize('DL.SettingConfirmCreatureRoleRemoval'), + hint: game.i18n.localize('DL.SettingConfirmCreatureRoleRemovalHint'), + default: true, + scope: 'world', + type: Boolean, + config: true, + }) game.settings.register('demonlord', 'fortuneAwardPrevented', { name: game.i18n.localize('DL.SettingFortuneAwardPrevented'), hint: game.i18n.localize('DL.SettingFortuneAwardPreventedHint'), diff --git a/src/styles/v2/_sheets.scss b/src/styles/v2/_sheets.scss index 0237330a..380fad1e 100644 --- a/src/styles/v2/_sheets.scss +++ b/src/styles/v2/_sheets.scss @@ -517,9 +517,9 @@ span.vertical-rule { } // Afflictions -$afflictions-demonlord: 'concentrate', 'defend', 'help', 'helped', 'prepare', 'reload', 'retreat', 'rush', 'stabilize', 'charmed', - 'compelled', 'defenseless', 'diseased', 'fatigued', 'horrified', 'grabbed', 'immobilized', 'impaired', 'surprised', - 'slowed', 'injured', 'incapacitated', 'disabled', 'dying', 'surrounded'; +$afflictions-demonlord: 'concentrate', 'defend', 'help', 'helped', 'prepare', 'reload', 'retreat', 'rush', 'stabilize', + 'charmed', 'compelled', 'defenseless', 'diseased', 'fatigued', 'horrified', 'grabbed', 'immobilized', 'impaired', + 'surprised', 'slowed', 'injured', 'incapacitated', 'disabled', 'dying', 'surrounded'; @each $affliction in $afflictions-demonlord { .icon-#{$affliction} { @include demonlord-icon('../assets/icons/effects/#{$affliction}.svg'); @@ -863,6 +863,13 @@ span.text-vs { } } +.checkable.locked::after { + content: '\f023'; // fa-lock + font-family: 'Font Awesome 6 Pro'; + font-weight: 900; + position: absolute; + right: 10px; +} /*******************/ /* Toggle */ /*******************/ diff --git a/src/templates/actor/tabs/afflictions.hbs b/src/templates/actor/tabs/afflictions.hbs index b7eff740..b1abd4b6 100644 --- a/src/templates/actor/tabs/afflictions.hbs +++ b/src/templates/actor/tabs/afflictions.hbs @@ -1,6 +1,6 @@
{{#*inline "dlAffliction"}} -
@@ -30,26 +30,26 @@
- {{> dlAffliction name="asleep" value=flags.demonlord.asleep label="DL.asleep" tooltip="DL.AfflictionsAsleep" }} - {{> dlAffliction name="blinded" value=flags.demonlord.blinded label="DL.blinded" tooltip="DL.AfflictionsBlinded" }} - {{> dlAffliction name="charmed" value=flags.demonlord.charmed label="DL.charmed" tooltip="DL.AfflictionsCharmed" }} - {{> dlAffliction name="compelled" value=flags.demonlord.compelled label="DL.compelled" tooltip="DL.AfflictionsCompelled" }} - {{> dlAffliction name="dazed" value=flags.demonlord.dazed label="DL.dazed" tooltip="DL.AfflictionsDazed" }} - {{> dlAffliction name="deafened" value=flags.demonlord.deafened label="DL.deafened" tooltip="DL.AfflictionsDeafened" }} - {{> dlAffliction name="defenseless" value=flags.demonlord.defenseless label="DL.defenseless" tooltip="DL.AfflictionsDefenseless"}} - {{> dlAffliction name="diseased" value=flags.demonlord.diseased label="DL.diseased" tooltip="DL.AfflictionsDiseased" }} - {{> dlAffliction name="fatigued" value=flags.demonlord.fatigued label="DL.fatigued" tooltip="DL.AfflictionsFatigued" }} - {{> dlAffliction name="frightened" value=flags.demonlord.frightened label="DL.frightened" tooltip="DL.AfflictionsFrightened" }} - {{> dlAffliction name="horrified" value=flags.demonlord.horrified label="DL.horrified" tooltip="DL.AfflictionsHorrified" }} - {{> dlAffliction name="grabbed" value=flags.demonlord.grabbed label="DL.grabbed" tooltip="DL.AfflictionsGrabbed" }} - {{> dlAffliction name="immobilized" value=flags.demonlord.immobilized label="DL.immobilized" tooltip="DL.AfflictionsImmobilized"}} - {{> dlAffliction name="impaired" value=flags.demonlord.impaired label="DL.impaired" tooltip="DL.AfflictionsImpaired" }} - {{> dlAffliction name="poisoned" value=flags.demonlord.poisoned label="DL.poisoned" tooltip="DL.AfflictionsPoisoned" }} - {{> dlAffliction name="prone" value=flags.demonlord.prone label="DL.prone" tooltip="DL.AfflictionsProne" }} - {{> dlAffliction name="slowed" value=flags.demonlord.slowed label="DL.slowed" tooltip="DL.AfflictionsSlowed" }} - {{> dlAffliction name="stunned" value=flags.demonlord.stunned label="DL.stunned" tooltip="DL.AfflictionsStunned" }} - {{> dlAffliction name="surprised" value=flags.demonlord.surprised label="DL.surprised" tooltip="DL.AfflictionsSurprised" }} - {{> dlAffliction name="unconscious" value=flags.demonlord.unconscious label="DL.unconscious" tooltip="DL.AfflictionsUnconscious"}} + {{> dlAffliction name="asleep" value=flags.demonlord.asleep immune=immunities.asleep label="DL.asleep" tooltip="DL.AfflictionsAsleep" }} + {{> dlAffliction name="blinded" value=flags.demonlord.blinded immune=immunities.blinded label="DL.blinded" tooltip="DL.AfflictionsBlinded" }} + {{> dlAffliction name="charmed" value=flags.demonlord.charmed immune=immunities.charmed label="DL.charmed" tooltip="DL.AfflictionsCharmed" }} + {{> dlAffliction name="compelled" value=flags.demonlord.compelled immune=immunities.compelled label="DL.compelled" tooltip="DL.AfflictionsCompelled" }} + {{> dlAffliction name="dazed" value=flags.demonlord.dazed immune=immunities.dazed label="DL.dazed" tooltip="DL.AfflictionsDazed" }} + {{> dlAffliction name="deafened" value=flags.demonlord.deafened immune=immunities.deafened label="DL.deafened" tooltip="DL.AfflictionsDeafened" }} + {{> dlAffliction name="defenseless" value=flags.demonlord.defenseless immune=immunities.defenseless label="DL.defenseless" tooltip="DL.AfflictionsDefenseless"}} + {{> dlAffliction name="diseased" value=flags.demonlord.diseased immune=immunities.diseased label="DL.diseased" tooltip="DL.AfflictionsDiseased" }} + {{> dlAffliction name="fatigued" value=flags.demonlord.fatigued immune=immunities.fatigued label="DL.fatigued" tooltip="DL.AfflictionsFatigued" }} + {{> dlAffliction name="frightened" value=flags.demonlord.frightened immune=immunities.frightened label="DL.frightened" tooltip="DL.AfflictionsFrightened" }} + {{> dlAffliction name="horrified" value=flags.demonlord.horrified immune=immunities.horrified label="DL.horrified" tooltip="DL.AfflictionsHorrified" }} + {{> dlAffliction name="grabbed" value=flags.demonlord.grabbed immune=immunities.grabbed label="DL.grabbed" tooltip="DL.AfflictionsGrabbed" }} + {{> dlAffliction name="immobilized" value=flags.demonlord.immobilized immune=immunities.immobilized label="DL.immobilized" tooltip="DL.AfflictionsImmobilized"}} + {{> dlAffliction name="impaired" value=flags.demonlord.impaired immune=immunities.impaired label="DL.impaired" tooltip="DL.AfflictionsImpaired" }} + {{> dlAffliction name="poisoned" value=flags.demonlord.poisoned immune=immunities.poisoned label="DL.poisoned" tooltip="DL.AfflictionsPoisoned" }} + {{> dlAffliction name="prone" value=flags.demonlord.prone immune=immunities.prone label="DL.prone" tooltip="DL.AfflictionsProne" }} + {{> dlAffliction name="slowed" value=flags.demonlord.slowed immune=immunities.slowed label="DL.slowed" tooltip="DL.AfflictionsSlowed" }} + {{> dlAffliction name="stunned" value=flags.demonlord.stunned immune=immunities.stunned label="DL.stunned" tooltip="DL.AfflictionsStunned" }} + {{> dlAffliction name="surprised" value=flags.demonlord.surprised immune=immunities.surprised label="DL.surprised" tooltip="DL.AfflictionsSurprised" }} + {{> dlAffliction name="unconscious" value=flags.demonlord.unconscious immune=immunities.unconscious label="DL.unconscious" tooltip="DL.AfflictionsUnconscious"}}