[Feature] Redesign and merge party members and resources tabs (#1784)

This commit is contained in:
Carlos Fernandez 2026-04-10 15:33:44 -04:00 committed by GitHub
parent 7fa03c58e0
commit 7ca420ae0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 522 additions and 357 deletions

View file

@ -316,6 +316,21 @@
} }
}, },
"newAdversary": "New Adversary" "newAdversary": "New Adversary"
},
"Party": {
"Subtitle": {
"character": "{community} {ancestry} | {subclass} {class}",
"companion": "Companion of {partner}"
},
"RemoveConfirmation": {
"title": "Remove member {name}",
"text": "Are you sure you want to remove {name} from the party?"
},
"Thresholds": {
"minor": "MIN",
"major": "MAJ",
"severe": "SEV"
}
} }
}, },
"APPLICATIONS": { "APPLICATIONS": {

View file

@ -1,5 +1,5 @@
import DHBaseActorSheet from '../api/base-actor.mjs'; import DHBaseActorSheet from '../api/base-actor.mjs';
import { getDocFromElement } from '../../../helpers/utils.mjs'; import { getDocFromElement, sortBy } from '../../../helpers/utils.mjs';
import { ItemBrowser } from '../../ui/itemBrowser.mjs'; import { ItemBrowser } from '../../ui/itemBrowser.mjs';
import FilterMenu from '../../ux/filter-menu.mjs'; import FilterMenu from '../../ux/filter-menu.mjs';
import DaggerheartMenu from '../../sidebar/tabs/daggerheartMenu.mjs'; import DaggerheartMenu from '../../sidebar/tabs/daggerheartMenu.mjs';
@ -18,13 +18,14 @@ export default class Party extends DHBaseActorSheet {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
classes: ['party'], classes: ['party'],
position: { position: {
width: 550, width: 600,
height: 900 height: 900
}, },
window: { window: {
resizable: true resizable: true
}, },
actions: { actions: {
openDocument: Party.#openDocument,
deletePartyMember: Party.#deletePartyMember, deletePartyMember: Party.#deletePartyMember,
deleteItem: Party.#deleteItem, deleteItem: Party.#deleteItem,
toggleHope: Party.#toggleHope, toggleHope: Party.#toggleHope,
@ -45,10 +46,6 @@ export default class Party extends DHBaseActorSheet {
header: { template: 'systems/daggerheart/templates/sheets/actors/party/header.hbs' }, header: { template: 'systems/daggerheart/templates/sheets/actors/party/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
partyMembers: { template: 'systems/daggerheart/templates/sheets/actors/party/party-members.hbs' }, partyMembers: { template: 'systems/daggerheart/templates/sheets/actors/party/party-members.hbs' },
resources: {
template: 'systems/daggerheart/templates/sheets/actors/party/resources.hbs',
scrollable: ['']
},
/* NOT YET IMPLEMENTED */ /* NOT YET IMPLEMENTED */
// projects: { // projects: {
// template: 'systems/daggerheart/templates/sheets/actors/party/projects.hbs', // template: 'systems/daggerheart/templates/sheets/actors/party/projects.hbs',
@ -66,7 +63,6 @@ export default class Party extends DHBaseActorSheet {
primary: { primary: {
tabs: [ tabs: [
{ id: 'partyMembers' }, { id: 'partyMembers' },
{ id: 'resources' },
/* NOT YET IMPLEMENTED */ /* NOT YET IMPLEMENTED */
// { id: 'projects' }, // { id: 'projects' },
{ id: 'inventory' }, { id: 'inventory' },
@ -96,6 +92,8 @@ export default class Party extends DHBaseActorSheet {
case 'header': case 'header':
await this._prepareHeaderContext(context, options); await this._prepareHeaderContext(context, options);
break; break;
case 'partyMembers':
await this._prepareMembersContext(context, options);
case 'notes': case 'notes':
await this._prepareNotesContext(context, options); await this._prepareNotesContext(context, options);
break; break;
@ -121,6 +119,59 @@ export default class Party extends DHBaseActorSheet {
context.tagTeamActive = Boolean(this.document.system.tagTeam.initiator); context.tagTeamActive = Boolean(this.document.system.tagTeam.initiator);
} }
async _prepareMembersContext(context, _options) {
context.partyMembers = [];
const traits = ['agility', 'strength', 'finesse', 'instinct', 'presence', 'knowledge'];
for (const actor of this.document.system.partyMembers) {
const weapons = [];
if (actor.type === 'character') {
if (actor.system.usedUnarmed) {
weapons.push(actor.system.usedUnarmed);
}
const equipped = actor.items.filter(i => i.system.equipped && i.type === 'weapon');
weapons.push(...sortBy(equipped, i => (i.system.secondary ? 1 : 0)));
}
context.partyMembers.push({
uuid: actor.uuid,
img: actor.img,
name: actor.name,
subtitle: (() => {
if (!['character', 'companion'].includes(actor.type)) {
return game.i18n.format(`TYPES.Actor.${actor.type}`);
}
const { value: classItem, subclass } = actor.system.class ?? {};
const partner = actor.system.partner;
const ancestry = actor.system.ancestry;
const community = actor.system.community;
if (partner || (classItem && subclass && ancestry && community)) {
return game.i18n.format(`DAGGERHEART.ACTORS.Party.Subtitle.${actor.type}`, {
class: classItem?.name,
subclass: subclass?.name,
partner: partner?.name,
ancestry: ancestry?.name,
community: community?.name
});
}
})(),
type: actor.type,
resources: actor.system.resources,
armorScore: actor.system.armorScore,
damageThresholds: actor.system.damageThresholds,
evasion: actor.system.evasion,
difficulty: actor.system.difficulty,
traits: actor.system.traits
? traits.map(t => ({
label: game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${t}.short`),
value: actor.system.traits[t].value
}))
: null,
weapons
});
}
}
/** /**
* Prepare render context for the Biography part. * Prepare render context for the Biography part.
* @param {ApplicationRenderContext} context * @param {ApplicationRenderContext} context
@ -149,6 +200,12 @@ export default class Party extends DHBaseActorSheet {
} }
} }
static async #openDocument(_, target) {
const uuid = target.dataset.uuid;
const document = await foundry.utils.fromUuid(uuid);
document?.sheet?.render(true);
}
/** /**
* Toggles a hope resource value. * Toggles a hope resource value.
* @type {ApplicationClickAction} * @type {ApplicationClickAction}
@ -190,7 +247,7 @@ export default class Party extends DHBaseActorSheet {
* @type {ApplicationClickAction} * @type {ApplicationClickAction}
*/ */
static async #toggleArmorSlot(_, target) { static async #toggleArmorSlot(_, target) {
const actor = game.actors.get(target.dataset.actorId); const actor = await foundry.utils.fromUuid(target.dataset.actorId);
const { value, max } = actor.system.armorScore; const { value, max } = actor.system.armorScore;
const inputValue = Number.parseInt(target.dataset.value); const inputValue = Number.parseInt(target.dataset.value);
const newValue = value >= inputValue ? inputValue - 1 : inputValue; const newValue = value >= inputValue ? inputValue - 1 : inputValue;
@ -425,25 +482,23 @@ export default class Party extends DHBaseActorSheet {
} }
static async #deletePartyMember(event, target) { static async #deletePartyMember(event, target) {
const doc = await getDocFromElement(target.closest('.inventory-item')); const doc = await foundry.utils.fromUuid(target.closest('[data-uuid]')?.dataset.uuid);
if (!event.shiftKey) { if (!event.shiftKey) {
const confirmed = await foundry.applications.api.DialogV2.confirm({ const confirmed = await foundry.applications.api.DialogV2.confirm({
window: { window: {
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', { title: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.title', {
type: game.i18n.localize('TYPES.Actor.adversary'),
name: doc.name name: doc.name
}) })
}, },
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: doc.name }) content: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.text', { name: doc.name })
}); });
if (!confirmed) return; if (!confirmed) return;
} }
const currentMembers = this.document.system.partyMembers.map(x => x.uuid); const currentMembers = this.document.system.partyMembers.map(x => x.uuid);
const newMemberdList = currentMembers.filter(uuid => uuid !== doc.uuid); const newMembersList = currentMembers.filter(uuid => uuid !== doc.uuid);
await this.document.update({ 'system.partyMembers': newMemberdList }); await this.document.update({ 'system.partyMembers': newMembersList });
} }
static async #deleteItem(event, target) { static async #deleteItem(event, target) {

View file

@ -1,28 +1,293 @@
@import '../../../utils/colors.less'; @import '../../../utils/colors.less';
@import '../../../utils/fonts.less'; @import '../../../utils/fonts.less';
@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.party { body.game:is(.performance-low, .noblur) {
.tab.partyMembers { .application.sheet.daggerheart.actor.dh-style.party .tab.resources .actors-list .actor-resources {
max-height: 400px; background: light-dark(@dark-blue, @dark-golden);
overflow: auto;
.actors-list { .actor-name {
display: flex; background: light-dark(@dark-blue, @dark-golden);
flex-direction: column;
gap: 10px;
align-items: center;
width: 100%;
}
.actors-dragger {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 100%;
height: 40px;
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
border-radius: 3px;
color: light-dark(@dark-blue-50, @beige-50);
} }
} }
} }
.application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers {
overflow: auto;
.actors-list {
display: flex;
flex-direction: column;
gap: 8px;
align-items: stretch;
width: 100%;
.actor-resources {
display: grid;
grid-template:
"img header" min-content
"img body" 1fr
/ 7.5rem 1fr;
gap: 6px;
column-gap: 12px;
padding: 6px;
background-color: light-dark(@dark-blue-10, @golden-10);
.actor-img-frame {
grid-area: img;
width: 7.5rem;
height: 7.5rem;
position: relative;
.actor-img {
object-fit: cover;
object-position: top center;
border-radius: 6px;
width: 100%;
height: 100%;
}
.equipped-weapons {
position: absolute;
top: -2px;
left: -3px;
display: flex;
flex-direction: column;
gap: 1px;
img {
border-radius: 50%;
width: 24px;
height: 24px;
border: 1px solid light-dark(@dark-blue, @golden);
object-fit: cover;
}
}
.evasion {
position: absolute;
top: 1px;
right: 1px;
width: 1.75rem;
height: 1.75rem;
background: url('../assets/svg/trait-shield.svg') no-repeat;
background-size: 100%;
font-size: var(--font-size-14);
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
}
.threshold-section {
position: absolute;
left: 0;
right: 0;
bottom: -2px;
margin: auto;
display: flex;
gap: 4px;
background-color: light-dark(transparent, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 4px 6px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 3px;
align-items: baseline;
width: fit-content;
h4 {
font-weight: bold;
text-transform: uppercase;
white-space: nowrap;
&.threshold-label {
font-size: var(--font-size-10);
color: light-dark(@dark-blue, @golden);
}
&.threshold-value {
font-size: var(--font-size-11);
color: light-dark(@dark, @beige);
}
}
}
}
header {
grid-area: header;
display: grid;
grid-template:
"name hope" min-content
"subtitle subtitle" min-content
/ 1fr min-content;
.actor-name {
width: 100%;
z-index: 1;
font-size: var(--font-size-20);
color: light-dark(@beige, @golden);
font-weight: bold;
}
.delete-icon {
font-size: 0.75em;
}
.subtitle {
grid-area: subtitle;
font-size: var(--font-size-14);
}
.hope-section {
display: flex;
background-color: light-dark(transparent, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 3px 6px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 3px;
align-items: center;
width: fit-content;
margin-left: auto;
h4 {
font-size: var(--font-size-12);
font-weight: bold;
text-transform: uppercase;
color: light-dark(@dark-blue, @golden);
margin-right: 3px;
}
.hope-value {
display: flex;
cursor: pointer;
font-size: var(--font-size-12);
margin-left: 1px;
}
}
}
.body {
grid-area: body;
display: flex;
align-items: start;
justify-content: space-between;
}
.resources {
display: flex;
flex-direction: column;
gap: 4px;
.slot-section {
display: flex;
flex-direction: row;
align-items: stretch;
.slot-label {
display: flex;
align-items: center;
color: light-dark(@beige, @dark-blue);
background: light-dark(@dark-blue, @golden);
padding: 0 4px;
width: fit-content;
font-weight: bold;
border-radius: 6px 0px 0px 6px;
font-size: var(--font-size-12);
white-space: nowrap;
.label {
padding-right: 2px;
}
.value {
font-variant-numeric: tabular-nums;
.current {
display: inline-block;
text-align: end;
width: 2ch;
}
.max {
display: inline-block;
text-align: start;
width: 2ch;
}
}
}
.slot-bar {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
background-color: light-dark(@dark-blue-10, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 2px 5px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 0 6px 6px 0;
width: fit-content;
min-height: 22px;
.armor-slot {
cursor: pointer;
transition: all 0.3s ease;
font-size: var(--font-size-12);
.fa-shield-halved {
color: light-dark(@dark-blue-40, @golden-40);
}
}
.slot {
width: 16px;
height: 10px;
border: 1px solid light-dark(@dark-blue, @golden);
background: light-dark(@dark-blue-10, @golden-10);
border-radius: 3px;
transition: all 0.3s ease;
cursor: pointer;
&.filled {
background: light-dark(@dark-blue, @golden);
}
}
}
}
}
.traits {
background-color: light-dark(@dark-blue-10, @dark-blue);
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 6px;
display: grid;
grid-template-columns: 1fr 1fr;
font-size: var(--font-size-12);
padding: 3px 4px;
gap: 3px 7px;
.trait {
display: flex;
justify-content: space-between;
gap: 3px;
.label {
color: light-dark(@dark-blue, @golden);
}
.value {
font-weight: 600;
}
}
}
}
}
.actors-dragger {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 100%;
height: 40px;
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
border-radius: 3px;
color: light-dark(@dark-blue-50, @beige-50);
}
}

View file

@ -1,196 +0,0 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
@import '../../../utils/mixin.less';
body.game:is(.performance-low, .noblur) {
.application.sheet.daggerheart.actor.dh-style.party .tab.resources .actors-list .actor-resources {
background: light-dark(@dark-blue, @dark-golden);
.actor-name {
background: light-dark(@dark-blue, @dark-golden);
}
}
}
.application.sheet.daggerheart.actor.dh-style.party {
.tab.resources {
overflow: auto;
.actors-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
align-items: center;
width: 100%;
justify-content: center;
.actor-resources {
display: flex;
flex-direction: column;
position: relative;
background: light-dark(@dark-blue-40, @dark-golden-40);
border-radius: 6px;
border: 1px solid light-dark(@dark-blue, @golden);
width: 230px;
height: -webkit-fill-available;
.actor-name {
position: absolute;
top: 0px;
background: light-dark(@dark-blue-90, @dark-golden-80);
backdrop-filter: blur(6.5px);
border-radius: 6px 6px 0px 0px;
text-align: center;
width: 100%;
z-index: 1;
font-size: var(--font-size-20);
color: light-dark(@beige, @golden);
font-weight: bold;
padding: 5px 0;
}
.actor-img {
height: 150px;
object-fit: cover;
object-position: top center;
border-radius: 6px 6px 0px 0px;
mask-image: linear-gradient(180deg, black 88%, transparent 100%);
}
.resources {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
margin: 10px;
.slot-section {
display: flex;
flex-direction: column;
align-items: center;
.slot-bar {
display: flex;
flex-wrap: wrap;
gap: 5px;
width: 239px;
background-color: light-dark(@dark-blue-10, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 5px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 6px;
width: fit-content;
.armor-slot {
cursor: pointer;
transition: all 0.3s ease;
font-size: var(--font-size-12);
.fa-shield-halved {
color: light-dark(@dark-blue-40, @golden-40);
}
}
.slot {
width: 20px;
height: 10px;
border: 1px solid light-dark(@dark-blue, @golden);
background: light-dark(@dark-blue-10, @golden-10);
border-radius: 3px;
transition: all 0.3s ease;
cursor: pointer;
&.filled {
background: light-dark(@dark-blue, @golden);
}
}
}
.slot-label {
display: flex;
align-items: center;
color: light-dark(@beige, @dark-blue);
background: light-dark(@dark-blue, @golden);
padding: 0 5px;
width: fit-content;
font-weight: bold;
border-radius: 0px 0px 5px 5px;
font-size: var(--font-size-12);
.label {
padding-right: 5px;
}
.value {
padding-left: 6px;
border-left: 1px solid light-dark(@beige, @dark-golden);
}
}
}
.hope-section {
position: relative;
display: flex;
gap: 10px;
background-color: light-dark(transparent, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 5px 10px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 3px;
align-items: center;
width: fit-content;
h4 {
font-size: var(--font-size-12);
font-weight: bold;
text-transform: uppercase;
color: light-dark(@dark-blue, @golden);
}
.hope-value {
display: flex;
cursor: pointer;
font-size: var(--font-size-12);
}
}
.threshold-section {
display: flex;
align-self: center;
gap: 10px;
background-color: light-dark(transparent, @dark-blue);
color: light-dark(@dark-blue, @golden);
padding: 5px 10px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 3px;
align-items: center;
width: fit-content;
h4 {
font-size: var(--font-size-12);
font-weight: bold;
text-transform: uppercase;
color: light-dark(@dark-blue, @golden);
&.threshold-value {
color: light-dark(@dark, @beige);
}
}
}
}
}
}
.actors-dragger {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 100%;
height: 40px;
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
border-radius: 3px;
color: light-dark(@dark-blue-50, @beige-50);
}
}
}

View file

@ -31,7 +31,6 @@
@import './actors/party/party-members.less'; @import './actors/party/party-members.less';
@import './actors/party/sheet.less'; @import './actors/party/sheet.less';
@import './actors/party/inventory.less'; @import './actors/party/inventory.less';
@import './actors/party/resources.less';
@import './items/beastform.less'; @import './items/beastform.less';
@import './items/class.less'; @import './items/class.less';

View file

@ -3,7 +3,6 @@
<div class='item-container'> <div class='item-container'>
<div class="item-info"> <div class="item-info">
<h1 class='item-name'><input type='text' name='name' value='{{source.name}}' /></h1> <h1 class='item-name'><input type='text' name='name' value='{{source.name}}' /></h1>
<h2 class="label">Party</h2>
</div> </div>
</div> </div>
</header> </header>

View file

@ -18,24 +18,156 @@
<i class="fa-solid fa-handshake-angle"></i> <i class="fa-solid fa-handshake-angle"></i>
<span>Help Action</span> <span>Help Action</span>
</button> --}} </button> --}}
<button data-action="triggerRest" data-action="triggerRest" data-type="shortRest">
<i class="fa-solid fa-utensils"></i>
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}</span>
</button>
<button data-action="triggerRest" data-type="longRest">
<i class="fa-solid fa-bed"></i>
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}</span>
</button>
</div> </div>
<fieldset class="actors-section glassy"> <ul class="actors-list">
<legend>{{localize tabs.partyMembers.label}}</legend> {{#each partyMembers as |member id|}}
<ul class="actors-list"> <li class="actor-resources">
{{#each document.system.partyMembers as |actor id|}} <div class="actor-img-frame">
{{> 'daggerheart.inventory-item' <img class="actor-img" src="{{member.img}}">
item=actor {{#if member.weapons}}
type='character' <div class="equipped-weapons">
isActor=true {{#each member.weapons as |weapon|}}
hideContextMenu=true <img src="{{weapon.img}}" data-tooltip="{{weapon.name}}"/>
}} {{/each}}
{{/each}} </div>
</ul> {{/if}}
{{#unless document.system.partyMembers.length}} {{#if member.evasion includeZero=true}}
<div class="actors-dragger"> <div class="evasion" data-tooltip="DAGGERHEART.GENERAL.evasion">{{member.evasion}}</div>
<span>{{localize "DAGGERHEART.GENERAL.dropActorsHere"}}</span> {{/if}}
</div> {{#if member.difficulty includeZero=true}}
{{/unless}} <div class="evasion" data-tooltip="DAGGERHEART.GENERAL.difficulty">{{member.difficulty}}</div>
</fieldset> {{/if}}
</section> {{#unless (eq member.type 'companion')}}
<div class="threshold-section">
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.minor"}}</h4>
<h4 class="threshold-value">{{member.damageThresholds.major}}</h4>
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.major"}}</h4>
<h4 class="threshold-value">{{member.damageThresholds.severe}}</h4>
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.severe"}}</h4>
</div>
{{/unless}}
</div>
<header>
<h2 class="actor-name">
<a data-action="openDocument" data-uuid="{{member.uuid}}">{{member.name}}</a>
<a class="delete-icon" data-action="deletePartyMember" data-uuid="{{member.uuid}}"><i class="fa-regular fa-times" inert></i></a>
</h2>
<div>
{{#unless (or (eq member.type 'companion') (eq member.type 'adversary')) }}
<div class="hope-section">
<h4>{{localize "DAGGERHEART.GENERAL.hope"}}</h4>
{{#times member.resources.hope.max}}
<span class='hope-value' data-action='toggleHope' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
{{#if (gte member.resources.hope.value (add this 1))}}
<i class='fa-solid fa-diamond'></i>
{{else}}
<i class='fa-regular fa-circle'></i>
{{/if}}
</span>
{{/times}}
</div>
{{/unless}}
</div>
{{#if member.subtitle}}
<span class="subtitle">{{member.subtitle}}</span>
{{/if}}
</header>
<section class="body">
<section class="resources">
{{#unless (eq member.type 'companion') }}
<div class="slot-section">
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.HitPoints.plural">
<span class="label">
<i class="fa-solid fa-heart" inert></i>
</span>
<span class="value">
<span class="current">{{member.resources.hitPoints.value}}</span>
/
<span class="max">{{member.resources.hitPoints.max}}</span>
</span>
</div>
<div class="slot-bar">
{{#times member.resources.hitPoints.max}}
<span class='slot {{#if (gte member.resources.hitPoints.value (add this 1))}}filled{{/if}}'
data-action='toggleHitPoints' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
</span>
{{/times}}
</div>
</div>
{{/unless}}
<div class="slot-section">
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.stress">
<span class="label">
<i class="fa-solid fa-bolt" inert></i>
</span>
<span class="value">
<span class="current">{{member.resources.stress.value}}</span>
/
<span class="max">{{member.resources.stress.max}}</span>
</span>
</div>
<div class="slot-bar">
{{#times member.resources.stress.max}}
<span class='slot {{#if (gte member.resources.stress.value (add this 1))}}filled{{/if}}'
data-action='toggleStress' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
</span>
{{/times}}
</div>
</div>
{{#if member.armorScore.max}}
<div class="slot-section">
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.armorSlots">
<span class="label">
<i class="fa-solid fa-shield" inert></i>
</span>
<span class="value">
<span class="current">{{member.armorScore.value}}</span>
/
<span class="max">{{member.armorScore.max}}</span>
</span>
</div>
<div class="slot-bar">
{{#times member.armorScore.max}}
<a class='armor-slot' data-action='toggleArmorSlot' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
{{#if (gte member.armorScore.value (add this 1))}}
<i class="fa-solid fa-shield"></i>
{{else}}
<i class="fa-solid fa-shield-halved"></i>
{{/if}}
</a>
{{/times}}
</div>
</div>
{{/if}}
</section>
{{#if member.traits}}
<div class="traits">
{{#each member.traits as |trait|}}
<span class="trait">
<span class="label">{{trait.label}}</span>
<span class="value">{{trait.value}}</span>
</span>
{{/each}}
</div>
{{/if}}
</section>
</li>
{{/each}}
</ul>
{{#unless document.system.partyMembers.length}}
<div class="actors-dragger">
<span>{{localize "DAGGERHEART.GENERAL.dropActorsHere"}}</span>
</div>
{{/unless}}
</section>

View file

@ -1,104 +0,0 @@
<section
class='tab {{tabs.resources.cssClass}} {{tabs.resources.id}}'
data-tab='{{tabs.resources.id}}'
data-group='{{tabs.resources.group}}'
>
<div data-action="triggerRest" data-type="longRest" class="actions-section">
<button data-type="longRest">
<i class="fa-solid fa-bed"></i>
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}</span>
</button>
<button data-action="triggerRest" data-type="shortRest">
<i class="fa-solid fa-utensils"></i>
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}</span>
</button>
</div>
<fieldset class="resource-section glassy">
<legend>{{localize tabs.resources.label}}</legend>
<ul class="actors-list">
{{#each document.system.partyMembers as |actor id|}}
<li class="actor-resources">
<h2 class="actor-name">{{actor.name}}</h2>
<img class="actor-img" src="{{actor.img}}">
<div class="resources">
{{#unless (eq actor.type 'companion') }}
<div class="slot-section">
<div class="slot-bar">
{{#times actor.system.resources.hitPoints.max}}
<span class='slot {{#if (gte actor.system.resources.hitPoints.value (add this 1))}}filled{{/if}}'
data-action='toggleHitPoints' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
</span>
{{/times}}
</div>
<div class="slot-label">
<span class="label">{{localize "DAGGERHEART.GENERAL.HitPoints.short"}}</span>
<span class="value">{{actor.system.resources.hitPoints.value}} / {{actor.system.resources.hitPoints.max}}</span>
</div>
</div>
{{/unless}}
<div class="slot-section">
<div class="slot-bar">
{{#times actor.system.resources.stress.max}}
<span class='slot {{#if (gte actor.system.resources.stress.value (add this 1))}}filled{{/if}}'
data-action='toggleStress' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
</span>
{{/times}}
</div>
<div class="slot-label">
<span class="label">{{localize "DAGGERHEART.GENERAL.stress"}}</span>
<span class="value">{{actor.system.resources.stress.value}} / {{actor.system.resources.stress.max}}</span>
</div>
</div>
{{#if actor.system.armorScore.max}}
<div class="slot-section">
<div class="slot-bar">
{{#times actor.system.armorScore.max}}
<a class='armor-slot' data-action='toggleArmorSlot' data-actor-id="{{actor.id}}" data-value="{{add this 1}}">
{{#if (gte actor.system.armorScore.value (add this 1))}}
<i class="fa-solid fa-shield"></i>
{{else}}
<i class="fa-solid fa-shield-halved"></i>
{{/if}}
</a>
{{/times}}
</div>
<div class="slot-label">
<span class="label">{{localize "DAGGERHEART.GENERAL.armorSlots"}}</span>
<span class="value">{{actor.system.armorScore.value}} / {{actor.system.armorScore.max}}</span>
</div>
</div>
{{/if}}
{{#unless (or (eq actor.type 'companion') (eq actor.type 'adversary')) }}
<div class="hope-section">
<h4>{{localize "DAGGERHEART.GENERAL.hope"}}</h4>
{{#times actor.system.resources.hope.max}}
<span class='hope-value' data-action='toggleHope' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
{{#if (gte actor.system.resources.hope.value (add this 1))}}
<i class='fa-solid fa-diamond'></i>
{{else}}
<i class='fa-regular fa-circle'></i>
{{/if}}
</span>
{{/times}}
</div>
{{/unless}}
{{#unless (eq actor.type 'companion')}}
<div class="threshold-section">
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.minor"}}</h4>
<h4 class="threshold-value">{{actor.system.damageThresholds.major}}</h4>
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.major"}}</h4>
<h4 class="threshold-value">{{actor.system.damageThresholds.severe}}</h4>
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.severe"}}</h4>
</div>
{{/unless}}
</div>
</li>
{{/each}}
</ul>
</fieldset>
</section>