This commit is contained in:
Dapoolp 2025-08-29 18:01:52 +02:00
commit 53a7868d9e
14 changed files with 62 additions and 41 deletions

View file

@ -17,6 +17,10 @@ We welcome contributions of all kinds:
Please be respectful and collaborative — were all here to build something great together.
### Community Translations
Please note that we are not accepting community translations in the main project. Instead, community translations should be published as a module.
---
## 🧭 General Guidelines

View file

@ -210,7 +210,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
* @protected
*/
async _prepareLoadoutContext(context, _options) {
context.cardView = !game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.displayDomainCardsAsList);
context.cardView = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.displayDomainCardsAsCard);
}
/**
@ -607,6 +607,15 @@ export default class CharacterSheet extends DHBaseActorSheet {
const presets = {
compendium: 'daggerheart',
folder: key,
filter:
key === 'subclasses'
? {
'system.linkedClass.uuid': {
key: 'system.linkedClass.uuid',
value: this.document.system.class.value._stats.compendiumSource
}
}
: undefined,
render: {
noFolder: true
}
@ -709,8 +718,8 @@ export default class CharacterSheet extends DHBaseActorSheet {
* @type {ApplicationClickAction}
*/
static async #toggleLoadoutView(_, button) {
const newAbilityView = button.dataset.value !== 'true';
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.displayDomainCardsAsList, newAbilityView);
const newAbilityView = button.dataset.value === 'true';
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.displayDomainCardsAsCard, newAbilityView);
this.render();
}

View file

@ -1,4 +1,4 @@
export const displayDomainCardsAsList = 'displayDomainCardsAsList';
export const displayDomainCardsAsCard = 'displayDomainCardsAsCard';
export const narrativeCountdown = {
simple: 'countdown-narrative-simple',
position: 'countdown-narrative-position'

View file

@ -52,8 +52,7 @@ export default class DHSubclass extends BaseDataItem {
async _preCreate(data, options, user) {
if (this.actor?.type === 'character') {
const dataUuid =
data.uuid ?? (data.folder ? `Compendium.daggerheart.subclasses.Item.${data._id}` : `Item.${data._id}`);
const dataUuid = data.uuid ?? data._stats.compendiumSource ?? `Item.${data._id}`;
if (this.actor.system.class.subclass) {
if (this.actor.system.multiclass.subclass) {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent'));

View file

@ -44,7 +44,7 @@ function getDamageMessage(damage, type, inline, defaultElement) {
const dualityElement = document.createElement('span');
dualityElement.innerHTML = `
<button class="enriched-damage-button${inline ? ' inline' : ''}"
<button type="button" class="enriched-damage-button${inline ? ' inline' : ''}"
data-value="${damage}"
data-type="${type}"
data-tooltip="${game.i18n.localize('DAGGERHEART.GENERAL.damage')}"
@ -71,6 +71,11 @@ export const renderDamageButton = async event => {
title: game.i18n.localize('Damage Roll'),
data: { bonuses: [] },
source: {},
hasDamage: true,
hasTarget: true,
targets: Array.from(game.user.targets).map(t =>
game.system.api.fields.ActionFields.TargetField.formatTarget(t)
),
roll: [
{
formula: value,

View file

@ -9,12 +9,12 @@ export default function DhDualityRollEnricher(match, _options) {
}
function getDualityMessage(roll, flavor) {
const trait = roll.trait && abilities[roll.trait] ? game.i18n.localize(abilities[roll.trait].label) : null;
const trait = roll?.trait && abilities[roll.trait] ? game.i18n.localize(abilities[roll.trait].label) : null;
const label =
flavor ??
(roll.trait
(roll?.trait
? game.i18n.format('DAGGERHEART.GENERAL.rollWith', { roll: trait })
: roll.reaction
: roll?.reaction
? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
: game.i18n.localize('DAGGERHEART.GENERAL.duality'));
@ -22,9 +22,9 @@ function getDualityMessage(roll, flavor) {
? game.i18n.localize(abilities[roll.trait].label)
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
const advantage = roll.advantage
const advantage = roll?.advantage
? CONFIG.DH.ACTIONS.advantageState.advantage.value
: roll.disadvantage
: roll?.disadvantage
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
: undefined;
const advantageLabel =
@ -36,21 +36,21 @@ function getDualityMessage(roll, flavor) {
const dualityElement = document.createElement('span');
dualityElement.innerHTML = `
<button class="duality-roll-button${roll.inline ? ' inline' : ''}"
<button type="button" class="duality-roll-button${roll?.inline ? ' inline' : ''}"
data-title="${label}"
data-label="${dataLabel}"
data-reaction="${roll.reaction ? 'true' : 'false'}"
data-hope="${roll.hope ?? 'd12'}"
data-fear="${roll.fear ?? 'd12'}"
data-reaction="${roll?.reaction ? 'true' : 'false'}"
data-hope="${roll?.hope ?? 'd12'}"
data-fear="${roll?.fear ?? 'd12'}"
${advantage ? `data-advantage="${advantage}"` : ''}
${roll.difficulty !== undefined ? `data-difficulty="${roll.difficulty}"` : ''}
${roll.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''}
${roll.advantage ? 'data-advantage="true"' : ''}
${roll.disadvantage ? 'data-disadvantage="true"' : ''}
${roll?.difficulty !== undefined ? `data-difficulty="${roll.difficulty}"` : ''}
${roll?.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''}
${roll?.advantage ? 'data-advantage="true"' : ''}
${roll?.disadvantage ? 'data-disadvantage="true"' : ''}
>
${roll.reaction ? '<i class="fa-solid fa-reply"></i>' : '<i class="fa-solid fa-circle-half-stroke"></i>'}
${roll?.reaction ? '<i class="fa-solid fa-reply"></i>' : '<i class="fa-solid fa-circle-half-stroke"></i>'}
${label}
${!flavor && (roll.difficulty || advantageLabel) ? `(${[roll.difficulty, advantageLabel ? game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`) : null].filter(x => x).join(' ')})` : ''}
${!flavor && (roll?.difficulty || advantageLabel) ? `(${[roll.difficulty, advantageLabel ? game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`) : null].filter(x => x).join(' ')})` : ''}
</button>
`;

View file

@ -34,7 +34,7 @@ export default function DhTemplateEnricher(match, _options) {
const templateElement = document.createElement('span');
templateElement.innerHTML = `
<button class="measured-template-button${inline ? ' inline' : ''}" data-type="${type}" data-range="${range}">
<button type="button" class="measured-template-button${inline ? ' inline' : ''}" data-type="${type}" data-range="${range}">
${label} - ${game.i18n.localize(`DAGGERHEART.CONFIG.Range.${range}.name`)}
</button>
`;

View file

@ -427,7 +427,7 @@
"_key": "!actors.items!3aAS2Qm3R6cgaYfE.tQgxiSS48TJ3X1Dl"
},
{
"name": "Avalance Roar",
"name": "Avalanche Roar",
"type": "feature",
"system": {
"description": "<p><strong>Spend a Fear</strong> to roar while within a cave and cause a cave-in. All targets within Close range must succeed on an Agility Reaction Roll (14) or take <strong>2d10</strong> physical damage. The rubble can be cleared with a Progress Countdown (8).</p><p>@Template[type:emanation|range:c]</p>",
@ -532,12 +532,12 @@
"compendiumSource": null,
"duplicateSource": null,
"exportSource": null,
"coreVersion": "13.346",
"coreVersion": "13.347",
"systemId": "daggerheart",
"systemVersion": "0.0.1",
"createdTime": 1754085059319,
"modifiedTime": 1754143365810,
"lastModifiedBy": "MQSznptE5yLT7kj8"
"modifiedTime": 1756256613353,
"lastModifiedBy": "CEZZA7TXd7uT8O2c"
},
"_key": "!actors.items!3aAS2Qm3R6cgaYfE.9Z0i0uURfBMVIapJ"
},

View file

@ -548,7 +548,7 @@
"_key": "!actors.items!UGPiPLJsPvMTSKEF.QV2ytK4b1VWF71OS"
},
{
"name": "Avalance",
"name": "Avalanche",
"type": "feature",
"system": {
"description": "<p><strong>Spend a Fear</strong> to have the Dragon unleash a huge downfall of snow and ice, covering all other creatures within Far range. All targets within this area must succeed on an Instinct Reaction Roll or be buried in snow and rocks, becoming <em>Vulnerable</em> until they dig themselves out from the debris. For each PC that fails the reaction roll, you gain a Fear.</p><p>@Template[type:emanation|range:f]</p>",
@ -678,12 +678,12 @@
"compendiumSource": null,
"duplicateSource": null,
"exportSource": null,
"coreVersion": "13.346",
"coreVersion": "13.347",
"systemId": "daggerheart",
"systemVersion": "0.0.1",
"createdTime": 1754131703390,
"modifiedTime": 1754131790034,
"lastModifiedBy": "MQSznptE5yLT7kj8"
"modifiedTime": 1756256581072,
"lastModifiedBy": "CEZZA7TXd7uT8O2c"
},
"_key": "!actors.items!UGPiPLJsPvMTSKEF.CcRTxCDCJskiu3fI"
},

View file

@ -1,6 +1,6 @@
{
"folder": "1gQpPaxdgvCxYlLs",
"name": "Strange Dirty Penant",
"name": "Strange Dirty Pendant",
"type": "loot",
"_id": "LriTeh9hkwzEaCr1",
"img": "icons/equipment/neck/necklace-carved-stone-spiral.webp",
@ -20,12 +20,12 @@
"compendiumSource": null,
"duplicateSource": null,
"exportSource": null,
"coreVersion": "13.346",
"coreVersion": "13.347",
"systemId": "daggerheart",
"systemVersion": "0.0.1",
"createdTime": 1754222150005,
"modifiedTime": 1754246254311,
"lastModifiedBy": "LgnbNMLaxandgMQq"
"modifiedTime": 1756136989085,
"lastModifiedBy": "HKcDBUU22bYKtQmH"
},
"_key": "!items!LriTeh9hkwzEaCr1"
}

View file

@ -177,7 +177,7 @@
"_key": "!actors.items!acMu9wJrMZZzLSTJ.cIAMenvMXHPTpOFn"
},
{
"name": "Avalance",
"name": "Avalanche",
"type": "feature",
"system": {
"description": "<p>Spend a Fear to carve the mountain with an icy torrent, causing an avalanche. All PCs in its path must succeed on an Agility or Strength Reaction Roll or be bowled over and carried down the mountain. A PC using rope, pitons, or other climbing gear gains advantage on this roll. Targets who fail are knocked down the mountain to Far range, take <strong>2d20</strong> physical damage, and must mark a Stress. Targets who succeed must mark a Stress. </p><section id=\"secret-3gM8fEJj1vD9W88k\" class=\"secret\"><p><em>How do the PCs try to weather the avalanche? What approach do the characters take to fi nd one another when their companions go hurtling down the mountainside?</em></p></section>",
@ -252,12 +252,12 @@
"compendiumSource": null,
"duplicateSource": null,
"exportSource": null,
"coreVersion": "13.346",
"coreVersion": "13.347",
"systemId": "daggerheart",
"systemVersion": "0.0.1",
"createdTime": 1754217019442,
"modifiedTime": 1754217102897,
"lastModifiedBy": "MQSznptE5yLT7kj8"
"modifiedTime": 1756256534443,
"lastModifiedBy": "CEZZA7TXd7uT8O2c"
},
"_key": "!actors.items!acMu9wJrMZZzLSTJ.jkm03DXYYajsRk2j"
},

View file

@ -54,6 +54,10 @@
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
gap: 8px;
max-height: 184px;
overflow: auto;
scrollbar-width: thin;
scrollbar-color: light-dark(#18162e, #f3c267) transparent;
.domain-container {
position: relative;

View file

@ -2,7 +2,7 @@
"id": "daggerheart",
"title": "Daggerheart",
"description": "An unofficial implementation of the Daggerheart system",
"version": "1.1.1",
"version": "1.1.2",
"compatibility": {
"minimum": "13",
"verified": "13.347",

View file

@ -6,7 +6,7 @@
<div class="tooltip-information-section">
<div class="tooltip-information">
<label>{{localize "DAGGERHEART.ITEMS.Weapon.weaponType"}}</label>
<div>{{#if item.system.secondaryWeapon}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon"}}{{/if}}</div>
<div>{{#if item.system.secondary}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon"}}{{/if}}</div>
</div>
<div class="tooltip-information">
<label>{{localize "DAGGERHEART.GENERAL.burden"}}</label>