From 70ebf8d75e1f7b8c62004f611bc782d4f3a6e620 Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 10 Dec 2025 17:38:56 +0100 Subject: [PATCH 1/8] RestDialog width fix --- src/module/dialog/rest-dialog.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/module/dialog/rest-dialog.js b/src/module/dialog/rest-dialog.js index dc563956..46135e86 100644 --- a/src/module/dialog/rest-dialog.js +++ b/src/module/dialog/rest-dialog.js @@ -3,6 +3,9 @@ const { DialogV2 } = foundry.applications.api export default function launchRestDialog(dialogTitle, callback) { const d = new DialogV2({ window: { title: dialogTitle }, + position: { + width: 500, + }, content: `
From 79cce56066a52b9b5cf764c6c8aaa8fda858cd1e Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 10 Dec 2025 17:45:18 +0100 Subject: [PATCH 2/8] voidRoll colour fix --- src/module/chat/roll-messages.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 6e0376d6..236d3fb2 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -47,13 +47,13 @@ export function postAttackToChat(attacker, defender, item, attackRoll, attackAtt const attackAttributeImmune = attacker?.getAttribute(attackAttribute)?.immune const defenseAttributeImmune = defender?.getAttribute(defenseAttribute)?.immune - const voidRoll = attackAttributeImmune || defenseAttributeImmune const targetNumber = defenseAttribute === 'defense' ? defender?.system.characteristics.defense : defender?.getAttribute(defenseAttribute)?.value || '' + const voidRoll = attackAttributeImmune || defenseAttributeImmune || !targetNumber const plus20 = attackRoll?.total >= 20 && (targetNumber ? attackRoll?.total > targetNumber + (game.settings.get('demonlord', 'optionalRuleExceedsByFive') ? 5 : 4) : true) const didHit = voidRoll ? false : attackRoll?.total >= targetNumber @@ -66,7 +66,7 @@ export function postAttackToChat(attacker, defender, item, attackRoll, attackAtt diceTotal = '?' // resultText = '' } - const resultBoxClass = voidRoll ? 'FAILURE' : (resultText === '' ? '' : didHit ? 'SUCCESS' : 'FAILURE') + const resultBoxClass = voidRoll ? '' : (resultText === '' ? '' : didHit ? 'SUCCESS' : 'FAILURE') const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((defender?.type === 'character' && defender?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' @@ -216,7 +216,6 @@ export function postTalentToChat(actor, talent, attackRoll, target, inputBoons, const attackAttributeImmune = actor?.getAttribute(attackAttribute)?.immune const defenseAttributeImmune = target?.getAttribute(defenseAttribute)?.immune - const voidRoll = attackAttributeImmune || defenseAttributeImmune let usesText = '' if (parseInt(talentData?.uses?.value) >= 0 && parseInt(talentData?.uses?.max) > 0) { @@ -226,6 +225,7 @@ export function postTalentToChat(actor, talent, attackRoll, target, inputBoons, } const targetNumber = talentData?.action?.attack ? actor.getTargetNumber(talent) : '' + const voidRoll = attackAttributeImmune || defenseAttributeImmune || !targetNumber const plus20 = attackRoll?.total >= 20 && (targetNumber ? attackRoll?.total > targetNumber + (game.settings.get('demonlord', 'optionalRuleExceedsByFive') ? 5 : 4) : true) let resultText = @@ -241,7 +241,7 @@ export function postTalentToChat(actor, talent, attackRoll, target, inputBoons, diceTotal = '?' // resultText = '' } - const resultBoxClass = voidRoll ? 'FAILURE' : (resultText === '' ? '' : attackRoll?.total >= +targetNumber ? 'SUCCESS' : 'FAILURE') + const resultBoxClass = voidRoll ? '' : (resultText === '' ? '' : attackRoll?.total >= +targetNumber ? 'SUCCESS' : 'FAILURE') const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((target?.actor?.type === 'character' && target?.actor?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' @@ -338,7 +338,6 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo const attackAttributeImmune = actor?.getAttribute(attackAttribute)?.immune const defenseAttributeImmune = target?.getAttribute(defenseAttribute)?.immune - const voidRoll = attackAttributeImmune || defenseAttributeImmune let uses = parseInt(spellData?.castings?.value) let usesMax = parseInt(spellData?.castings?.max) @@ -346,6 +345,7 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo if (uses >= 0 && usesMax > 0) usesText = game.i18n.localize('DL.SpellCastingsUses') + ': ' + uses + ' / ' + usesMax const targetNumber = actor.getTargetNumber(spell) + const voidRoll = attackAttributeImmune || defenseAttributeImmune || !targetNumber const plus20 = attackRoll?.total >= 20 && (targetNumber ? attackRoll?.total > targetNumber + (game.settings.get('demonlord', 'optionalRuleExceedsByFive') ? 5 : 4) : true) let resultText = @@ -360,7 +360,7 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo diceTotal = '?' // resultText = '' } - const resultBoxClass = voidRoll ? 'FAILURE' : (resultText === '' ? '' : attackRoll?.total >= +targetNumber ? 'SUCCESS' : 'FAILURE') + const resultBoxClass = voidRoll ? '' : (resultText === '' ? '' : attackRoll?.total >= +targetNumber ? 'SUCCESS' : 'FAILURE') const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((target?.actor?.type === 'character' && target?.actor?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' From c197aeabc7b1810ebadefbf858fa0d470d6bbaa7 Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 10 Dec 2025 17:52:33 +0100 Subject: [PATCH 3/8] Corruption roll fix --- src/module/chat/roll-messages.js | 49 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 236d3fb2..41027818 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -460,6 +460,26 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo /* -------------------------------------------- */ +async function rollMarkOfDarkness(actor, corruptionRoll) { + // Get mark of darkess if roll < corruption value + if (corruptionRoll.total < actor.system.characteristics.corruption.value) { + const compendiumRollTables = await game.packs.get('demonlord.sotdl-roll-tables').getDocuments() + const tableMarkOfDarkess = compendiumRollTables.find(i => i.name === 'Mark of Darkness') + const result = await tableMarkOfDarkess.draw() + let resultText = result.results[0].text + await actor.createEmbeddedDocuments('Item', [ + { + name: 'Mark of Darkness', + type: 'feature', + img: 'icons/magic/death/skull-energy-light-purple.webp', + system: { + description: resultText, + }, + }, + ]) + } +} + export async function postCorruptionToChat(actor, corruptionRoll) { const templateData = { actor: actor, @@ -489,25 +509,16 @@ export async function postCorruptionToChat(actor, corruptionRoll) { chatData.content = await foundry.applications.handlebars.renderTemplate(template, templateData) chatData.sound = CONFIG.sounds.dice - await ChatMessage.create(chatData) - - // Get mark of darkess if roll < corruption value - if (corruptionRoll.total < actor.system.characteristics.corruption.value) { - const compendiumRollTables = await game.packs.get('demonlord.sotdl roll tabels').getDocuments() - const tableMarkOfDarkess = compendiumRollTables.find(i => i.name === 'Mark of Darkness') - const result = await tableMarkOfDarkess.draw() - let resultText = result.results[0].text - await actor.createEmbeddedDocuments('Item', [ - { - name: 'Mark of Darkness', - type: 'feature', - img: 'icons/magic/death/skull-energy-light-purple.webp', - system: { - description: resultText, - }, - }, - ]) - } + const msg = await ChatMessage.create(chatData) + // Wait for 3D roll. + if (game.modules.get('dice-so-nice')?.active) { + game.dice3d + .waitFor3DAnimationByMessageID(msg.id) + .then(() => + rollMarkOfDarkness(actor,corruptionRoll) + ) + } else + await rollMarkOfDarkness(actor,corruptionRoll) } export async function postFortuneToChat(actor, awarded) { From 5ac293bde149b95ed7cbdee3bd9ef97aa0c1474f Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 17 Dec 2025 19:50:16 +0100 Subject: [PATCH 4/8] Look Out creatures! --- src/lang/en.json | 7 + src/module/actor/actor.js | 135 +++++++++++++++++- src/module/actor/sheets/character-sheet.js | 5 + src/module/chat/roll-messages.js | 31 ++++ src/module/dialog/frightened-dialog.js | 40 ++++++ .../actor/parts/character-sheet-sidemenu.hbs | 3 + src/templates/chat/text.hbs | 9 ++ 7 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 src/module/dialog/frightened-dialog.js create mode 100644 src/templates/chat/text.hbs diff --git a/src/lang/en.json b/src/lang/en.json index a36e0276..6af53757 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -174,6 +174,9 @@ "DL.AvailabilityR": "Rare", "DL.AvailabilityU": "Uncommon", "DL.BackgroundTitle": "Background", + "DL.BecomeFrightenedForRound" : "Your become frightened {round} round.", + "DL.BecomeFrightenedForRounds" : "Your become frightened {round} rounds.", + "DL.BecomeStunned" : "Your become stunned for {round} round.", "DL.ButtonEdit": "Edit", "DL.ButtonView": "View", "DL.ChallengeRequestRollText": "Request Challenge Roll", @@ -383,6 +386,9 @@ "DL.FeatureDelete": "Delete feature", "DL.FeatureEdit": "Edit feature", "DL.FeaturesTitle": "Features", + "DL.FourOrMoreCreatures": "Four or more creatures at once", + "DL.FourOrMoreCreaturesInSight": "Sees four or more creatures at once", + "DL.GainedInsanity" : "You gain {insanity} Insanity.", "DL.GMTools": "GM Tools", "DL.GMnote": "GM Notes", "DL.GMnoteEdit": "Edit GM Note", @@ -426,6 +432,7 @@ "DL.LanguagesTitle": "Languages", "DL.LanguagesWrite": "Write", "DL.LanguagesWriteShort": "W", + "DL.LookOutCreatures": "Look out creatures!", "DL.MacroApplyAfflicationTitle": "Apply Afflictions", "DL.MacroCancel": "Cancel", "DL.MacroChallengeChoose": "Choose Attribute:", diff --git a/src/module/actor/actor.js b/src/module/actor/actor.js index 7e3b0253..baa1b5f6 100644 --- a/src/module/actor/actor.js +++ b/src/module/actor/actor.js @@ -6,6 +6,7 @@ import {DLActiveEffects} from '../active-effects/item-effects' import {DLAfflictions} from '../active-effects/afflictions' import {capitalize, plusify} from '../utils/utils' import launchRollDialog from '../dialog/roll-dialog' +import launchFrightenedDialog from '../dialog/frightened-dialog' import { postAttackToChat, postAttributeToChat, @@ -14,7 +15,8 @@ import { postSpellToChat, postTalentToChat, postFortuneToChat, - postRestToChat + postRestToChat, + postPlainTextToChat } from '../chat/roll-messages' import {handleCreateAncestry, handleCreatePath, handleCreateRole, handleCreateRelic } from '../item/nested-objects' import {TokenManager} from '../pixi/token-manager' @@ -951,6 +953,137 @@ export class DemonlordActor extends Actor { /* -------------------------------------------- */ + async goingMad() { + const compendia = await game.packs.get('sdlc-1000.tables') + if (compendia) { + const compendiumRollTables = await compendia.getDocuments() + const tableMadness = compendiumRollTables.find(i => i.name === 'Madness') + if (tableMadness) await tableMadness.draw() + } + } + + async stunnedChallengeRoll() { + let actor = this + if (!actor.isImmuneToAffliction('stunned')) { + const attribute = actor.getAttribute('will') + let roll = await actor.rollAttributeChallenge(attribute, 0, 0) + const targetNumber = game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' ? 11 : 10 + if (roll._total < targetNumber) { + const stunnedEffect = CONFIG.statusEffects.find(e => e.id === 'stunned') + stunnedEffect['statuses'] = stunnedEffect.id + stunnedEffect.duration.rounds = 1 + await ActiveEffect.create(stunnedEffect, { + parent: actor, + }) + } + let durationRoll = new Roll(`1d1`) + await durationRoll.evaluate() + postPlainTextToChat(actor, 'stunned',durationRoll) + } else ui.notifications.warn(game.i18n.localize('DL.DialogWarningActorImmune')) + } + + async setInsanityValue(roll) { + let actor = this + let increment = roll._total + let newValue = + actor.system.characteristics.insanity.value + increment < actor.system.characteristics.insanity.max + ? actor.system.characteristics.insanity.value + increment + : actor.system.characteristics.insanity.max + const isFrightened = actor.effects.find(e => e.statuses?.has('frightened')) === undefined ? false : true + const isStunned = actor.effects.find(e => e.statuses?.has('stunned')) === undefined ? false : true + await actor.update({ 'system.characteristics.insanity.value': newValue }) + if (!isFrightened) { + const frightenedEffect = CONFIG.statusEffects.find(e => e.id === 'frightened') + frightenedEffect['statuses'] = frightenedEffect.id + frightenedEffect.duration.rounds = newValue + + if (!actor.isImmuneToAffliction('frightened')) { + await ActiveEffect.create(frightenedEffect, { + parent: actor, + }) + } else ui.notifications.warn(game.i18n.localize('DL.DialogWarningActorImmune')) + } else { + const frightenedEffect = actor.effects.find(e => e.statuses?.has('frightened')) + await frightenedEffect.update({ 'duration.rounds': newValue }) + if (!isStunned) await this.stunnedChallengeRoll() + } + } + + async rollFrightened() { + let actor = this + const isStunned = actor.effects.find(e => e.statuses?.has('stunned')) === undefined ? false : true + launchFrightenedDialog(async (dHtml, creatureTrait) => { + let fourOrMore = dHtml.currentTarget.querySelector("input[id='fourOrMore']").checked ? -1 : 0 + if (fourOrMore) { + let fourAndMoreEffect = new ActiveEffect({ + name: game.i18n.localize('DL.FourOrMoreCreaturesInSight'), + icon: 'icons/svg/terror.svg', + changes: [{ key: 'system.bonuses.challenge.boons.will', value: -1, mode: CONST.ACTIVE_EFFECT_MODES.ADD }], + flags: { demonlord: { specialDuration: 'NextChallengeRoll' } }, + }) + + await ActiveEffect.create(fourAndMoreEffect, { + parent: actor, + }) + } + + if (!isStunned) { + const attribute = actor.getAttribute('will') + let roll = await actor.rollAttributeChallenge(attribute, 0, 0) + const targetNumber = game.settings.get('demonlord', 'optionalRuleDieRollsMode') === 'b' ? 11 : 10 + if (roll._total < targetNumber) await actor.rollDurationAndSanity(creatureTrait) + } + // Stunned -> autofail + else await actor.rollDurationAndSanity(creatureTrait) + }) + } + + async rollDurationAndSanity(creatureTrait) { + const actor = this + const isHorrifying = creatureTrait === 'h' || creatureTrait === 'fh' ? true : false + const isFrightening = creatureTrait === 'f' ? true : false + const isFrightened = actor.effects.find(e => e.statuses?.has('frightened')) === undefined ? false : true + + if (isFrightening) { + if (!isFrightened) { + if (!actor.isImmuneToAffliction('frightened')) { + let durationRoll = actor.system.characteristics.insanity.value + ? new Roll(`1d3+${actor.system.characteristics.insanity.value}`) + : new Roll(`1d3`) + await durationRoll.evaluate() + const frightenedEffect = CONFIG.statusEffects.find(e => e.id === 'frightened') + frightenedEffect['statuses'] = frightenedEffect.id + frightenedEffect.duration.rounds = durationRoll.total + await ActiveEffect.create(frightenedEffect, { + parent: actor, + }) + postPlainTextToChat(actor,'frightenedForRounds', durationRoll) + } else ui.notifications.warn(game.i18n.localize('DL.DialogWarningActorImmune')) + } else + { + let durationRoll = new Roll(`1d1`) + await durationRoll.evaluate() + this.setInsanityValue(durationRoll) + postPlainTextToChat(actor,'frightenedForRounds', durationRoll) + } + } + + if (isHorrifying) { + if (!isFrightened) { + let durationRoll = new Roll(`1d3`) + await durationRoll.evaluate() + this.setInsanityValue(durationRoll) + } else { + let insanityIncreaseRoll = new Roll('1d3') + await insanityIncreaseRoll.evaluate() + postPlainTextToChat(actor, 'gainedInsanity', insanityIncreaseRoll) + this.setInsanityValue(insanityIncreaseRoll) + } + } + + if (actor.system.characteristics.insanity.value === actor.system.characteristics.insanity.max) await this.goingMad() + } + async createItemCreate(event) { event.preventDefault() diff --git a/src/module/actor/sheets/character-sheet.js b/src/module/actor/sheets/character-sheet.js index 2c653848..1634d3b1 100644 --- a/src/module/actor/sheets/character-sheet.js +++ b/src/module/actor/sheets/character-sheet.js @@ -12,6 +12,7 @@ export default class DLCharacterSheet extends DLBaseActorSheet { }, actions: { rollCorruption: this.onRollCorruption, + rollFrightened: this.onrollFrightened, editStatBar: this.onEditStatBar, editLanguages: this.onEditLanguages, //editReligion: this.onEditReligion // Unused? @@ -215,6 +216,10 @@ export default class DLCharacterSheet extends DLBaseActorSheet { return await this.actor.rollCorruption() } + static async onrollFrightened() { + return await this.actor.rollFrightened() + } + /** Edit HealthBar, Insanity and Corruption */ static async onEditStatBar() { const actor = this.actor diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 41027818..49065baa 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -460,6 +460,37 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo /* -------------------------------------------- */ +export function postPlainTextToChat(actor, text, roll) { + const templateData = { + actor: actor, + data: {}, + } + + const rollMode = game.settings.get('core', 'rollMode') + const chatData = getChatBaseData(actor, rollMode) + const data = templateData.data + data['actorInfo'] = buildActorInfo(actor) + data['text'] = text + switch (text) { + case 'frightenedForRounds': + data['text'] = Math.abs(roll._total === 1) ? game.i18n.format('DL.BecomeFrightenedForRound', {round: roll._total}) : + game.i18n.format('DL.BecomeFrightenedForRounds', {round: roll._total}) + break + case 'stunned': + data['text'] = game.i18n.format('DL.BecomeStunned', {round: roll._total}) + break + case 'gainedInsanity': + data['text'] = game.i18n.format('DL.GainedInsanity', {insanity: roll._total}) + break + } + if (roll) chatData.rolls = [roll] + const template = 'systems/demonlord/templates/chat/text.hbs' + foundry.applications.handlebars.renderTemplate(template, templateData).then(content => { + chatData.content = content + ChatMessage.create(chatData) + }) +} + async function rollMarkOfDarkness(actor, corruptionRoll) { // Get mark of darkess if roll < corruption value if (corruptionRoll.total < actor.system.characteristics.corruption.value) { diff --git a/src/module/dialog/frightened-dialog.js b/src/module/dialog/frightened-dialog.js new file mode 100644 index 00000000..c740c946 --- /dev/null +++ b/src/module/dialog/frightened-dialog.js @@ -0,0 +1,40 @@ +const { DialogV2 } = foundry.applications.api + +export default function launchFrightenedDialog(callback) { + const d = new DialogV2({ + window: { + title: game.i18n.localize('DL.LookOutCreatures'), + }, + options : { closeOnSubmit: true}, + position: { + width: 500, + }, + content: ` +
+
+ + +
+
+ `, + buttons: [ + { + action: 'f', + label: game.i18n.localize('DL.CreatureFrightening'), + callback: html => callback(html, 'f'), + }, + { + action: 'h', + label: game.i18n.localize('DL.CreatureHorrifying'), + callback: html => callback(html, 'h'), + }, + { + action: 'fh', + label: `${game.i18n.localize('DL.CreatureFrightening')}/${game.i18n.localize('DL.CreatureHorrifying')}`, + callback: html => callback(html, 'fh'), + }, + ], + close: () => {}, + }) + d.render(true) +} \ No newline at end of file diff --git a/src/templates/actor/parts/character-sheet-sidemenu.hbs b/src/templates/actor/parts/character-sheet-sidemenu.hbs index 8744cf6b..6c4c79e7 100644 --- a/src/templates/actor/parts/character-sheet-sidemenu.hbs +++ b/src/templates/actor/parts/character-sheet-sidemenu.hbs @@ -90,6 +90,9 @@ {{#unless system.characteristics.insanity.immune}}
{{ifThen (gte ownership 2) system.characteristics.insanity.max '?'}}
{{ifThen (gte ownership 2) system.characteristics.insanity.value '?'}}
+ {{#if (gte ownership 2)}} + + {{/if}} {{else}}
{{/unless}} diff --git a/src/templates/chat/text.hbs b/src/templates/chat/text.hbs new file mode 100644 index 00000000..4a8dd962 --- /dev/null +++ b/src/templates/chat/text.hbs @@ -0,0 +1,9 @@ +
+
{{data.actorInfo}}
+
+
+ {{data.text}} +
+
+
From 5dd78be477d9dd3068dd848141401f4dc6923378 Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 17 Dec 2025 20:28:16 +0100 Subject: [PATCH 5/8] Combat duration display fixes --- src/module/active-effects/effects.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/module/active-effects/effects.js b/src/module/active-effects/effects.js index d269ca5e..3ebee57a 100644 --- a/src/module/active-effects/effects.js +++ b/src/module/active-effects/effects.js @@ -120,17 +120,17 @@ export function prepareActiveEffectCategories(effects, showCreateButtons = false if (e.duration.turns > 0) { const rr = calcEffectRemainingRounds(e, game.combat.round) const rt = calcEffectRemainingTurn(e, game.combat.turn) - const sr = `${rr} ${Math.abs(rr) > 1 ? i18n("COMBAT.Rounds") : i18n("COMBAT.Round")}` - const st = `${rt} ${Math.abs(rt) > 1 ? i18n("COMBAT.Turns") : i18n("COMBAT.Turn")}` + const sr = Math.abs(rr) > 1 ? `${rr} ${i18n("COMBAT.DURATION.ROUNDS.many")}` : `${rr} ${i18n("COMBAT.DURATION.ROUNDS.one")}` + const st = Math.abs(rt) > 1 ? `${rt} ${i18n("COMBAT.DURATION.TURNS.many")}` : `${rt} ${i18n("COMBAT.DURATION.TURNS.one")}` e.dlRemaining = sr + ' ' + st } else { const r = calcEffectRemainingRounds(e, game.combat.round) - e.dlRemaining = `${r} ${Math.abs(r) > 1 ? i18n("COMBAT.Rounds") : i18n("COMBAT.Round")}` + e.dlRemaining = Math.abs(r) > 1 ? `${r} ${i18n("COMBAT.DURATION.ROUNDS.many")}` : `${r} ${i18n("COMBAT.DURATION.ROUNDS.one")}` } } else { const r = calcEffectRemainingSeconds(e, game.time.worldTime) - e.dlRemaining = `${r} ${i18n("TIME.Seconds")}` + e.dlRemaining = Math.abs(r) > 1 ? `${r} ${i18n("TIME.Second.other")}` : `${r} ${i18n("TIME.Second.one")}` } } else { e.dlRemaining = e.duration.label From 2ebfeb280cd1ad0080b276d85216702d99859ee5 Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 17 Dec 2025 20:33:27 +0100 Subject: [PATCH 6/8] postAttributeToChat localization fix --- src/module/chat/roll-messages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 49065baa..a46f420b 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -165,7 +165,7 @@ export function postAttributeToChat(actor, attribute, challengeRoll, inputBoons, const templateData = { actor: actor, tokenId: actor.token ? actor.token.uuid : null, - item: {name: attribute?.toUpperCase()}, + item: {name: game.i18n.localize(CONFIG.DL.attributes[attribute]?.toUpperCase())}, diceData: formatDice(challengeRoll), data: {}, } From f68113440f83c993d9092bab51f6f385853ff191 Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 17 Dec 2025 20:39:25 +0100 Subject: [PATCH 7/8] Restore lost functionality --- src/templates/actor/parts/character-sheet-sidemenu.hbs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/templates/actor/parts/character-sheet-sidemenu.hbs b/src/templates/actor/parts/character-sheet-sidemenu.hbs index 6c4c79e7..b81cf283 100644 --- a/src/templates/actor/parts/character-sheet-sidemenu.hbs +++ b/src/templates/actor/parts/character-sheet-sidemenu.hbs @@ -138,6 +138,7 @@ {{#if (gte ownership 2)}}
+ {{#unless hideFortune}}
+ {{/unless}} + {{#unless hideTurnMode}}
+ {{/unless}}
{{/if}}
From 91633adb56f91a8782054c00d3df30dc676b20fe Mon Sep 17 00:00:00 2001 From: sasquach45932 Date: Wed, 17 Dec 2025 20:42:26 +0100 Subject: [PATCH 8/8] Corruption roll fix #2 --- src/module/chat/roll-messages.js | 47 ++++++++++++-------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index a46f420b..c0fda309 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -491,26 +491,6 @@ export function postPlainTextToChat(actor, text, roll) { }) } -async function rollMarkOfDarkness(actor, corruptionRoll) { - // Get mark of darkess if roll < corruption value - if (corruptionRoll.total < actor.system.characteristics.corruption.value) { - const compendiumRollTables = await game.packs.get('demonlord.sotdl-roll-tables').getDocuments() - const tableMarkOfDarkess = compendiumRollTables.find(i => i.name === 'Mark of Darkness') - const result = await tableMarkOfDarkess.draw() - let resultText = result.results[0].text - await actor.createEmbeddedDocuments('Item', [ - { - name: 'Mark of Darkness', - type: 'feature', - img: 'icons/magic/death/skull-energy-light-purple.webp', - system: { - description: resultText, - }, - }, - ]) - } -} - export async function postCorruptionToChat(actor, corruptionRoll) { const templateData = { actor: actor, @@ -540,16 +520,23 @@ export async function postCorruptionToChat(actor, corruptionRoll) { chatData.content = await foundry.applications.handlebars.renderTemplate(template, templateData) chatData.sound = CONFIG.sounds.dice - const msg = await ChatMessage.create(chatData) - // Wait for 3D roll. - if (game.modules.get('dice-so-nice')?.active) { - game.dice3d - .waitFor3DAnimationByMessageID(msg.id) - .then(() => - rollMarkOfDarkness(actor,corruptionRoll) - ) - } else - await rollMarkOfDarkness(actor,corruptionRoll) + await ChatMessage.create(chatData) + if (corruptionRoll.total < actor.system.characteristics.corruption.value) { + const compendiumRollTables = await game.packs.get('demonlord.sotdl-roll-tables').getDocuments() + const tableMarkOfDarkess = compendiumRollTables.find(i => i.name === 'Mark of Darkness') + const result = await tableMarkOfDarkess.draw() + let resultText = result.results[0].text + await actor.createEmbeddedDocuments('Item', [ + { + name: 'Mark of Darkness', + type: 'feature', + img: 'icons/magic/death/skull-energy-light-purple.webp', + system: { + description: resultText, + }, + }, + ]) + } } export async function postFortuneToChat(actor, awarded) {