diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c07bd..cac1902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,4 +12,12 @@ Jun 25, 2022 ## v0.0.4-ALPHA.0 Jul 23, 2022 -* Refactor of all \ No newline at end of file +* Refactor of all + + +## v0.0.5-BETA.0 +Jul 30, 2022 +* Initial release supporting PF2e system +* Right-click of fudge icon to globally pause/disable all fudges +* Config dialog UI improvements +* Notification to DMs when new version installed/upgraded \ No newline at end of file diff --git a/README.md b/README.md index f9baa40..024ca5e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +   + +  + Die Hard ======== This Foundry VTT module is intended to provide functionality that modifies/adjusted die rolls in certain systems. @@ -14,8 +18,6 @@ Currently being (quasi) managed here: https://github.com/users/UranusBytes/proje ## Currently Supported Systems * DND5e (current) - -## Future Supported Systems * PF2e ## Troubleshoot @@ -23,11 +25,15 @@ Extensive logging is used within the module, with debug logging enabled with the ## Known Issues * Raw die rolls for actors not working (even if fudge defined on GM/Player) -* Actors throwing raw It's possible to define a fudge that is impossible to achieve (especially when considering modifiers. Or to define a fudge of "> 20" for a d20). The failsafe is attempting to fudge 150 times, at which point the closest possible is provided. +* It's possible to define a fudge that is impossible to achieve (especially when considering modifiers. Or to define a fudge of "> 20" for a d20). The failsafe is attempting to fudge 150 times, at which point the closest possible is provided. * When the fudge config dialog is open, fudge status/list is not updated if any are changed by other GMs and/or PC/Actor rolls +* Completely incompatible with [Better Rolls for 5e](https://github.com/RedReign/FoundryVTT-BetterRolls5e) #6 -## Currently Supported Functionality -### Fudge +# Current module Functionality +## Fudge +Allow the GM to influence die rolls + +# Fudge  With the module enabled, a poop icon will be displayed above the message tray. @@ -67,6 +73,9 @@ The way Fudge works is that the next die roll of that type (either system specif -## Future Planned Functionality -### Karmic dice +# Future Planned Functionality +## Karmic dice All for gradual adjustment/influence of player dice over time... + +# Thanks +None of this module would be possible without the inspiration, and continued guidance/support/feedback, from @apoapostolov. Thank you! \ No newline at end of file diff --git a/module.json b/module.json index c54ac44..b5241d7 100644 --- a/module.json +++ b/module.json @@ -1,9 +1,9 @@ { "name": "foundry-die-hard", "title": "Die Hard", - "description": "Adjustments for DND5e die rolls like fudging...", + "description": "Adjustments for DND5e & PF2e die rolls like fudging...", "author": "Jeremy (UranusBytes)", - "version": "0.0.4", + "version": "0.0.5", "minimumCoreVersion": "9", "compatibleCoreVersion": "9", "esmodules": [ diff --git a/scripts/classes/DEPRECATED_DieHardFudge.js b/scripts/classes/DEPRECATED_DieHardFudge.js deleted file mode 100644 index b8e25bd..0000000 --- a/scripts/classes/DEPRECATED_DieHardFudge.js +++ /dev/null @@ -1,9 +0,0 @@ -export class DEPRECATED_DieHardFudge { - constructor() { - - } - - init() { - - } -} diff --git a/scripts/classes/DieHard.js b/scripts/classes/DieHard.js new file mode 100644 index 0000000..148de98 --- /dev/null +++ b/scripts/classes/DieHard.js @@ -0,0 +1,45 @@ +import {dieHardLog, insertAfter} from "../lib/helpers.js"; +import DieHardFudgeDialog from "./DieHardFudgeDialog.js"; + + +export default class DieHard { + + constructor() { + dieHardLog(true, 'DieHard - constructor'); + + // Setup default settings; + + } + + init() { + dieHardLog(true, 'DieHard - init'); + } + + static renderFudgeIcon() { + if (game.settings.get('foundry-die-hard', 'dieHardSettings').system == null) { + dieHardLog(false, 'Unsupported system for world; not rendering side bar') + return + } + dieHardLog(false, 'Render side bar') + let fudgeButton = document.createElement('label'); + //fudgeButton.setAttribute('id', 'die-hard-fudge-icon'); + fudgeButton.classList.add('die-hard-fudge-icon'); + fudgeButton.innerHTML = '
'; + + fudgeButton.addEventListener("click", async (ev) => { + new DieHardFudgeDialog().render(true); + }); + fudgeButton.addEventListener("contextmenu", async (ev) => { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.disableAllFudges(); + }); + + // ToDo: Fix this ugly hack + // the document object isn't existing sometimes yet, so just ignore. It'll eventually render + try { + //insertAfter(pauseButton, document.querySelector('.chat-control-icon')); + insertAfter(fudgeButton, document.querySelector('.chat-control-icon')); + game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon() + } + catch (e) { } + } +} \ No newline at end of file diff --git a/scripts/classes/DieHardConfig.js b/scripts/classes/DieHardConfig.js index d92d40c..2941b2c 100644 --- a/scripts/classes/DieHardConfig.js +++ b/scripts/classes/DieHardConfig.js @@ -1,5 +1,6 @@ import {dieHardLog} from "../lib/helpers.js"; -import {DieHardDnd5e} from "./DieHardDnd5e.js"; +import DieHardDnd5e from "./DieHardDnd5e.js"; +import DieHardPf2e from "./DieHardPf2e.js"; export default class DieHardConfig { // static get defaultOptions() { @@ -47,7 +48,8 @@ export default class DieHardConfig { allActors: true }, fudgeConfig: { - maxFudgeAttemptsPerRoll: 150 + maxFudgeAttemptsPerRoll: 150, + globalDisable: false }, gmFudges: [] }; @@ -55,7 +57,9 @@ export default class DieHardConfig { if (game.system.id == 'dnd5e') { dieHardLog(true, 'Configuring for dndn5e system') dieHardSettings.system = new DieHardDnd5e; - + } else if (game.system.id == 'pf2e') { + dieHardLog(true, 'Configuring for pf2e system') + dieHardSettings.system = new DieHardPf2e; } else { dieHardLog(true, 'Unsupport game system: ' + game.system.id) } diff --git a/scripts/classes/DieHardDnd5e.js b/scripts/classes/DieHardDnd5e.js index 8a1f321..1727dea 100644 --- a/scripts/classes/DieHardDnd5e.js +++ b/scripts/classes/DieHardDnd5e.js @@ -1,8 +1,9 @@ import {dieHardLog} from "../lib/helpers.js"; -import {DieHardSystem} from "./DieHardSystem.js"; -import {DieHardFudgeD20Roll} from "./DieHardFudgeD20Roll.js"; -export class DieHardDnd5e extends DieHardSystem{ +import DieHardSystem from "./DieHardSystem.js"; +import DieHardFudgeD20Roll from "./DieHardFudgeD20Roll.js"; + +export default class DieHardDnd5e extends DieHardSystem{ constructor() { dieHardLog(false, 'DieHardDnd5e - constructor'); super(); @@ -19,6 +20,7 @@ export class DieHardDnd5e extends DieHardSystem{ // See notes in DieHardFudgeD20Roll CONFIG.Dice.DieHardFudgeD20Roll = DieHardFudgeD20Roll; + this.rawRollClassName = "Roll" this.fudgeWhatOptions = [ { id: 'actorRollSkill', @@ -187,11 +189,18 @@ export class DieHardDnd5e extends DieHardSystem{ if (fudgeIndex !== -1 && actorFudges[fudgeIndex].statusActive) { dieHardLog(false, 'DieHardDnd5e.wrappedRoll - active actor fudge', actorFudges[fudgeIndex]); foundry.utils.mergeObject(options, {data: {fudge: true, fudgeOperator: actorFudges[fudgeIndex].operator, fudgeOperatorValue: actorFudges[fudgeIndex].operatorValue, fudgeHow: actorFudges[fudgeIndex].howFormula }}); - // Delete the fudge from the actor - let deletedFudge = actorFudges.splice(fudgeIndex,1) - game.actors.get(actorId).setFlag('foundry-die-hard', 'fudges', actorFudges); - // Check if still have active fudges; - this.refreshActiveFudgesIcon(); + if (actorFudges[fudgeIndex].statusEndless) { + dieHardLog(false, 'DieHardSystem.wrappedRoll - fudge is endless'); + } else { + // Disable the fudge + actorFudges[fudgeIndex].statusActive = false + + // Delete the fudge from the actor + // let deletedFudge = actorFudges.splice(fudgeIndex, 1) + game.actors.get(actorId).setFlag('foundry-die-hard', 'fudges', actorFudges); + // Check if still have active fudges; + this.refreshActiveFudgesIcon(); + } } // Check if user has an active fudge @@ -220,31 +229,41 @@ export class DieHardDnd5e extends DieHardSystem{ actorRollSkill(wrapped, skillId, options={}) { dieHardLog(false, 'DieHardDnd5e.actorRollSkill', this); - game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollSkill') + if (!game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollSkill') + } wrapped(skillId, options); } actorRollAbilitySave(wrapped, abilityId, options={}) { dieHardLog(false, 'DieHardDnd5e.actorRollAbilitySave', this); - game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilitySave') + if (!game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilitySave') + } wrapped(abilityId, options); } actorRollAbilityTest(wrapped, abilityId, options={}) { dieHardLog(false, 'DieHardDnd5e.actorRollAbilityTest', this); - game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilityTest') + if (!game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilityTest') + } wrapped(abilityId, options); } actorRollDeathSave(wrapped, options={}) { dieHardLog(false, 'DieHardDnd5e.actorRollDeathSave', this); - game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollDeathSave') + if (!game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollDeathSave') + } wrapped(options); } entityRollAttack(wrapped, options={}) { dieHardLog(false, 'DieHardDnd5e.entityRollAttack', this); - game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.actor.id, 'entityRollAttack') + if (!game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.actor.id, 'entityRollAttack') + } wrapped(options); } diff --git a/scripts/classes/DieHardFudgeD20Roll.js b/scripts/classes/DieHardFudgeD20Roll.js index 4022aca..5e15903 100644 --- a/scripts/classes/DieHardFudgeD20Roll.js +++ b/scripts/classes/DieHardFudgeD20Roll.js @@ -9,7 +9,7 @@ Because this extends D20Roll, I could not find a clean way to import. I tried m import D20Roll from '../../../../systems/dnd5e/module/dice/d20-roll.js' import {dieHardLog} from "../lib/helpers.js"; -export class DieHardFudgeD20Roll extends D20Roll { +export default class DieHardFudgeD20Roll extends D20Roll { // This is a simple extension constructor(formula, data, options) { super(formula, data, options); diff --git a/scripts/classes/DieHardFudgeDialog.js b/scripts/classes/DieHardFudgeDialog.js index 60a1608..57d3d27 100644 --- a/scripts/classes/DieHardFudgeDialog.js +++ b/scripts/classes/DieHardFudgeDialog.js @@ -1,6 +1,6 @@ import {dieHardLog} from "../lib/helpers.js"; -export class DieHardFudgeDialog extends FormApplication { +export default class DieHardFudgeDialog extends FormApplication { static get defaultOptions() { return mergeObject(super.defaultOptions, { classes: ['form'], diff --git a/scripts/classes/DieHardFudgeRoll.js b/scripts/classes/DieHardFudgeRoll.js index 3632efc..0674f78 100644 --- a/scripts/classes/DieHardFudgeRoll.js +++ b/scripts/classes/DieHardFudgeRoll.js @@ -1,4 +1,4 @@ -export class DieHardFudgeRoll extends Roll { +export default class DieHardFudgeRoll extends Roll { // This is a simple extension constructor(formula, data, options) { super(formula, data, options); diff --git a/scripts/classes/DieHardPf2e.js b/scripts/classes/DieHardPf2e.js new file mode 100644 index 0000000..35701da --- /dev/null +++ b/scripts/classes/DieHardPf2e.js @@ -0,0 +1,301 @@ +import {dieHardLog} from "../lib/helpers.js"; + +import DieHardSystem from "./DieHardSystem.js"; +//import DieHardFudgeD20Roll from "./DieHardFudgeD20Roll.js"; + +export default class DieHardPf2e extends DieHardSystem { + constructor() { + dieHardLog(false, 'DieHardPf2e - constructor'); + super(); + + libWrapper.register('foundry-die-hard', 'game.pf2e.Check.roll', this.wrappedCheckRoll, 'WRAPPER'); + + this.rawRollClassName = "CheckRoll" + this.fudgeWhatOptions = [] + /* + this.fudgeWhatOptions = [ + { + id: 'actorSavingThrow', + name: 'Saving Throw' + }, + { + id: 'actorSkillCheck', + name: 'Skill Check' + }, + { + id: 'actorMeleeStrike', + name: 'Melee Strike' + }, + { + id: 'actorRangedStrike', + name: 'Ranged Strike' + }, + { + id: 'actorSpellAttack', + name: 'Spell Attack' + }, + { + id: 'pf2eD20', + name: 'Any PF2e d20' + } + ] + */ + } + + + hookReady() { + dieHardLog(false, 'PF2e System Hook - Ready'); + } + + isPromise(p) { + if (typeof p === 'object' && typeof p.then === 'function') { + return true; + } + + return false; + } +/* + fudgeD20Roll(result, evaluate_options) { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll'); + // dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll - result', result); + let fudgeOperator = result.data.fudgeOperator + let fudgeOperatorValue = result.data.fudgeOperatorValue + + let gen_new_result = false; + let evalResult = this.evalFudge(result.total, fudgeOperator, fudgeOperatorValue) + if (evalResult) { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: Fudge not needed, but still wiped from actor'); + this.dmToGm('DieHard-Fudge: Fudge not needed, but still wiped from actor...'); + } else { + gen_new_result = true; + let dmMessage = "Fudge (" + result.data.fudgeHow + ") values:" + result.total; + + // This is a safety to prevent endless loops from possibly sneaking in + let SafetyLoopIndex = game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.maxFudgeAttemptsPerRoll; + while (gen_new_result && SafetyLoopIndex > 0) { + SafetyLoopIndex--; + + // ToDo: Can a "clone()" or a "reroll()" be used instead? https://foundryvtt.com/api/Roll.html#clone + const new_roll = new DieHardFudgeD20Roll( + result.formula, + result.data, { + flavor: result.options.flavor, + advantageMode: result.options.advantageMode, + defaultRollMode: result.options.defaultRollMode, + rollMode: result.options.rollMode, + critical: result.options.critical, + fumble: result.options.fumble, + targetValue: result.options.targetValue, + elvenAccuracy: result.options.elvenAccuracy, + halflingLucky: result.options.halflingLucky, + reliableTalent: result.options.reliableTalent + }); + new_roll.evaluate({async: false, minimize: evaluate_options.minimize, maximize: evaluate_options.maximize}); + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: New roll: ', new_roll) + + evalResult = this.evalFudge(new_roll.total, fudgeOperator, fudgeOperatorValue) + if (evalResult) { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: New result: ' + new_roll.total) + gen_new_result = false; + foundry.utils.mergeObject(result, new_roll); + this.dmToGm(dmMessage); + } else { + // New roll is insufficient, but lets at least check if it is "closer" + if (this.isBetterFudge(result.total, new_roll.total, fudgeOperator, fudgeOperatorValue)) { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: New result insufficient, but at least better (' + new_roll.total + "). Try again (tries left: " + SafetyLoopIndex + ")...") + foundry.utils.mergeObject(result, new_roll); + } else { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: New result insufficient (' + new_roll.total + "). Try again (tries left: " + SafetyLoopIndex + ")...") + } + dmMessage += ',' + new_roll.total; + } + } + if (SafetyLoopIndex === 0) { + dieHardLog(false, 'DieHardDnd5e - fudgeD20Roll: Tried until retry safety killed...'); + this.dmToGm('DieHard-Fudge: Gave up trying to fudge; loop safety reached...'); + } + } + + dieHardLog(false, 'Done with modify_results', result); + return result + } + + d20rollEvaluate(wrapped, evaluate_options) { + dieHardLog(false, 'DieHardDnd5e.d20rollEvaluate', this.data); + + let fudge = false; + if (this.data.fudge === true) { + evaluate_options.async = false; + + + if (this instanceof CONFIG.Dice.DieHardFudgeD20Roll) { + // This is a recursive roll; do sync + evaluate_options.async = false; + } else { + // This is a root roll, so allow fudge re-roll + fudge = true; + } + } else { + dieHardLog(false, 'DieHardDnd5e.d20rollEvaluate - No fudging planned for this roll'); + } + + let result = wrapped.call(evaluate_options) + // If a fudge re-roll is allowed + if (fudge) { + result.then(function (value) { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.fudgeD20Roll(value, evaluate_options) + }) + } + + + return result + } + */ + /** + * Generic wrapper for all PF2e Check rolls + */ + wrappedCheckRoll(wrapped, check, context, event, callback) { + dieHardLog(true, 'DieHardPf2e.wrappedCheckRoll - this', this); + dieHardLog(true, 'DieHardPf2e.wrappedCheckRoll - arguments.length', arguments.length); + dieHardLog(true, 'DieHardPf2e.wrappedCheckRoll - arguments', arguments); + + if (game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + dieHardLog(true, 'DieHardPf2e.wrappedCheckRoll - Globally disabled', game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable); + // Globally disabled + wrapped(check, context, event, callback); + return + } + + // Convert PF2e check to rollType + let rollType = 'pf2eD20' + if (check.name.indexOf('Saving Throw')) { + rollType = 'actorSavingThrow' + } else if (check.name.indexOf('Skill Check')) { + rollType = 'actorSkillCheck' + } else if (check.name.indexOf('Melee Strike')) { + rollType = 'actorMeleeStrike' + } else if (check.name.indexOf('Ranged Strike')) { + rollType = 'actorRangedStrike' + } else if (check.name.indexOf('Spell Attack')) { + rollType = 'actorSpellAttack' + } + + // Check if actor has an active fudge + let actorFudges = game.actors.get(context.actor.id).getFlag('foundry-die-hard', 'fudges'); + if (!Array.isArray(actorFudges)) { + actorFudges = [] + } + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - actorFudges', actorFudges); + let fudgeIndex = actorFudges.findIndex(element => { + return element.whatId === rollType; + }); + if (fudgeIndex !== -1 && actorFudges[fudgeIndex].statusActive) { + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - active actor fudge', actorFudges[fudgeIndex]); + foundry.utils.mergeObject(check, { + data: { + fudge: true, + fudgeOperator: actorFudges[fudgeIndex].operator, + fudgeOperatorValue: actorFudges[fudgeIndex].operatorValue, + fudgeHow: actorFudges[fudgeIndex].howFormula + } + }); + if (actorFudges[fudgeIndex].statusEndless) { + dieHardLog(false, 'DieHardSystem.wrappedRoll - fudge is endless'); + } else { + // Disable the fudge + actorFudges[fudgeIndex].statusActive = false + + // Delete the fudge from the actor + //let deletedFudge = actorFudges.splice(fudgeIndex, 1) + game.actors.get(context.actor.id).setFlag('foundry-die-hard', 'fudges', actorFudges); + // Check if still have active fudges; + game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon(); + } + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - merged check', check); + } + + // Check if user has an active fudge + let userFudges = game.users.current.getFlag('foundry-die-hard', 'fudges'); + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - userFudges', userFudges); + if (!Array.isArray(userFudges)) { + userFudges = [] + } + fudgeIndex = userFudges.findIndex(element => { + return element.whatId === rollType; + }); + if (fudgeIndex !== -1 && userFudges[fudgeIndex].statusActive) { + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - active user fudge', userFudges[fudgeIndex]); + foundry.utils.mergeObject(check, { + data: { + fudge: true, + fudgeOperator: userFudges[fudgeIndex].operator, + fudgeOperatorValue: userFudges[fudgeIndex].operatorValue, + fudgeHow: userFudges[fudgeIndex].howFormula + } + }); + if (userFudges[fudgeIndex].statusEndless) { + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - fudge is endless'); + } else { + // Disable the fudge + userFudges[fudgeIndex].statusActive = false + + // Delete the fudge from the user + // let deletedFudge = userFudges.splice(fudgeIndex, 1) + game.users.current.setFlag('foundry-die-hard', 'fudges', userFudges); + // Check if still have active fudges; + game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon(); + } + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - merged check', check); + } + let result = wrapped(check, context, event, callback); + dieHardLog(false, 'DieHardPf2e.wrappedCheckRoll - result', result); + } + +/* + actorRollSave(wrapped, skillId, options = {}) { + dieHardLog(true, 'DieHardPf2e.actorRollSave', this, arguments.length); + // game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollSkill') + wrapped(skillId, options); + } + + actorRollAttribute(wrapped, event, attributeName) { + dieHardLog(true, 'DieHardPf2e.actorRollAttribute', this, arguments.length, event, attributeName); + // game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilitySave') + wrapped(abilityId, options); + } + + d20Roll(wrapped, event, item, pars, data, template, title, speaker, flavor, onClose, dialogOptions, rollMode, rollType) { + dieHardLog(true, 'DieHardPf2e.d20Roll', this, arguments.length, event, attributeName); + // game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilitySave') + wrapped(abilityId, options); + } + + checkRoll(wrapped, check, context, event, callback) { + dieHardLog(true, 'DieHardPf2e.checkRoll - this', this); + dieHardLog(true, 'DieHardPf2e.checkRoll - arguments.length', arguments.length, check, context, event, callback); + // game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilitySave') + wrapped(check, context, event, callback); + } +*/ + /* + actorRollAbilityTest(wrapped, abilityId, options = {}) { + dieHardLog(false, 'DieHardDnd5e.actorRollAbilityTest', this); + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollAbilityTest') + wrapped(abilityId, options); + } + + actorRollDeathSave(wrapped, options = {}) { + dieHardLog(false, 'DieHardDnd5e.actorRollDeathSave', this); + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.id, 'actorRollDeathSave') + wrapped(options); + } + + entityRollAttack(wrapped, options = {}) { + dieHardLog(false, 'DieHardDnd5e.entityRollAttack', this); + game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.actor.id, 'entityRollAttack') + wrapped(options); + } + */ + +} + diff --git a/scripts/classes/DieHardSystem.js b/scripts/classes/DieHardSystem.js index 912eae6..61d28ae 100644 --- a/scripts/classes/DieHardSystem.js +++ b/scripts/classes/DieHardSystem.js @@ -1,8 +1,8 @@ import {dieHardLog} from "../lib/helpers.js"; -import {DieHardFudgeRoll} from "./DieHardFudgeRoll.js"; -import {DieHardFudgeD20Roll} from "./DieHardFudgeD20Roll.js"; +import DieHardFudgeRoll from "./DieHardFudgeRoll.js"; +import DieHardFudgeD20Roll from "./DieHardFudgeD20Roll.js"; -export class DieHardSystem{ +export default class DieHardSystem{ constructor() { dieHardLog(false, 'DieHardSystem - constructor'); @@ -12,6 +12,7 @@ export class DieHardSystem{ CONFIG.Dice.DieHardFudgeRoll = DieHardFudgeRoll; + this.rawRollClassName = "" this.fudgeWhatOptions = [] this.fudgeWhatBaseOptions = [ { @@ -77,13 +78,23 @@ export class DieHardSystem{ wrapRollEvaluate(wrapped, eval_options) { dieHardLog(false, 'DieHardSystem : wrapRollEvaluate'); - // dieHardLog(true, 'DieHardDnd5e - wrapRollEvaluate - this', this); + dieHardLog(false, 'DieHardSystem - wrapRollEvaluate - arguments', arguments); + dieHardLog(false, 'DieHardSystem - wrapRollEvaluate - this', this); + dieHardLog(false, 'DieHardSystem - wrapRollEvaluate - this.callee', this.callee); + // dieHardLog(true, 'DieHardDnd5e - wrapRollEvaluate - this.constructor.name', this.constructor.name); - // dieHardLog(true, 'DieHardDnd5e - wrapRollEvaluate - eval_options', eval_options); + dieHardLog(false, 'DieHardSystem - wrapRollEvaluate - eval_options', eval_options); //dieHardLog(true, 'DieHardDnd5e - wrapRollEvaluate - game.users.current.data.name', game.users.current.data.name); + dieHardLog(true, 'DieHardSystem - wrapRollEvaluate - this.constructor.name', this.constructor.name); + + if (game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + dieHardLog(true, 'DieHardSystem - wrapRollEvaluate - Globally disabled', game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable); + // Globally disabled + return wrapped(eval_options) + } // Check if a raw die roll (otherwise some type of system specific raw) - if (this.constructor.name === "Roll"){ + if (this.constructor.name === game.settings.get('foundry-die-hard', 'dieHardSettings').system.rawRollClassName){ dieHardLog(false, 'DieHardSystem - wrapRollEvaluate - raw roll; figure out if needs to be fudged or is a recursive fudge'); let fudge = false; @@ -95,7 +106,7 @@ export class DieHardSystem{ // dieHardLog(false, 'DieHardDnd5e - wrapRollEvaluate - die', this.dice[die]); // Check if actor has an active raw fudge - + // ToDo: something goes here... // Check if user has an active raw fudge let userFudges = game.users.current.getFlag('foundry-die-hard', 'fudges'); @@ -103,6 +114,7 @@ export class DieHardSystem{ userFudges = [] } // dieHardLog(true, 'DieHardDnd5e - wrapRollEvaluate - userFudges', userFudges); + dieHardLog(false, 'DieHardSystem.wrappedRoll - raw die faces', this.dice[die].faces); let fudgeIndex = userFudges.findIndex(element => { return element.whatId === ('rawd' + this.dice[die].faces);}); if (fudgeIndex !== -1 && userFudges[fudgeIndex].statusActive) { dieHardLog(false, 'DieHardSystem.wrappedRoll - active user raw fudge', userFudges[fudgeIndex]); @@ -257,7 +269,7 @@ export class DieHardSystem{ Return an array of all users (map of id and name), defaulting to ones currently active */ getUsers(activeOnly = true, includeFudges = false, getGM = false, userId = null) { - dieHardLog(false, 'DieHardSystem : getUsers'); + dieHardLog(false, 'DieHardSystem : getUsers', activeOnly, includeFudges, getGM, userId); if (game.settings.get('foundry-die-hard', 'dieHardSettings').debug.allActors) { activeOnly = false } @@ -321,6 +333,13 @@ export class DieHardSystem{ } async refreshActiveFudgesIcon() { + if (game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) { + document.getElementById('die-hard-pause-fudge-icon').classList.remove("die-hard-fudge-pause-icon-hidden"); + document.getElementById('die-hard-fudge-icon').classList.remove("die-hard-fudge-icon-active"); + return; + } else { + document.getElementById('die-hard-pause-fudge-icon').classList.add("die-hard-fudge-pause-icon-hidden"); + } if (this.hasActiveFudges()) { document.getElementById('die-hard-fudge-icon').classList.add("die-hard-fudge-icon-active"); } else { @@ -397,29 +416,12 @@ export class DieHardSystem{ } } - // - // disableAllFudges() { - // dieHardLog(false, 'DieHardSystem : disableAllFudges') - // let actors = game.settings.get('foundry-die-hard', 'dieHardSettings').system.getActors(); - // for (let actorIndex = 0; actorIndex < actors.length; actorIndex++) { - // try { - // let actorId = actors[actorIndex].id - // let actorFudges = game.actors.get(actorId).getFlag('foundry-die-hard', 'fudges'); - // for (let fudgeIndex = 0; fudgeIndex < actorFudges.length; fudgeIndex++) { - // actorFudges[fudgeIndex].statusActive = false; - // } - // game.actors.get(actorId).setFlag('foundry-die-hard', 'fudges', actorFudges); - // } - // catch (e) {} - // } - // let gmFudges = game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges; - // for (let fudgeIndex = 0; fudgeIndex < gmFudges.length; fudgeIndex++) { - // gmFudges[fudgeIndex].statusActive = false; - // } - // game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges = gmFudges; - // - // game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon() - // } + + disableAllFudges() { + dieHardLog(false, 'DieHardSystem : disableAllFudges', game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable) + game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable = ! game.settings.get('foundry-die-hard', 'dieHardSettings').fudgeConfig.globalDisable + game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon(); + } static registerTests = context => { dieHardLog(false, 'DieHardSystem : registerTests') diff --git a/scripts/classes/DieHardTests.js b/scripts/classes/DieHardTests.js index f65fddd..f026790 100644 --- a/scripts/classes/DieHardTests.js +++ b/scripts/classes/DieHardTests.js @@ -1,4 +1,4 @@ -import {DieHardSystem} from "./DieHardSystem.js"; +import DieHardSystem from "./DieHardSystem.js"; import {dieHardLog} from "../lib/helpers.js"; export const registerDieHardTests = quench => { diff --git a/scripts/classes/DieHardVersionNotification.js b/scripts/classes/DieHardVersionNotification.js new file mode 100644 index 0000000..4914063 --- /dev/null +++ b/scripts/classes/DieHardVersionNotification.js @@ -0,0 +1,22 @@ +/* + * Provides a mechanism to send whisper to GM when new version installed. + */ +export default class DieHardVersionNotification { + static checkVersion() { + if (game.user.isGM && game.user.getFlag('foundry-die-hard', 'versionNotification') !== game.modules.get('foundry-die-hard').data.version) { + let versionMessage = "Die Hard v0.0.5" + + "This version includes the following major changes:
To report problems: