From 30ab18d6832c1d1a9e57def04283f6e0cc33fe0e Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 28 Jun 2025 10:05:29 +0200 Subject: [PATCH 1/2] Fix Class HitPoints and ComainConfig (#190) * Added HitPoints on class for use on character * Updated DomainConfig to use the official domain icons --- lang/en.json | 1 + module/config/domainConfig.mjs | 19 +++++++++---------- module/data/actor/character.mjs | 7 +++++-- module/data/item/class.mjs | 10 ++++++++-- templates/sheets/items/class/settings.hbs | 7 +++---- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/lang/en.json b/lang/en.json index ce8f0295..205a77e4 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1295,6 +1295,7 @@ "Severe": "Severe" }, "Evasion": "Evasion", + "HitPoints": "Hit Points", "ClassFeatures": "Class Features", "Subclasses": "Subclasses", "Guide": { diff --git a/module/config/domainConfig.mjs b/module/config/domainConfig.mjs index 3ecb0bd1..136b077e 100644 --- a/module/config/domainConfig.mjs +++ b/module/config/domainConfig.mjs @@ -2,56 +2,55 @@ export const domains = { arcana: { id: 'arcana', label: 'DAGGERHEART.Domains.arcana.label', - src: 'icons/magic/symbols/circled-gem-pink.webp', + src: 'systems/daggerheart/assets/icons/domains/arcana.svg', description: 'DAGGERHEART.Domains.Arcana' }, blade: { id: 'blade', label: 'DAGGERHEART.Domains.blade.label', - src: 'icons/weapons/swords/sword-broad-crystal-paired.webp', + src: 'systems/daggerheart/assets/icons/domains/blade.svg', description: 'DAGGERHEART.Domains.Blade' }, bone: { id: 'bone', label: 'DAGGERHEART.Domains.bone.label', - src: 'icons/skills/wounds/bone-broken-marrow-red.webp', + src: 'systems/daggerheart/assets/icons/domains/bone.svg', description: 'DAGGERHEART.Domains.Bone' }, codex: { id: 'codex', label: 'DAGGERHEART.Domains.codex.label', - src: 'icons/sundries/books/book-embossed-jewel-gold-purple.webp', + src: 'systems/daggerheart/assets/icons/domains/codex.svg', description: 'DAGGERHEART.Domains.Codex' }, grace: { id: 'grace', label: 'DAGGERHEART.Domains.grace.label', - src: 'icons/skills/movement/feet-winged-boots-glowing-yellow.webp', + src: 'systems/daggerheart/assets/icons/domains/grace.svg', description: 'DAGGERHEART.Domains.Grace' }, midnight: { id: 'midnight', label: 'DAGGERHEART.Domains.midnight.label', - src: 'icons/environment/settlement/watchtower-castle-night.webp', - background: 'systems/daggerheart/assets/backgrounds/MidnightBackground.webp', + src: 'systems/daggerheart/assets/icons/domains/midnight.svg', description: 'DAGGERHEART.Domains.Midnight' }, sage: { id: 'sage', label: 'DAGGERHEART.Domains.sage.label', - src: 'icons/sundries/misc/pipe-wooden-straight-brown.webp', + src: 'systems/daggerheart/assets/icons/domains/sage.svg', description: 'DAGGERHEART.Domains.Sage' }, splendor: { id: 'splendor', label: 'DAGGERHEART.Domains.splendor.label', - src: 'icons/magic/control/control-influence-crown-gold.webp', + src: 'systems/daggerheart/assets/icons/domains/splendor.svg', description: 'DAGGERHEART.Domains.Splendor' }, valor: { id: 'valor', label: 'DAGGERHEART.Domains.valor.label', - src: 'icons/magic/control/control-influence-rally-purple.webp', + src: 'systems/daggerheart/assets/icons/domains/valor.svg', description: 'DAGGERHEART.Domains.Valor' } }; diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 9e467cab..8d6e2e41 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -30,7 +30,10 @@ export default class DhCharacter extends BaseDataActor { return { resources: new fields.SchemaField({ - hitPoints: resourceField(6), + hitPoints: new fields.SchemaField({ + value: new foundry.data.fields.NumberField({ initial: 0, integer: true }), + bonus: new foundry.data.fields.NumberField({ initial: 0, integer: true }) + }), stress: resourceField(6), hope: resourceField(6) }), @@ -243,7 +246,7 @@ export default class DhCharacter extends BaseDataActor { experience.total = experience.value + experience.bonus; } - this.resources.hitPoints.maxTotal = this.resources.hitPoints.max + this.resources.hitPoints.bonus; + this.resources.hitPoints.maxTotal = (this.class.value?.system?.hitPoints ?? 0) + this.resources.hitPoints.bonus; this.resources.stress.maxTotal = this.resources.stress.max + this.resources.stress.bonus; this.evasion.total = (this.class?.evasion ?? 0) + this.evasion.bonus; this.proficiency.total = this.proficiency.value + this.proficiency.bonus; diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index cd69648d..46ec6ff8 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -20,8 +20,14 @@ export default class DHClass extends BaseDataItem { ...super.defineSchema(), domains: new fields.ArrayField(new fields.StringField(), { max: 2 }), classItems: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), - - evasion: new fields.NumberField({ initial: 0, integer: true }), + hitPoints: new fields.NumberField({ + required: true, + integer: true, + min: 1, + initial: 5, + label: 'DAGGERHEART.Sheets.Class.HitPoints' + }), + evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.Sheets.Class.Evasion' }), hopeFeatures: new foundry.data.fields.ArrayField(new ActionField()), classFeatures: new foundry.data.fields.ArrayField(new ActionField()), subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), diff --git a/templates/sheets/items/class/settings.hbs b/templates/sheets/items/class/settings.hbs index 1a211f2b..47e3ddb9 100644 --- a/templates/sheets/items/class/settings.hbs +++ b/templates/sheets/items/class/settings.hbs @@ -3,11 +3,10 @@ data-tab='{{tabs.settings.id}}' data-group='{{tabs.settings.group}}' > - -
+
{{localize tabs.settings.label}} - {{localize "DAGGERHEART.Sheets.Class.Evasion"}} - {{formField systemFields.evasion value=source.system.evasion}} + {{formGroup systemFields.hitPoints value=source.system.hitPoints localize=true}} + {{formGroup systemFields.evasion value=source.system.evasion localize=true}}
From b4fff7b9e6b88eda14e56b0a3fe6df2beee76585 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 28 Jun 2025 10:05:53 +0200 Subject: [PATCH 2/2] 174 character context menu (#189) * Set up the contextMenues properly * Fixed double item generation on drop --- lang/en.json | 11 + module/applications/sheets/character.mjs | 195 +++++++++++++----- module/documents/item.mjs | 28 +++ styles/chat.less | 1 + styles/daggerheart.css | 1 + templates/chat/ability-use.hbs | 1 - templates/sheets/actors/character/loadout.hbs | 2 +- templates/sheets/actors/character/sidebar.hbs | 2 +- .../global/partials/domain-card-item.hbs | 6 +- .../partials/inventory-fieldset-items.hbs | 2 +- .../sheets/global/partials/inventory-item.hbs | 10 +- 11 files changed, 197 insertions(+), 62 deletions(-) diff --git a/lang/en.json b/lang/en.json index 205a77e4..9a614b68 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1099,6 +1099,17 @@ "biography": "Biography", "effects": "Effects" }, + "ContextMenu": { + "UseItem": "Use", + "Equip": "Equip", + "Unequip": "Unequip", + "Edit": "Edit", + "Delete": "Delete", + "ToLoadout": "Send to Loadout", + "ToVault": "Send to Vault", + "Consume": "Consume Item", + "SendToChat": "Send To Chat" + }, "Armor": { "Title": "Active Armor" }, diff --git a/module/applications/sheets/character.mjs b/module/applications/sheets/character.mjs index 82679ccd..665c203e 100644 --- a/module/applications/sheets/character.mjs +++ b/module/applications/sheets/character.mjs @@ -43,10 +43,11 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { makeDeathMove: this.makeDeathMove, itemQuantityDecrease: (_, button) => this.setItemQuantity(button, -1), itemQuantityIncrease: (_, button) => this.setItemQuantity(button, 1), - useAbility: this.useAbility, + toChat: this.toChat, useAdvancementCard: this.useAdvancementCard, useAdvancementAbility: this.useAdvancementAbility, toggleEquipItem: this.toggleEquipItem, + toggleVault: this.toggleVault, levelManagement: this.levelManagement, editImage: this._onEditImage }, @@ -58,11 +59,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { submitOnChange: true, closeOnSubmit: false }, - dragDrop: [ - { dragSelector: null, dropSelector: '.weapon-section' }, - { dragSelector: null, dropSelector: '.armor-section' }, - { dragSelector: '.item-list .item', dropSelector: null } - ] + dragDrop: [] }; static PARTS = { @@ -214,6 +211,109 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { return { primary: primaryTabs, secondary: secondaryTabs }; } + async _onFirstRender(context, options) { + await super._onFirstRender(context, options); + + this._createContextMenues(); + } + + _createContextMenues() { + const allOptions = { + useItem: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.UseItem', + icon: '', + callback: this.constructor.useItem.bind(this) + }, + equip: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.Equip', + icon: '', + condition: el => { + const item = foundry.utils.fromUuidSync(el.dataset.uuid); + return !item.system.equipped; + }, + callback: this.constructor.toggleEquipItem.bind(this) + }, + unequip: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.Unequip', + icon: '', + condition: el => { + const item = foundry.utils.fromUuidSync(el.dataset.uuid); + return item.system.equipped; + }, + callback: this.constructor.toggleEquipItem.bind(this) + }, + edit: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.Edit', + icon: '', + callback: this.constructor.viewObject.bind(this) + }, + delete: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.Delete', + icon: '', + callback: this.constructor.deleteItem.bind(this) + }, + sendToLoadout: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.ToLoadout', + icon: '', + condition: el => { + const item = foundry.utils.fromUuidSync(el.dataset.uuid); + return item.system.inVault; + }, + callback: this.constructor.toggleVault.bind(this) + }, + sendToVault: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.ToVault', + icon: '', + condition: el => { + const item = foundry.utils.fromUuidSync(el.dataset.uuid); + return !item.system.inVault; + }, + callback: this.constructor.toggleVault.bind(this) + }, + sendToChat: { + name: 'DAGGERHEART.Sheets.PC.ContextMenu.SendToChat', + icon: '', + callback: this.constructor.toChat.bind(this) + } + }; + + const getMenuOptions = type => () => { + let menuItems = ['class', 'subclass'].includes(type) ? [] : [allOptions.useItem]; + switch (type) { + case 'weapon': + case 'armor': + menuItems.push(...[allOptions.equip, allOptions.unequip]); + break; + case 'domainCard': + menuItems.push(...[allOptions.sendToLoadout, allOptions.sendToVault]); + break; + } + menuItems.push(...[allOptions.sendToChat, allOptions.edit, allOptions.delete]); + + return menuItems; + }; + + const menuConfigs = [ + 'armor', + 'weapon', + 'miscellaneous', + 'consumable', + 'domainCard', + 'miscellaneous', + 'ancestry', + 'community', + 'class', + 'subclass' + ]; + menuConfigs.forEach(type => { + this._createContextMenu(getMenuOptions(type), `.${type}-context-menu`, { + eventName: 'click', + parentClassHooks: false, + fixed: true + }); + }); + } + _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); @@ -544,20 +644,14 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { (await game.packs.get('daggerheart.communities'))?.render(true); } - static useItem(event) { - const uuid = event.target.closest('[data-item-id]').dataset.itemId, - item = this.document.items.find(i => i.uuid === uuid); - item.use(event); + static useItem(element, button) { + const id = (button ?? element).closest('a').id, + item = this.document.items.get(id); + item.use({}); } - static async viewObject(_, button) { - const object = await fromUuid(button.dataset.value); - if (!object) return; - - const tab = button.dataset.tab; - if (tab && object.sheet._tabs) object.sheet._tabs[0].active = tab; - - if (object.sheet.editMode) object.sheet.editMode = false; + static async viewObject(element, button) { + const object = await fromUuid((button ?? element).dataset.uuid); object.sheet.render(true); } @@ -620,8 +714,8 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { this.render(); } - static async deleteItem(_, button) { - const item = await fromUuid($(button).closest('[data-item-id]')[0].dataset.itemId); + static async deleteItem(element, button) { + const item = await fromUuid((button ?? element).closest('a').dataset.uuid); await item.delete(); } @@ -655,35 +749,29 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { cls.create(msg.toObject()); } - static async useAbility(_, button) { - const item = await fromUuid(button.dataset.feature); - const type = button.dataset.type; + static async toChat(element, button) { + if (button?.dataset?.type === 'experience') { + const experience = this.document.system.experiences[button.dataset.uuid]; + const cls = getDocumentClass('ChatMessage'); + const systemData = { + name: game.i18n.localize('DAGGERHEART.General.Experience.Single'), + description: `${experience.description} ${experience.total < 0 ? experience.total : `+${experience.total}`}` + }; + const msg = new cls({ + type: 'abilityUse', + user: game.user.id, + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + systemData + ) + }); - const cls = getDocumentClass('ChatMessage'); - const systemData = { - title: - type === 'ancestry' - ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.AncestryTitle') - : type === 'community' - ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle') - : game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), - origin: this.document.id, - img: item.img, - name: item.name, - description: item.system.description, - actions: [] - }; - const msg = new cls({ - type: 'abilityUse', - user: game.user.id, - system: systemData, - content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/chat/ability-use.hbs', - systemData - ) - }); - - cls.create(msg.toObject()); + cls.create(msg.toObject()); + } else { + const item = await fromUuid((button ?? element).dataset.uuid); + item.toChat(this.document.id); + } } static async useAdvancementCard(_, button) { @@ -738,8 +826,9 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { cls.create(msg.toObject()); } - static async toggleEquipItem(_, button) { - const item = this.document.items.get(button.id); + static async toggleEquipItem(element, button) { + const id = (button ?? element).closest('a').id; + const item = this.document.items.get(id); if (item.system.equipped) { await item.update({ 'system.equipped': false }); return; @@ -763,6 +852,12 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { this.render(); } + static async toggleVault(element, button) { + const id = (button ?? element).closest('a').id; + const item = this.document.items.get(id); + await item.update({ 'system.inVault': !item.system.inVault }); + } + async _onDragStart(_, event) { super._onDragStart(event); } diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 54759542..ca86ce98 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -141,4 +141,32 @@ export default class DhpItem extends Item { // Display Item Card in chat return response; } + + async toChat(origin) { + const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: + this.type === 'ancestry' + ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.AncestryTitle') + : this.type === 'community' + ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle') + : game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), + origin: origin, + img: this.img, + name: this.name, + description: this.system.description, + actions: [] + }; + const msg = new cls({ + type: 'abilityUse', + user: game.user.id, + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + systemData + ) + }); + + cls.create(msg.toObject()); + } } diff --git a/styles/chat.less b/styles/chat.less index c1de3106..e075274f 100644 --- a/styles/chat.less +++ b/styles/chat.less @@ -283,6 +283,7 @@ h2 { width: 100%; text-align: center; + margin: 0; } } diff --git a/styles/daggerheart.css b/styles/daggerheart.css index c1824583..994293bf 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -1598,6 +1598,7 @@ .daggerheart.chat.domain-card .domain-card-title h2 { width: 100%; text-align: center; + margin: 0; } .daggerheart.chat.domain-card .ability-card-footer { display: flex; diff --git a/templates/chat/ability-use.hbs b/templates/chat/ability-use.hbs index 51d56ace..4ebaa293 100644 --- a/templates/chat/ability-use.hbs +++ b/templates/chat/ability-use.hbs @@ -1,6 +1,5 @@
-
{{title}}

{{name}}

diff --git a/templates/sheets/actors/character/loadout.hbs b/templates/sheets/actors/character/loadout.hbs index a03f393c..375581f3 100644 --- a/templates/sheets/actors/character/loadout.hbs +++ b/templates/sheets/actors/character/loadout.hbs @@ -23,6 +23,6 @@
{{> 'systems/daggerheart/templates/sheets/global/partials/inventory-fieldset-items.hbs' title=(localize 'DAGGERHEART.Sheets.PC.Tabs.Loadout') type='domainCard' isGlassy=true cardView='list'}} - {{> 'systems/daggerheart/templates/sheets/global/partials/inventory-fieldset-items.hbs' title=(localize 'DAGGERHEART.Sheets.PC.Tabs.Vault') type='domainCard' isGlassy=true cardView='list'}} + {{> 'systems/daggerheart/templates/sheets/global/partials/inventory-fieldset-items.hbs' title=(localize 'DAGGERHEART.Sheets.PC.Tabs.Vault') type='domainCard' isVault=true isGlassy=true cardView='list'}}
\ No newline at end of file diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index 8e4891dc..bba7b3e3 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -111,7 +111,7 @@
- +
{{/each}} diff --git a/templates/sheets/global/partials/domain-card-item.hbs b/templates/sheets/global/partials/domain-card-item.hbs index 9198c8af..55662833 100644 --- a/templates/sheets/global/partials/domain-card-item.hbs +++ b/templates/sheets/global/partials/domain-card-item.hbs @@ -1,5 +1,5 @@
  • - +
    {{#if (eq type 'weapon')}} @@ -24,8 +24,8 @@ {{/unless}} {{/if}} - - + +
    {{item.name}}
    diff --git a/templates/sheets/global/partials/inventory-fieldset-items.hbs b/templates/sheets/global/partials/inventory-fieldset-items.hbs index d37119d5..f327c268 100644 --- a/templates/sheets/global/partials/inventory-fieldset-items.hbs +++ b/templates/sheets/global/partials/inventory-fieldset-items.hbs @@ -3,7 +3,7 @@