Compare commits

..

4 commits

Author SHA1 Message Date
WBHarry
3f4d1cd292
Removed faulty hitPoint cost from rousing speech (#1595) 2026-01-28 11:09:01 +01:00
Nikhil Nagarajan
a18393a9d0
[PR] Loadout Max detection when pulled from compendium (#1589)
* Initial test implementation for solution

* Expanded the existing _preCreate logic

---------

Co-authored-by: WBHarry <williambjrklund@gmail.com>
2026-01-28 08:51:00 +01:00
WBHarry
076b7f01fa
[Fix] 1587 - Lightmode Touchups (#1590)
* Fixed hud statuses and tooltips

* Fixed chat

* Fixed radiobuttons being missplaced
2026-01-28 08:49:22 +01:00
WBHarry
bb43cb57dc
[Fix] 1582 - Automation Additions (#1592)
* Added an automation setting for chat command resources

* Added automation settings for wether to have deathmove automation

* .

* Flattened automation structure
2026-01-28 08:47:02 +01:00
15 changed files with 115 additions and 87 deletions

View file

@ -309,7 +309,7 @@ Hooks.on('chatMessage', (_, message) => {
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value ? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
: undefined; : undefined;
const difficulty = rollCommand.difficulty; const difficulty = rollCommand.difficulty;
const grantResources = Boolean(rollCommand.grantResources); const grantResources = rollCommand.grantResources;
const target = getCommandTarget({ allowNull: true }); const target = getCommandTarget({ allowNull: true });
const title = const title =

View file

@ -2111,7 +2111,6 @@
"tier4": "tier 4", "tier4": "tier 4",
"domains": "Domains", "domains": "Domains",
"downtime": "Downtime", "downtime": "Downtime",
"itemFeatures": "Item Features",
"roll": "Roll", "roll": "Roll",
"rules": "Rules", "rules": "Rules",
"partyMembers": "Party Members", "partyMembers": "Party Members",
@ -2120,7 +2119,8 @@
"questions": "Questions", "questions": "Questions",
"configuration": "Configuration", "configuration": "Configuration",
"base": "Base", "base": "Base",
"triggers": "Triggers" "triggers": "Triggers",
"deathMoves": "Deathmoves"
}, },
"Tiers": { "Tiers": {
"singular": "Tier", "singular": "Tier",
@ -2144,6 +2144,7 @@
"armorSlots": "Armor Slots", "armorSlots": "Armor Slots",
"artistAttribution": "Artwork By: {artist}", "artistAttribution": "Artwork By: {artist}",
"attack": "Attack", "attack": "Attack",
"automation": "Automation",
"basics": "Basics", "basics": "Basics",
"bonus": "Bonus", "bonus": "Bonus",
"burden": "Burden", "burden": "Burden",

View file

@ -43,7 +43,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
return context; return context;
} }
async handleAvoidDeath() { async handleAvoidDeath(useAutomation) {
const target = this.actor.uuid; const target = this.actor.uuid;
const config = await enrichedFateRoll({ const config = await enrichedFateRoll({
target, target,
@ -53,6 +53,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
}); });
if (!config.roll.fate) return; if (!config.roll.fate) return;
if (!useAutomation) return '';
let returnMessage = game.i18n.localize('DAGGERHEART.UI.Chat.deathMove.avoidScar'); let returnMessage = game.i18n.localize('DAGGERHEART.UI.Chat.deathMove.avoidScar');
if (config.roll.fate.value <= this.actor.system.levelData.level.current) { if (config.roll.fate.value <= this.actor.system.levelData.level.current) {
@ -75,7 +76,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
return returnMessage; return returnMessage;
} }
async handleRiskItAll() { async handleRiskItAll(useAutomation) {
const config = await enrichedDualityRoll({ const config = await enrichedDualityRoll({
reaction: true, reaction: true,
traitValue: null, traitValue: null,
@ -90,6 +91,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
}); });
if (!config.roll.result) return; if (!config.roll.result) return;
if (!useAutomation) return '';
const clearAllStressAndHitpointsUpdates = [ const clearAllStressAndHitpointsUpdates = [
{ key: 'hitPoints', clear: true }, { key: 'hitPoints', clear: true },
@ -128,7 +130,9 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
return chatMessage; return chatMessage;
} }
async handleBlazeOfGlory() { async handleBlazeOfGlory(useAutomation) {
if (!useAutomation) return '';
this.actor.createEmbeddedDocuments('ActiveEffect', [ this.actor.createEmbeddedDocuments('ActiveEffect', [
{ {
name: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'), name: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'),
@ -160,19 +164,23 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
let result = ''; let result = '';
const deathMoveAutomation = game.settings.get(
CONFIG.DH.id,
CONFIG.DH.SETTINGS.gameSettings.Automation
).deathMoveAutomation;
if (CONFIG.DH.GENERAL.deathMoves.blazeOfGlory === this.selectedMove) { if (CONFIG.DH.GENERAL.deathMoves.blazeOfGlory === this.selectedMove) {
result = await this.handleBlazeOfGlory(); result = await this.handleBlazeOfGlory(deathMoveAutomation.blazeOfGlory);
} }
if (CONFIG.DH.GENERAL.deathMoves.avoidDeath === this.selectedMove) { if (CONFIG.DH.GENERAL.deathMoves.avoidDeath === this.selectedMove) {
result = await this.handleAvoidDeath(); result = await this.handleAvoidDeath(deathMoveAutomation.avoidDeath);
} }
if (CONFIG.DH.GENERAL.deathMoves.riskItAll === this.selectedMove) { if (CONFIG.DH.GENERAL.deathMoves.riskItAll === this.selectedMove) {
result = await this.handleRiskItAll(); result = await this.handleRiskItAll(deathMoveAutomation.riskItAll);
} }
if (!result) return; if (result === undefined) return;
const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance) const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance)
.expandRollMessage?.desc; .expandRollMessage?.desc;

View file

@ -34,7 +34,7 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' }, header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' },
general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' }, general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' },
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/rules.hbs' }, rules: { template: 'systems/daggerheart/templates/settings/automation-settings/deathMoves.hbs' },
roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' }, roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' },
footer: { template: 'systems/daggerheart/templates/settings/automation-settings/footer.hbs' } footer: { template: 'systems/daggerheart/templates/settings/automation-settings/footer.hbs' }
}; };
@ -42,7 +42,7 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
/** @inheritdoc */ /** @inheritdoc */
static TABS = { static TABS = {
main: { main: {
tabs: [{ id: 'general' }, { id: 'rules' }, { id: 'roll' }], tabs: [{ id: 'general' }, { id: 'deathMoves' }, { id: 'roll' }],
initial: 'general', initial: 'general',
labelPrefix: 'DAGGERHEART.GENERAL.Tabs' labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
} }

View file

@ -94,8 +94,10 @@ export default class DHDomainCard extends BaseDataItem {
return false; return false;
} }
if (!this.actor.system.loadoutSlot.available) { if (!this.actor.system.loadoutSlot.available && !this.loadoutIgnore) {
data.system.inVault = true; data.system.inVault = true;
await this.updateSource({ inVault: true });
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.loadoutMaxReached'));
} }
} }
} }

View file

@ -55,6 +55,23 @@ export default class DhAutomation extends foundry.abstract.DataModel {
initial: true, initial: true,
label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.resourceScrollTexts.label' label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.resourceScrollTexts.label'
}), }),
deathMoveAutomation: new fields.SchemaField({
avoidDeath: new fields.BooleanField({
required: true,
initial: true,
label: 'DAGGERHEART.CONFIG.DeathMoves.avoidDeath.name'
}),
riskItAll: new fields.BooleanField({
required: true,
initial: true,
label: 'DAGGERHEART.CONFIG.DeathMoves.riskItAll.name'
}),
blazeOfGlory: new fields.BooleanField({
required: true,
initial: true,
label: 'DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'
})
}),
defeated: new fields.SchemaField({ defeated: new fields.SchemaField({
enabled: new fields.BooleanField({ enabled: new fields.BooleanField({
required: true, required: true,

View file

@ -86,6 +86,8 @@ export const enrichedDualityRoll = async (
{ reaction, traitValue, target, difficulty, title, label, advantage, grantResources, customConfig }, { reaction, traitValue, target, difficulty, title, label, advantage, grantResources, customConfig },
event event
) => { ) => {
const shouldGrantResources = grantResources === undefined ? true : grantResources;
const config = { const config = {
event: event ?? {}, event: event ?? {},
title: title, title: title,
@ -94,12 +96,12 @@ export const enrichedDualityRoll = async (
roll: { roll: {
trait: traitValue && target ? traitValue : null, trait: traitValue && target ? traitValue : null,
difficulty: difficulty, difficulty: difficulty,
advantage, advantage
// type: reaction ? 'reaction' : null //not needed really but keeping it for troubleshooting // type: reaction ? 'reaction' : null //not needed really but keeping it for troubleshooting
}, },
skips: { skips: {
resources: !grantResources, resources: !shouldGrantResources,
triggers: !grantResources triggers: !shouldGrantResources
}, },
type: 'trait', type: 'trait',
hasRoll: true, hasRoll: true,

View file

@ -14,15 +14,7 @@
"description": "<p><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>Once per long rest</strong></span>, you can give a heartfelt, inspiring speech. </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>All allies</strong></span> within </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>Far</strong></span> range </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>clear 2 Stress</strong></span><strong>.</strong></p>", "description": "<p><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>Once per long rest</strong></span>, you can give a heartfelt, inspiring speech. </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>All allies</strong></span> within </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>Far</strong></span> range </span><span style=\"box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); color: rgb(239, 230, 216); font-family: Montserrat, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgba(24, 22, 46, 0.376); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial\"><strong>clear 2 Stress</strong></span><strong>.</strong></p>",
"chatDisplay": false, "chatDisplay": false,
"actionType": "action", "actionType": "action",
"cost": [ "cost": [],
{
"scalable": false,
"key": "hitPoints",
"value": 1,
"step": null,
"consumeOnSuccess": false
}
],
"uses": { "uses": {
"value": null, "value": null,
"max": "1", "max": "1",

View file

@ -54,6 +54,9 @@
input[type='checkbox'], input[type='checkbox'],
input[type='radio'] { input[type='radio'] {
height: 20px;
width: 20px;
&:checked::after { &:checked::after {
color: light-dark(@dark, @golden); color: light-dark(@dark, @golden);
} }

View file

@ -2,11 +2,13 @@
.status-effects { .status-effects {
.effect-control { .effect-control {
filter: none; filter: none;
background: var(--dark-blue-90);
} }
.effect-control-container { .effect-control-container {
.effect-control { .effect-control {
filter: none; filter: none;
background: var(--dark-blue-90);
} }
.effect-control-disabled-marker { .effect-control-disabled-marker {
@ -22,6 +24,7 @@
.palette-category-title { .palette-category-title {
grid-column: span var(--effect-columns); grid-column: span var(--effect-columns);
font-weight: bold; font-weight: bold;
color: light-dark(@dark-blue, @golden);
} }
} }
} }

View file

@ -82,7 +82,7 @@
} }
} }
&:not(.duality .fate) { &:not(.duality):not(.fate) {
.font-20 { .font-20 {
color: @dark; color: @dark;
} }
@ -176,7 +176,6 @@
} }
&.fate { &.fate {
&.hope { &.hope {
--text-color: @golden; --text-color: @golden;
--bg-color: @golden-40; --bg-color: @golden-40;
@ -194,7 +193,6 @@
background-color: @chat-blue-bg; background-color: @chat-blue-bg;
} }
} }
} }
&.duality { &.duality {

View file

@ -3,7 +3,8 @@
.daggerheart.chat-sidebar.theme-light, .daggerheart.chat-sidebar.theme-light,
#interface.theme-light { #interface.theme-light {
.chat-message:not(.duality) .message-content { .chat-message:not(.duality):not(.fate) {
.message-content {
color: @dark; color: @dark;
blockquote { blockquote {
@ -67,6 +68,7 @@
} }
} }
} }
}
.chat-message.dh-chat-message { .chat-message.dh-chat-message {
.message-content { .message-content {

View file

@ -227,16 +227,6 @@ aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip.card-s
outline: 1px solid light-dark(@dark-blue, @golden); outline: 1px solid light-dark(@dark-blue, @golden);
} }
.theme-light #tooltip:has(div.daggerheart.dh-style.tooltip.card-style),
.theme-light aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) {
background-image: url('../assets/parchments/dh-parchment-light.png');
}
.theme-light aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip) {
box-shadow: 0 0 25px @dark-blue-90;
outline: 1px solid light-dark(@dark-blue, @golden);
}
#tooltip, #tooltip,
.locked-tooltip, .locked-tooltip,
.daggerheart.dh-style.tooltip { .daggerheart.dh-style.tooltip {

View file

@ -1,8 +1,17 @@
<section <section
class="tab {{tabs.rules.cssClass}} {{tabs.rules.id}}" class="tab {{tabs.deathMoves.cssClass}} {{tabs.deathMoves.id}}"
data-tab="{{tabs.rules.id}}" data-tab="{{tabs.deathMoves.id}}"
data-group="{{tabs.rules.group}}" data-group="{{tabs.deathMoves.group}}"
> >
<fieldset>
<legend>
{{localize "DAGGERHEART.GENERAL.automation"}}
</legend>
{{formGroup settingFields.schema.fields.deathMoveAutomation.fields.avoidDeath value=settingFields._source.deathMoveAutomation.avoidDeath localize=true}}
{{formGroup settingFields.schema.fields.deathMoveAutomation.fields.riskItAll value=settingFields._source.deathMoveAutomation.riskItAll localize=true}}
{{formGroup settingFields.schema.fields.deathMoveAutomation.fields.blazeOfGlory value=settingFields._source.deathMoveAutomation.blazeOfGlory localize=true}}
</fieldset>
<fieldset> <fieldset>
<legend> <legend>
{{localize "DAGGERHEART.SETTINGS.Automation.defeated.title"}} {{localize "DAGGERHEART.SETTINGS.Automation.defeated.title"}}

View file

@ -13,6 +13,7 @@
{{formGroup settingFields.schema.fields.summaryMessages.fields.damage value=settingFields._source.summaryMessages.damage localize=true}} {{formGroup settingFields.schema.fields.summaryMessages.fields.damage value=settingFields._source.summaryMessages.damage localize=true}}
{{formGroup settingFields.schema.fields.summaryMessages.fields.effects value=settingFields._source.summaryMessages.effects localize=true}} {{formGroup settingFields.schema.fields.summaryMessages.fields.effects value=settingFields._source.summaryMessages.effects localize=true}}
</div> </div>
{{formGroup settingFields.schema.fields.countdownAutomation value=settingFields._source.countdownAutomation localize=true}} {{formGroup settingFields.schema.fields.countdownAutomation value=settingFields._source.countdownAutomation localize=true}}
{{formGroup settingFields.schema.fields.actionPoints value=settingFields._source.actionPoints localize=true}} {{formGroup settingFields.schema.fields.actionPoints value=settingFields._source.actionPoints localize=true}}
{{formGroup settingFields.schema.fields.hordeDamage value=settingFields._source.hordeDamage localize=true}} {{formGroup settingFields.schema.fields.hordeDamage value=settingFields._source.hordeDamage localize=true}}