diff --git a/src/lang/en.json b/src/lang/en.json index d3eb1486..8d68c78e 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -637,6 +637,8 @@ "DL.SettingDSNColourDie": "Enable dice colouring", "DL.SettingDSNHint": "Colourize the Dice So Nice! boons/banes dice. Select d3 die numerals (Arabic/Roman) on Demon Lord theme.", "DL.SettingDSNLabel": "Dice So Nice! Settings", + "DL.SettingDamageScrollText": "Enable Scroll Text for Damage/Health", + "DL.SettingDamageScrollTextHint": "When checked, scrolling text appears above tokens about damage/heal value.", "DL.SettingEnableQuickDraw": "Enable one-click draw for rolltables.", "DL.SettingEnableQuickDrawHint": "Draw directly form sidebar, compendia or sheets (right-click).", "DL.SettingFinesseAutoSelect": "Finesse weapon attack attribute auto select", diff --git a/src/module/active-effects/afflictions.js b/src/module/active-effects/afflictions.js index bd2fdfab..35ef7a31 100644 --- a/src/module/active-effects/afflictions.js +++ b/src/module/active-effects/afflictions.js @@ -177,11 +177,10 @@ export class DLAfflictions { effectsDataList.push(_buildBaseAffliction('grabbed', 'systems/demonlord/assets/icons/effects/grabbed.svg')) // Horrified - const baneValue = game.settings.get('demonlord', 'optionalRuleBaneValue') ? -2 : -3 effectsDataList.push( _buildBaseAffliction('horrified', 'systems/demonlord/assets/icons/effects/horrified.svg', [ - addEffect('system.bonuses.challenge.boons.all', baneValue, effectPriority), - addEffect('system.bonuses.attack.boons.all', baneValue, effectPriority), + addEffect('system.bonuses.challenge.boons.all', -3, effectPriority), + addEffect('system.bonuses.attack.boons.all', -3, effectPriority), ]), ) diff --git a/src/module/actor/actor.js b/src/module/actor/actor.js index 9aff0412..662555c9 100644 --- a/src/module/actor/actor.js +++ b/src/module/actor/actor.js @@ -625,7 +625,11 @@ getTargetAttackBane(target) { for (let effect of this.appliedEffects) { const specialDuration = foundry.utils.getProperty(effect, `flags.${game.system.id}.specialDuration`) - if (specialDuration === 'NextD20Roll' || specialDuration === 'NextChallengeRoll') await effect?.delete() + const doNotAnimate = foundry.utils.getProperty(effect, `flags.${game.system.id}.doNotAnimate`) === undefined ? false: true + if (specialDuration === 'NextD20Roll' || specialDuration === 'NextChallengeRoll') { + if (doNotAnimate) await effect?.delete({animate: false}) + else await effect?.delete() + } } return challengeRoll @@ -1066,6 +1070,7 @@ getTargetAttackBane(target) { flags: { demonlord: { specialDuration: 'NextChallengeRoll', + doNotAnimate: true, }, }, }) @@ -1101,13 +1106,13 @@ getTargetAttackBane(target) { }, ], flags: { demonlord: { - specialDuration: 'NextChallengeRoll', + specialDuration: 'NextChallengeRoll', animate: false }, }, }) await ActiveEffect.create(willChallengeRollBanesEffect, { - parent: actor, + parent: actor, animate: false }) } } @@ -1128,12 +1133,13 @@ getTargetAttackBane(target) { flags: { demonlord: { specialDuration: 'NextChallengeRoll', + doNotAnimate : true, }, }, }) await ActiveEffect.create(darkMagicSpellsKnownEffect, { - parent: actor, + parent: actor, animate: false }) } } @@ -1219,7 +1225,7 @@ getTargetAttackBane(target) { if (validTargetArray.length >= 4 && !isStunned) await ActiveEffect.create(fourAndMoreEffect, { - parent: actor, + parent: actor, animate: false }) const isFrightened = actor.effects.find(e => e.statuses?.has('frightened')) === undefined ? false : true @@ -1349,7 +1355,7 @@ getTargetAttackBane(target) { }) await ActiveEffect.create(seesFrighteningSource, { - parent: actor, + parent: actor, animate: false }) } @@ -1539,7 +1545,7 @@ getTargetAttackBane(target) { }) await ActiveEffect.create(seesFrighteningSource, { - parent: actor, + parent: actor, animate: false }) } } diff --git a/src/module/actor/sheets/base-actor-sheet.js b/src/module/actor/sheets/base-actor-sheet.js index b3b2f1b9..c5e96cb6 100644 --- a/src/module/actor/sheets/base-actor-sheet.js +++ b/src/module/actor/sheets/base-actor-sheet.js @@ -523,6 +523,13 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh const affliction = CONFIG.statusEffects.find(a => a.id === afflictionId) if (!affliction) return false affliction['statuses'] = [affliction.id] + + if (affliction.id === "horrified") + { + affliction.description = game.settings.get('demonlord', 'optionalRuleBaneValue') ? affliction.description.replace('3','2') : affliction.description = affliction.description.replace('2','3') + game.settings.get('demonlord', 'optionalRuleBaneValue') ? Object.keys(affliction.changes).forEach(function(value){ affliction.changes[value].value = -2 }) : Object.keys(affliction.changes).forEach(function(value){ affliction.changes[value].value = -3 }) + } + await ActiveEffect.create(affliction, { parent: this.actor }) const targets = tokenManager.targets switch (afflictionId) { diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 029fa6ed..6cbd0c63 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -510,7 +510,7 @@ export async function postCustomTextToChat(actor, roll, options, attribute = {}) data['targetValue'] = targetNumber data['failureText'] = roll.total >= targetNumber - ? game.i18n.localize('DL.YouCannotBeEffectedUntilYouCompleteARest') + ? game.i18n.localize('DL.YouCannotBeAffectedUntilYouCompleteARest') : game.i18n.format('DL.BecomeFrightenedForRounds', { round: `${durationRollFormulaText}` }) data['actionEffects'] = buildAttributeEffectsMessage(actor, attribute, 0, 0) data['resultText'] = @@ -530,7 +530,7 @@ export async function postCustomTextToChat(actor, roll, options, attribute = {}) if (options.legacyMode) { data['failureText'] = roll.total >= targetNumber - ? game.i18n.localize('DL.YouCannotBeEffectedUntilYouCompleteARest') + ? game.i18n.localize('DL.YouCannotBeAffectedUntilYouCompleteARest') : isMad ? game.i18n.format('DL.GainedInsanityAndGoMad', { insanity: 1 }) : game.i18n.format('DL.GainedInsanity', { insanity: 1 }) @@ -592,7 +592,7 @@ export async function postCustomTextToChat(actor, roll, options, attribute = {}) if (options.legacyMode) { data['failureText'] = roll.total >= targetNumber - ? game.i18n.format('DL.YouCannotBeEffectedUntilYouCompleteARest') + ? game.i18n.format('DL.YouCannotBeAffectedUntilYouCompleteARest') : game.i18n.format('DL.GainedInsanity', { insanity: `${insanityRollFormulaText}` }) } else { data['failureText'] = diff --git a/src/module/demonlord.js b/src/module/demonlord.js index cac212b9..0f6994ab 100644 --- a/src/module/demonlord.js +++ b/src/module/demonlord.js @@ -261,10 +261,43 @@ Hooks.on('createToken', async _tokenDocument => { return 0 }) -Hooks.on('updateActor', async (actor, updateData) => { +Hooks.on("preUpdateActor", (actor, updateData, options) => { + options['demonlord'] = { + oldHealth: actor.system.characteristics.health.value + } +}) + +Hooks.on('updateActor', async (actor, updateData, options) => { if (!game.ready || !actor.isOwner) return if (Object.keys(updateData).equals(['_id'])) return - + if (actor && updateData && options?.action == 'update' && options?.diff && game.settings.get('demonlord', 'damageScrollText')) { + const oldHealth = options['demonlord'].oldHealth + const flatChanges = foundry.utils.flattenObject(updateData) + for (const [key, value] of Object.entries(flatChanges)) { + if (key === 'system.characteristics.health.value') { + /** + * Modified version of the awesome https://github.com/foundryvtt/dnd5e/blob/5.3.x/module/documents/actor/actor.mjs + * Big thanks to Andrew Clayton + */ + const tokens = actor.isToken ? [actor.token] : actor.getActiveTokens(true, true) + if (!tokens.length) return + const diff = value - oldHealth + for (const token of tokens) { + if (!token.object?.visible || token.isSecret) continue; + const t = token.object + canvas.interface.createScrollingText(t.center, diff * -1, { + duration: 1000, + fontSize: 28 + 20 * (Math.clamp(Math.abs(diff) / actor.system.characteristics.health.max, 0, 1)), + fill: diff > 0 ? "#a22223" : "#1b8f23", + direction: diff > 0 ? CONST.TEXT_ANCHOR_POINTS.BOTTOM : CONST.TEXT_ANCHOR_POINTS.TOP, + stroke: 0x000000, + strokeThickness: 4, + jitter: 0.25 + }) + } + } + } + } if (game.combat) { let token = actor.token || game.combats?.viewed?.combatants.find(c => c.actor?.id == actor.id)?.token diff --git a/src/module/settings.js b/src/module/settings.js index 41811f05..8b6d9604 100644 --- a/src/module/settings.js +++ b/src/module/settings.js @@ -963,4 +963,12 @@ export const registerSettings = function () { type: Boolean, config: true }) + game.settings.register('demonlord', 'damageScrollText', { + name: game.i18n.localize('DL.SettingDamageScrollText'), + hint: game.i18n.localize('DL.SettingDamageScrollTextHint'), + default: true, + scope: 'world', + type: Boolean, + config: true, + }) } diff --git a/src/module/utils/handlebars-helpers.js b/src/module/utils/handlebars-helpers.js index 69ad1c98..048454d8 100644 --- a/src/module/utils/handlebars-helpers.js +++ b/src/module/utils/handlebars-helpers.js @@ -112,6 +112,14 @@ export function registerHandlebarsHelpers() { return ( game.settings.get('demonlord', 'optionalRuleHide2025FHTraits') && !game.settings.get('demonlord', 'optionalRuleTraitMode2025') && ([game.i18n.localize('DL.CreatureHorrifying').toLowerCase(), game.i18n.localize('DL.CreatureFrightening').toLowerCase()].find(x => x === a.toLowerCase()) !== undefined)) }) + Handlebars.registerHelper('dlGetAfflictionToolTip', function (tooltip) { + if (tooltip === 'DL.AfflictionsHorrified') + return game.settings.get('demonlord', 'optionalRuleBaneValue') + ? game.i18n.localize('DL.AfflictionsHorrified').replace('3', '2') + : game.i18n.localize('DL.AfflictionsHorrified').replace('2', '3') + else return game.i18n.localize(tooltip) + }) + Handlebars.registerHelper('enrichHTMLUnrolled', async (x) => await TextEditor.enrichHTML(x, { unrolled: true })) Handlebars.registerHelper('lookupAttributeModifier', (attributeName, actorData) => actorData?.system?.attributes[attributeName.toLowerCase()]?.modifier diff --git a/src/templates/actor/tabs/afflictions.hbs b/src/templates/actor/tabs/afflictions.hbs index d550ca2b..699f8961 100644 --- a/src/templates/actor/tabs/afflictions.hbs +++ b/src/templates/actor/tabs/afflictions.hbs @@ -1,7 +1,7 @@