Added implementation of unstoppable

This commit is contained in:
WBHarry 2025-11-22 21:43:31 +01:00
parent 87643dc662
commit eb573e7ccb
38 changed files with 256 additions and 99 deletions

View file

@ -130,7 +130,8 @@
"RangeDependance": {
"hint": "Settings for an optional distance at which this effect should activate",
"title": "Range Dependant"
}
},
"immuneStatusText": "Immunity: {status}"
},
"ACTORS": {
"Adversary": {
@ -396,7 +397,8 @@
"stressReduction": "Reduce By Stress",
"title": "Damage Reduction",
"unncessaryStress": "You don't need to expend stress",
"usedMarks": "Used Marks"
"usedMarks": "Used Marks",
"reduceSeverity": "Severity Reduced By {nr}"
},
"DeathMove": {
"selectMove": "Select Move",
@ -1031,7 +1033,8 @@
},
"ItemResourceType": {
"simple": "Simple",
"diceValue": "Dice Value"
"diceValue": "Dice Value",
"die": "Die"
},
"Range": {
"self": {
@ -2526,7 +2529,8 @@
"abilityCheckTitle": "{ability} Check"
},
"effectSummary": {
"title": "Effects Applied"
"title": "Effects Applied",
"immunityTo": "Immunity: {immunities}"
},
"featureTitle": "Class Feature",
"groupRoll": {

View file

@ -10,6 +10,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.reject = reject;
this.actor = actor;
this.damage = damage;
this.damageType = damageType;
this.rulesDefault = game.settings.get(
CONFIG.DH.id,
CONFIG.DH.SETTINGS.gameSettings.Automation
@ -57,6 +58,11 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
null
);
this.reduceSeverity = this.damageType.reduce((value, curr) => {
return Math.max(this.actor.system.rules.damageReduction.reduceSeverity[curr], value);
}, 0);
this.actor.system.rules.damageReduction.reduceSeverity[this.damageType];
this.thresholdImmunities = Object.keys(actor.system.rules.damageReduction.thresholdImmunities).reduce(
(acc, key) => {
if (actor.system.rules.damageReduction.thresholdImmunities[key])
@ -111,7 +117,9 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
CONFIG.DH.GENERAL.ruleChoice.onWithToggle.id,
CONFIG.DH.GENERAL.ruleChoice.offWithToggle.id
].includes(this.rulesDefault);
context.thresholdImmunities = this.thresholdImmunities;
context.reduceSeverity = this.reduceSeverity;
context.thresholdImmunities =
Object.keys(this.thresholdImmunities).length > 0 ? this.thresholdImmunities : null;
const { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage } =
this.getDamageInfo();
@ -173,6 +181,9 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.damage - armorMarkReduction - selectedStressMarks.length - stressReductions.length,
0
);
if (this.reduceSeverity) {
currentDamage = Math.max(currentDamage - this.reduceSeverity, 0);
}
if (this.thresholdImmunities[currentDamage]) currentDamage = 0;

View file

@ -31,6 +31,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
toggleEquipItem: CharacterSheet.#toggleEquipItem,
toggleResourceDice: CharacterSheet.#toggleResourceDice,
handleResourceDice: CharacterSheet.#handleResourceDice,
advanceResourceDie: CharacterSheet.#advanceResourceDie,
cancelBeastform: CharacterSheet.#cancelBeastform,
useDowntime: this.useDowntime
},
@ -148,6 +149,10 @@ export default class CharacterSheet extends DHBaseActorSheet {
htmlElement.querySelectorAll('.armor-marks-input').forEach(element => {
element.addEventListener('change', this.updateArmorMarks.bind(this));
});
htmlElement.querySelectorAll('.item-resource.die').forEach(element => {
element.addEventListener('contextmenu', this.lowerResourceDie.bind(this));
});
}
/** @inheritdoc */
@ -858,6 +863,27 @@ export default class CharacterSheet extends DHBaseActorSheet {
});
}
/** */
static #advanceResourceDie(_, target) {
this.updateResourceDie(target, true);
}
lowerResourceDie(event) {
event.preventDefault();
event.stopPropagation();
this.updateResourceDie(event.target, false);
}
async updateResourceDie(target, advance) {
const item = await getDocFromElement(target);
if (!item) return;
const advancedValue = item.system.resource.value + (advance ? 1 : -1);
await item.update({
'system.resource.value': Math.min(advancedValue, Number(item.system.resource.dieFaces.split('d')[1]))
});
}
/**
*
*/

View file

@ -24,7 +24,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
acc.push({
name: game.i18n.localize(statusData.name),
statuses: [status],
img: statusData.icon,
img: statusData.icon ?? statusData.img,
tint: effect.tint
});
}

View file

@ -1519,6 +1519,10 @@ export const itemResourceTypes = {
diceValue: {
id: 'diceValue',
label: 'DAGGERHEART.CONFIG.ItemResourceType.diceValue'
},
die: {
id: 'die',
label: 'DAGGERHEART.CONFIG.ItemResourceType.die'
}
};

View file

@ -57,6 +57,12 @@ export default class DhpAdversary extends BaseDataActor {
hitPoints: resourceField(0, 0, 'DAGGERHEART.GENERAL.HitPoints.plural', true),
stress: resourceField(0, 0, 'DAGGERHEART.GENERAL.stress', true)
}),
rules: new fields.SchemaField({
conditionImmunities: new fields.SchemaField({
vulnerable: new fields.BooleanField({ initial: false }),
restrained: new fields.BooleanField({ initial: false })
})
}),
attack: new ActionField({
initial: {
name: 'Attack',

View file

@ -250,6 +250,10 @@ export default class DhCharacter extends BaseDataActor {
thresholdImmunities: new fields.SchemaField({
minor: new fields.BooleanField({ initial: false })
}),
reduceSeverity: new fields.SchemaField({
magical: new fields.NumberField({ initial: 0, min: 0 }),
physical: new fields.NumberField({ initial: 0, min: 0 })
}),
disabledArmor: new fields.BooleanField({ intial: false })
}),
attack: new fields.SchemaField({
@ -279,6 +283,10 @@ export default class DhCharacter extends BaseDataActor {
})
})
}),
conditionImmunities: new fields.SchemaField({
vulnerable: new fields.BooleanField({ initial: false }),
restrained: new fields.BooleanField({ initial: false })
}),
runeWard: new fields.BooleanField({ initial: false }),
burden: new fields.SchemaField({
ignore: new fields.BooleanField()

View file

@ -51,6 +51,12 @@ export default class DhCompanion extends BaseDataActor {
}
}
),
rules: new fields.SchemaField({
conditionImmunities: new fields.SchemaField({
vulnerable: new fields.BooleanField({ initial: false }),
restrained: new fields.BooleanField({ initial: false })
})
}),
attack: new ActionField({
initial: {
name: 'Attack',

View file

@ -47,6 +47,7 @@ export default class EffectsField extends fields.ArrayField {
static async applyEffects(targets) {
if (!this.effects?.length || !targets?.length) return;
const conditions = CONFIG.DH.GENERAL.conditions();
let effects = this.effects;
const messageTargets = [];
targets.forEach(async baseToken => {
@ -56,7 +57,20 @@ export default class EffectsField extends fields.ArrayField {
const token =
canvas.tokens.get(baseToken.id) ?? foundry.utils.fromUuidSync(baseToken.actorId).prototypeToken;
if (!token) return;
messageTargets.push(token.document ?? token);
const messageToken = token.document ?? token;
const conditionImmunities = messageToken.actor.system.rules.conditionImmunities ?? {};
messageTargets.push({
token: messageToken,
conditionImmunities: Object.values(conditionImmunities).some(x => x)
? game.i18n.format('DAGGERHEART.UI.Chat.effectSummary.immunityTo', {
immunities: Object.keys(conditionImmunities)
.filter(x => conditionImmunities[x])
.map(x => game.i18n.localize(conditions[x].name))
.join(', ')
})
: null
});
effects.forEach(async e => {
const effect = this.item.effects.get(e._id);

View file

@ -57,6 +57,27 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
update.img = 'icons/magic/life/heart-cross-blue.webp';
}
const immuneStatuses =
data.statuses?.filter(
status =>
this.parent.system.rules?.conditionImmunities &&
this.parent.system.rules.conditionImmunities[status]
) ?? [];
if (immuneStatuses.length > 0) {
update.statuses = data.statuses.filter(x => !immuneStatuses.includes(x));
const conditions = CONFIG.DH.GENERAL.conditions();
const scrollingTexts = immuneStatuses.map(status => ({
text: game.i18n.format('DAGGERHEART.ACTIVEEFFECT.immuneStatusText', {
status: game.i18n.localize(conditions[status].name)
})
}));
if (update.statuses.length > 0) {
setTimeout(() => scrollingTexts, 500);
} else {
this.parent.queueScrollText(scrollingTexts);
}
}
if (Object.keys(update).length > 0) {
await this.updateSource(update);
}
@ -76,7 +97,10 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
change.value = change.value.replaceAll(/origin\.@/gi, '@');
try {
const effect = foundry.utils.fromUuidSync(change.effect.origin);
const doc = effect.parent?.parent;
const doc =
effect.parent?.parent instanceof game.system.api.documents.DhpActor
? effect.parent
: effect.parent.parent;
if (doc) parseModel = doc;
} catch (_) {}
}

View file

@ -12,7 +12,10 @@ export const preloadHandlebarsTemplates = async function () {
'systems/daggerheart/templates/sheets/global/partials/action-item.hbs',
'systems/daggerheart/templates/sheets/global/partials/domain-card-item.hbs',
'systems/daggerheart/templates/sheets/global/partials/item-resource.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-section.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-section/resource-section.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-section/simple.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-section/dice-value.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-section/die.hbs',
'systems/daggerheart/templates/sheets/global/partials/resource-bar.hbs',
'systems/daggerheart/templates/components/card-preview.hbs',
'systems/daggerheart/templates/levelup/parts/selectable-card-preview.hbs',

View file

@ -401,7 +401,7 @@
"description": "<p>You are <em>Restrained</em> until you break free with a successful Strength Roll.</p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -580,7 +580,7 @@
"description": "<p>You are<em> Restrained</em> in smoky chains until you break free with a successful Strength or Instinct Roll. A target Restrained by this feature must spend a Hope to make an action roll.</p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -439,7 +439,7 @@
"description": "<p>You are <em>Restrained </em>until the Defender takes Severe damage.</p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -385,7 +385,7 @@
"description": "<p>You are <em>Restrained</em> until you break free with a successful Finesse or Strength Roll.</p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -624,7 +624,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -426,7 +426,7 @@
"description": "<p>You are <em>Restrained</em> and <em>Vulnerable</em> until you break free with a successful Strength Roll or the Kraken takes Major or greater damage. While <em>Restrained</em> and <em>Vulnerable</em> in this way, you must mark a Stress when you make an action roll.</p>",
"tint": "#ffffff",
"statuses": [
"restrain",
"restrained",
"vulnerable"
],
"sort": 0,

View file

@ -432,7 +432,7 @@
"description": "<p>You are <em>Restrained</em> and <em>Vulnerable</em> until you break free, ending both conditions, with a successful Finesse or Strength Roll (13).</p><p>[[/dr trait=finesse difficulty=13]]<br />[[/dr trait=strength difficulty=13]]</p>",
"tint": "#ffffff",
"statuses": [
"restrain",
"restrained",
"vulnerable"
],
"sort": 0,

View file

@ -361,7 +361,7 @@
"description": "<p>You are<strong> </strong><em>Restrained</em> within the Gaoler until freed with a successful Strength Roll (18). While <em>Restrained</em>, you can only attack the Gaoler. </p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -399,7 +399,7 @@
"description": "<p>You are <em>Restrained</em> until you're freed with a successful Strength Roll. When a creature makes an action roll against the cage, they must mark a Stress. </p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -211,7 +211,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -267,7 +267,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},
@ -313,7 +313,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},
@ -359,7 +359,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -112,7 +112,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -173,7 +173,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},
@ -219,7 +219,7 @@
"description": "",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -302,7 +302,7 @@
"description": "<p><em>Restrained</em> lasts until youre freed with a successful Finesse or Strength roll or by dealing at least 6 damage to the vines.</p>",
"tint": "#ffffff",
"statuses": [
"restrain"
"restrained"
],
"sort": 0,
"flags": {},

View file

@ -313,7 +313,7 @@
"description": "<p><em>Restrained</em> and <em>Vulnerable</em> until you break free, clearing both conditions, with a successful Finesse or Strength Roll or by dealing 10 damage to the vines. When the target makes a roll to escape, they take <strong>1d8+4</strong> physical damage and lose a Hope.</p><section class=\"secret\" id=\"secret-Eui1zx8GKoUhEXq6\"><p><em>What painful memories do the vines bring to the surface as they pierce flesh?</em></p></section>",
"tint": "#ffffff",
"statuses": [
"restrain",
"restrained",
"vulnerable"
],
"sort": 0,

View file

@ -80,39 +80,52 @@
gap: 5px;
}
.token-target-container {
.token-target-outer-container {
display: flex;
align-items: center;
gap: 13px;
border-radius: 6px;
padding: 0 2px;
border-radius: 6px;
background: transparent;
transition: all 0.3s ease;
padding: 5px;
transition: all 0.3s ease;
flex-direction: column;
gap: 2px;
&.clickable {
cursor: pointer;
.token-target-container {
display: flex;
align-items: center;
gap: 13px;
border-radius: 6px;
padding: 0 2px;
border-radius: 6px;
background: transparent;
transition: all 0.3s ease;
padding: 5px;
transition: all 0.3s ease;
&:hover {
background: @golden-10;
&.clickable {
cursor: pointer;
&:hover {
background: @golden-10;
}
}
img {
width: 40px;
height: 40px;
border-radius: 50%;
pointer-events: none;
}
.title {
font-size: var(--font-size-20);
color: @golden;
font-weight: 700;
margin: 0;
pointer-events: none;
}
}
img {
width: 40px;
height: 40px;
border-radius: 50%;
pointer-events: none;
}
.title {
font-size: var(--font-size-20);
color: @golden;
font-weight: 700;
margin: 0;
pointer-events: none;
.token-target-immunity {
white-space: nowrap;
font-style: italic;
font-size: 8px;
padding: 0 5px;
}
}

View file

@ -71,12 +71,20 @@
</div>
{{/each}}
{{#if thresholdImmunities}}
<div class="resources-container">
<div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}</h4>
{{#if reduceSeverity}}
<div class="resources-container">
<div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.reduceSeverity" nr=reduceSeverity}}</h4>
</div>
</div>
{{/if}}
{{#if thresholdImmunities}}
<div class="resources-container">
<div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}</h4>
</div>
</div>
</div>
{{/if}}
{{#each thresholdImmunities as | immunity key |}}

View file

@ -56,7 +56,7 @@ Parameters:
</div>
{{!-- Simple Resource --}}
{{#if (and (not hideResources) (eq item.system.resource.type 'simple'))}}
{{#if (and (not hideResources) (not (eq item.system.resource.type 'diceValue')))}}
{{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}}
{{/if}}
{{#if (and (not hideResources) (gte item.system.quantity 0))}}

View file

@ -3,7 +3,7 @@
<i class="{{#if item.system.resource.icon}}{{item.system.resource.icon}}{{else}}fa-solid fa-hashtag{{/if}}"></i>
<input type="number" class="inventory-item-resource" value="{{item.system.resource.value}}" min="0" max="{{rollParsed item.system.resource.max item.actor item true}}" />
</div>
{{else}}
{{else if (eq item.system.resource.type 'diceValue')}}
<div class="item-resources">
{{#times (rollParsed item.system.resource.max item.parent item numerical=true)}}
{{#with (ifThen (lookup ../item.system.resource.diceStates this) (lookup ../item.system.resource.diceStates this) this) as | state |}}
@ -18,4 +18,11 @@
{{/times}}
<a data-action="handleResourceDice" data-tooltip="DAGGERHEART.APPLICATIONS.ResourceDice.rerollDice"><i class="fa-solid fa-dice resource-edit"></i></a>
</div>
{{else if (eq item.system.resource.type 'die')}}
<a class="item-resource die" data-action="advanceResourceDie">
<div class="item-dice-resource">
<label>{{#if item.system.resource.value}}{{item.system.resource.value}}{{/if}}</label>
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" item.system.resource.dieFaces ".svg"}}" />
</div>
</a>
{{/if}}

View file

@ -1,33 +0,0 @@
<fieldset>
<legend>
{{localize "DAGGERHEART.GENERAL.Resource.single"}}
{{#unless source.system.resource}}
<a data-action="addResource"><i class="fa-solid fa-plus icon-button"></i></a>
{{else}}
<a data-action="removeResource"><i class="fa-solid fa-trash"></i></a>
{{/unless}}
</legend>
{{#if source.system.resource}}
<div class="{{#if (eq source.system.resource.type 'simple')}}nest-inputs{{else}}two-columns{{/if}} even">
{{formGroup systemFields.resource.fields.type value=source.system.resource.type localize=true blank=false}}
{{formGroup systemFields.resource.fields.recovery value=source.system.resource.recovery localize=true}}
{{#if (eq source.system.resource.type 'simple')}}
{{formGroup systemFields.resource.fields.progression value=source.system.resource.progression localize=true}}
{{/if}}
</div>
<div class="two-columns even">
{{#if (eq source.system.resource.type 'simple')}}
{{formGroup systemFields.resource.fields.value value=source.system.resource.value localize=true}}
{{formGroup systemFields.resource.fields.max value=source.system.resource.max localize=true}}
{{else}}
{{formGroup systemFields.resource.fields.dieFaces value=source.system.resource.dieFaces localize=true blank=false}}
{{formGroup systemFields.resource.fields.max value=source.system.resource.max label="DAGGERHEART.GENERAL.amount" localize=true}}
{{/if}}
</div>
{{#if (eq source.system.resource.type 'simple')}}{{formGroup systemFields.resource.fields.icon value=source.system.resource.icon localize=true placeholder="fa-solid fa-hashtag"}}{{/if}}
{{/if}}
</fieldset>

View file

@ -0,0 +1,11 @@
<span>
<div class="two-columns even">
{{formGroup systemFields.resource.fields.type value=source.system.resource.type localize=true blank=false}}
{{formGroup systemFields.resource.fields.recovery value=source.system.resource.recovery localize=true}}
</div>
<div class="two-columns even">
{{formGroup systemFields.resource.fields.dieFaces value=source.system.resource.dieFaces localize=true blank=false}}
{{formGroup systemFields.resource.fields.max value=source.system.resource.max label="DAGGERHEART.GENERAL.amount" localize=true}}
</div>
</span>

View file

@ -0,0 +1,6 @@
<span>
<div class="two-columns even">
{{formGroup systemFields.resource.fields.type value=source.system.resource.type localize=true blank=false}}
{{formGroup systemFields.resource.fields.dieFaces value=source.system.resource.dieFaces localize=true blank=false}}
</div>
</span>

View file

@ -0,0 +1,20 @@
<fieldset>
<legend>
{{localize "DAGGERHEART.GENERAL.Resource.single"}}
{{#unless source.system.resource}}
<a data-action="addResource"><i class="fa-solid fa-plus icon-button"></i></a>
{{else}}
<a data-action="removeResource"><i class="fa-solid fa-trash"></i></a>
{{/unless}}
</legend>
{{#if source.system.resource}}
{{#if (eq source.system.resource.type 'simple')}}
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section/simple.hbs"}}
{{else if (eq source.system.resource.type 'diceValue')}}
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section/dice-value.hbs"}}
{{else}}
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section/die.hbs"}}
{{/if}}
{{/if}}
</fieldset>

View file

@ -0,0 +1,14 @@
<span>
<div class="nest-inputs even">
{{formGroup systemFields.resource.fields.type value=source.system.resource.type localize=true blank=false}}
{{formGroup systemFields.resource.fields.recovery value=source.system.resource.recovery localize=true}}
{{formGroup systemFields.resource.fields.progression value=source.system.resource.progression localize=true}}
</div>
<div class="two-columns even">
{{formGroup systemFields.resource.fields.value value=source.system.resource.value localize=true}}
{{formGroup systemFields.resource.fields.max value=source.system.resource.max localize=true}}
</div>
{{formGroup systemFields.resource.fields.icon value=source.system.resource.icon localize=true placeholder="fa-solid fa-hashtag"}}
</span>

View file

@ -16,5 +16,5 @@
{{formField systemFields.recallCost value=source.system.recallCost data-dtype="Number"}}
</fieldset>
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section.hbs" }}
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section/resource-section.hbs" }}
</section>

View file

@ -3,5 +3,5 @@
data-tab='{{tabs.settings.id}}'
data-group='{{tabs.settings.group}}'
>
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section.hbs" }}
{{> "systems/daggerheart/templates/sheets/global/partials/resource-section/resource-section.hbs" }}
</section>

View file

@ -23,9 +23,14 @@
</div>
<div class="targets-container">
{{#each targets}}
<div class="token-target-container {{#if this.id}}clickable{{/if}}" data-token="{{this.id}}">
<img src="{{this.texture.src}}" />
<h2 class="title">{{this.name}}</h2>
<div class="token-target-outer-container">
<div class="token-target-container {{#if this.token.id}}clickable{{/if}}" data-token="{{this.token.id}}">
<img src="{{this.token.texture.src}}" />
<h2 class="title">{{this.token.name}}</h2>
</div>
{{#if this.conditionImmunities}}
<span class="token-target-immunity">{{this.conditionImmunities}}</span>
{{/if}}
</div>
{{/each}}
</div>