[Feature] 1740 - Beastform Info (#1750)

* Improved the EffectDisplay tooltip of the beastform effect to show the info about the active beastform

* .

* Move template to more sorted location

---------

Co-authored-by: Carlos Fernandez <cfern1990@gmail.com>
This commit is contained in:
WBHarry 2026-03-28 00:18:35 +01:00 committed by GitHub
parent e3c4f1ce9f
commit c730cc3d4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 226 additions and 164 deletions

View file

@ -25,7 +25,7 @@ export default class BeastformEffect extends BaseEffect {
width: new fields.NumberField({ integer: false, nullable: true })
})
}),
advantageOn: new fields.ArrayField(new fields.StringField()),
advantageOn: new fields.TypedObjectField(new fields.SchemaField({ value: new fields.StringField() })),
featureIds: new fields.ArrayField(new fields.StringField()),
effectIds: new fields.ArrayField(new fields.StringField())
};

View file

@ -99,10 +99,14 @@ export default class DHBeastform extends BaseDataItem {
get beastformAttackData() {
const effect = this.parent.effects.find(x => x.type === 'beastform');
return DHBeastform.getBeastformAttackData(effect);
}
static getBeastformAttackData(effect) {
if (!effect) return null;
const traitBonus =
effect.system.changes.find(x => x.key === `system.traits.${this.mainTrait}.value`)?.value ?? 0;
const mainTrait = effect.system.changes.find(x => x.key === 'system.rules.attack.roll.trait')?.value;
const traitBonus = effect.system.changes.find(x => x.key === `system.traits.${mainTrait}.value`)?.value ?? 0;
const evasionBonus = effect.system.changes.find(x => x.key === 'system.evasion')?.value ?? 0;
const damageDiceIndex = effect.system.changes.find(x => x.key === 'system.rules.attack.damage.diceIndex');
@ -110,7 +114,7 @@ export default class DHBeastform extends BaseDataItem {
const damageBonus = effect.system.changes.find(x => x.key === 'system.rules.attack.damage.bonus')?.value ?? 0;
return {
trait: game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.mainTrait].label),
trait: game.i18n.localize(CONFIG.DH.ACTOR.abilities[mainTrait]?.label),
traitBonus: traitBonus ? Number(traitBonus).signedString() : '',
evasionBonus: evasionBonus ? Number(evasionBonus).signedString() : '',
damageDice: damageDice,

View file

@ -31,12 +31,39 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
this.#bordered = true;
let effect = {};
if (element.dataset.uuid) {
const effectData = (await foundry.utils.fromUuid(element.dataset.uuid)).toObject();
const effectItem = await foundry.utils.fromUuid(element.dataset.uuid);
const effectData = effectItem.toObject();
effect = {
...effectData,
name: game.i18n.localize(effectData.name),
description: game.i18n.localize(effectData.description ?? effectData.parent.system.description)
name: game.i18n.localize(effectData.name)
};
if (effectData.type === 'beastform') {
const beastformData = {
features: [],
advantageOn: effectData.system.advantageOn,
beastformAttackData: game.system.api.data.items.DHBeastform.getBeastformAttackData(effectItem)
};
const features = effectItem.parent.items.filter(x => effectItem.system.featureIds.includes(x.id));
for (const feature of features) {
const featureData = feature.toObject();
featureData.enrichedDescription = await feature.system.getEnrichedDescription();
beastformData.features.push(featureData);
}
effect.description = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/ui/tooltip/parts/beastformData.hbs',
{
item: { system: beastformData }
}
);
} else {
effect.description = game.i18n.localize(
effectData.description ?? effectData.parent.system.description
);
}
} else {
const conditions = CONFIG.DH.GENERAL.conditions();
const condition = conditions[element.dataset.condition];

View file

@ -36,6 +36,7 @@ export const preloadHandlebarsTemplates = async function () {
'systems/daggerheart/templates/actionTypes/summon.hbs',
'systems/daggerheart/templates/actionTypes/transform.hbs',
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
'systems/daggerheart/templates/ui/tooltip/parts/beastformData.hbs',
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
'systems/daggerheart/templates/dialogs/downtime/activities.hbs',

View file

@ -339,7 +339,8 @@
background: light-dark(@light-black, @dark-blue);
border: 1px solid light-dark(@dark-blue, @golden);
h4, i {
h4,
i {
color: light-dark(@dark-blue, @golden);
}
}
@ -399,7 +400,9 @@
background: light-dark(@light-black, @dark-blue);
border: 1px solid light-dark(@dark-blue, @golden);
.label, .value, i {
.label,
.value,
i {
color: light-dark(@dark-blue, @golden);
}
}

View file

@ -1,3 +1,4 @@
@import './tooltip/sheet.less';
@import './tooltip/tooltip.less';
@import './tooltip/armorManagement.less';
@import './tooltip/battlepoints.less';

View file

@ -18,7 +18,7 @@
display: flex;
flex-direction: column;
align-items: center;
text-align: start;
text-align: center;
padding: 5px;
gap: 0px;

View file

@ -0,0 +1,129 @@
#tooltip:has(div.daggerheart.dh-style.tooltip.card-style),
aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip),
#tooltip.bordered-tooltip {
.tooltip-title {
font-size: var(--font-size-20);
color: light-dark(@dark-blue, @golden);
font-weight: 700;
}
.tooltip-description {
font-style: inherit;
text-align: inherit;
width: 100%;
padding: 5px 10px;
position: relative;
margin-top: 5px;
&::before {
content: '';
background: @golden;
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
height: 2px;
width: calc(100% - 10px);
}
&::before {
position: absolute;
top: -5px;
}
}
.tooltip-separator {
background: @golden;
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
height: 2px;
width: calc(100% - 10px);
margin-bottom: 2px;
}
.tooltip-tags {
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
padding: 5px 10px;
position: relative;
max-height: 150px;
overflow-y: auto;
position: relative;
scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent;
.tooltip-tag {
display: flex;
gap: 10px;
flex-direction: column;
.tooltip-tag-label-container {
display: flex;
align-items: center;
gap: 5px;
img {
width: 40px;
height: 40px;
border-radius: 3px;
}
}
}
}
.tags {
display: flex;
gap: 5px 10px;
padding-bottom: 16px;
flex-wrap: wrap;
justify-content: center;
&.advantages {
width: 100%;
padding: 5px 10px;
padding-bottom: 16px;
position: relative;
margin-top: 5px;
&::before {
content: '';
background: @golden;
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
height: 2px;
width: calc(100% - 10px);
}
&::before {
position: absolute;
top: -5px;
}
.tag {
background: @green-10;
color: @green;
border-color: @green;
}
}
.tag {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 3px 5px;
font-size: var(--font-size-12);
font: @font-body;
background: light-dark(@dark-15, @beige-15);
border: 1px solid light-dark(@dark, @beige);
border-radius: 3px;
}
.label {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: var(--font-size-12);
}
}
}

View file

@ -13,13 +13,6 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) {
outline: 1px solid light-dark(@dark-80, @beige-80);
box-shadow: 0 0 25px rgba(0, 0, 0, 0.8);
.tooltip-title {
font-size: var(--font-size-20);
color: light-dark(@dark-blue, @golden);
font-weight: 700;
margin-bottom: 5px;
}
.tooltip-subtitle {
margin: 0;
}
@ -80,110 +73,6 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) {
}
}
.tooltip-tags {
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
padding: 5px 10px;
position: relative;
padding-top: 10px;
max-height: 150px;
overflow-y: auto;
position: relative;
scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent;
&::before {
content: '';
background: @golden;
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
height: 2px;
width: calc(100% - 10px);
}
&::before {
position: absolute;
top: 0px;
}
.tooltip-tag {
display: flex;
gap: 10px;
flex-direction: column;
.tooltip-tag-label-container {
display: flex;
align-items: center;
gap: 5px;
img {
width: 40px;
height: 40px;
border-radius: 3px;
}
}
}
}
.tags {
display: flex;
gap: 5px 10px;
padding-bottom: 16px;
flex-wrap: wrap;
justify-content: center;
&.advantages {
width: 100%;
padding: 5px 10px;
padding-bottom: 16px;
position: relative;
margin-top: 5px;
&::before {
content: '';
background: @golden;
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
height: 2px;
width: calc(100% - 10px);
}
&::before {
position: absolute;
top: -5px;
}
.tag {
background: @green-10;
color: @green;
border-color: @green;
}
}
.tag {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 3px 5px;
font-size: var(--font-size-12);
font: @font-body;
background: light-dark(@dark-15, @beige-15);
border: 1px solid light-dark(@dark, @beige);
border-radius: 3px;
}
.label {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: var(--font-size-12);
}
}
.item-icons-list {
position: absolute;
display: flex;

View file

@ -3,37 +3,7 @@
<h2 class="tooltip-title">{{item.name}}</h2>
<p class="tooltip-subtitle"><i>{{item.system.examples}}</i></p>
{{#if description}}
<div class="tooltip-description">{{{description}}}</div>
{{/if}}
<div class="tags">
{{#with item.system.beastformAttackData}}
<div class="tag">
<span>{{localize "DAGGERHEART.ITEMS.Beastform.mainTrait"}} {{this.trait}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.ITEMS.Beastform.traitBonus"}} {{this.traitBonus}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.GENERAL.evasion"}} {{this.evasionBonus}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.GENERAL.damage"}} {{concat this.damageDice ' ' this.damageBonus}} <i class="fa-solid fa-hand-fist"></i></span>
</div>
{{/with}}
</div>
<h2 class="tooltip-title">{{localize "DAGGERHEART.ITEMS.Beastform.FIELDS.advantageOn.label"}}</h2>
<div class="tags advantages">
{{#each item.system.advantageOn as | chip |}}
<div class="tag">
<span>{{ifThen chip.value chip.value chip}}</span>
</div>
{{/each}}
</div>
{{> "systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs" features=item.system.features label=(localize "DAGGERHEART.GENERAL.features")}}
{{> "systems/daggerheart/templates/ui/tooltip/parts/beastformData.hbs" }}
<p class="tooltip-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.Tooltip.middleClick"}}

View file

@ -41,26 +41,32 @@
</div>
{{/if}}
{{#unless effect.isLockedCondition}}
<div class="close-hints">
{{#if effect.system.stacking}}
{{#if (eq effect.type 'beastform')}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.increaseStacks"}}
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.Tooltip.middleClick"}}
</p>
{{#if (gt effect.system.stacking.value 1)}}
{{/if}}
{{#unless effect.isLockedCondition}}
{{#if effect.system.stacking}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.decreaseStacks"}}
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.increaseStacks"}}
</p>
{{#if (gt effect.system.stacking.value 1)}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.decreaseStacks"}}
</p>
{{else}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.removeThing" thing=(localize "DAGGERHEART.GENERAL.Effect.single")}}
</p>
{{/if}}
{{else}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.removeThing" thing=(localize "DAGGERHEART.GENERAL.Effect.single")}}
</p>
{{/if}}
{{else}}
<p class="close-hint">
<i class="fa-solid fa-computer-mouse"></i> {{localize "DAGGERHEART.UI.EffectsDisplay.removeThing" thing=(localize "DAGGERHEART.GENERAL.Effect.single")}}
</p>
{{/if}}
{{/unless}}
</div>
{{/unless}}
</div>

View file

@ -0,0 +1,31 @@
{{#if description}}
<div class="tooltip-description">{{{description}}}</div>
{{/if}}
<div class="tags">
{{#with item.system.beastformAttackData}}
<div class="tag">
<span>{{localize "DAGGERHEART.ITEMS.Beastform.mainTrait"}} {{this.trait}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.ITEMS.Beastform.traitBonus"}} {{this.traitBonus}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.GENERAL.evasion"}} {{this.evasionBonus}}</span>
</div>
<div class="tag">
<span>{{localize "DAGGERHEART.GENERAL.damage"}} {{concat this.damageDice ' ' this.damageBonus}} <i class="fa-solid fa-hand-fist"></i></span>
</div>
{{/with}}
</div>
<h2 class="tooltip-title">{{localize "DAGGERHEART.ITEMS.Beastform.FIELDS.advantageOn.label"}}</h2>
<div class="tags advantages">
{{#each item.system.advantageOn as | chip |}}
<div class="tag">
<span>{{ifThen chip.value chip.value chip}}</span>
</div>
{{/each}}
</div>
{{> "systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs" features=item.system.features label=(localize "DAGGERHEART.GENERAL.features")}}

View file

@ -1,4 +1,5 @@
{{#if (gt features.length 0)}}<h2 class="tooltip-title">{{label}}</h2>{{/if}}
<div class="tooltip-separator"></div>
<div class="tooltip-tags">
{{#each features as | feature |}}
{{#with (ifThen ../isAction feature (ifThen feature.item feature.item feature))}}