diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ca9178..2f5482f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,4 +2,10 @@ ## v0.0.2-ALPHA.0 Jun 16, 2022 -* Initial release of Fudge for DND 5e \ No newline at end of file +* Initial release of Fudge for DND 5e + +## v0.0.3-ALPHA.0 +Jun 25, 2022 +* Major refactor of system code to support flexibility +* Adjust dialog to support new UI/UX +* TOTALLY BROKEN fudging of rolls \ No newline at end of file diff --git a/README.md b/README.md index ffa4e99..a0b4c9b 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ The way Fudge works is that the next die roll of that type for that Actor will b  +### Known Issues +* TBD ## Future Planned Functionality ### Karmic dice diff --git a/module.json b/module.json index a94dee4..7304a77 100644 --- a/module.json +++ b/module.json @@ -3,7 +3,7 @@ "title": "Die Hard", "description": "Adjustments for DND5e die rolls like fudging...", "author": "Jeremy (UranusBytes)", - "version": "0.0.2", + "version": "0.0.3", "minimumCoreVersion": "9", "compatibleCoreVersion": "9", "esmodules": [ diff --git a/scripts/Notes.txt b/scripts/Notes.txt index 1e06dd8..9250f23 100644 --- a/scripts/Notes.txt +++ b/scripts/Notes.txt @@ -28,3 +28,8 @@ game + + +Fudges are maintained as: +- For PC actors, as flags within the actor +- For GM, as Setting - scope world diff --git a/scripts/classes/DieHardConfig.js b/scripts/classes/DieHardConfig.js index b881dfa..dd2747f 100644 --- a/scripts/classes/DieHardConfig.js +++ b/scripts/classes/DieHardConfig.js @@ -45,7 +45,8 @@ export default class DieHardConfig { system: null, fudgeConfig: { maxFudgeAttemptsPerRoll: 150 - } + }, + gmFudges: [] }; if (game.system.id == 'dnd5e') { diff --git a/scripts/classes/DieHardDnd5e.js b/scripts/classes/DieHardDnd5e.js index 8b41da0..e917ed9 100644 --- a/scripts/classes/DieHardDnd5e.js +++ b/scripts/classes/DieHardDnd5e.js @@ -55,17 +55,6 @@ export class DieHardDnd5e extends DieHardSystem{ dieHardLog(false, 'Dnd 5e System Hook - Ready'); } - getFudgeActors() { - dieHardLog(false, 'DieHardDnd5e - getFudgeActors'); - let whoActors = [] - for (let actorId of game.actors.keys()) { - let curActor = game.actors.get(actorId); - if(curActor.data.type === 'character') { - whoActors.push({id: actorId, name: curActor.name}) - } - } - return whoActors; - } getFudgeWhatOptions() { return this.fudgeWhatOptions; @@ -188,6 +177,8 @@ export class DieHardDnd5e extends DieHardSystem{ // Delete the fudge from the actor let deletedFudge = actorFudges.splice(fudgeIndex,1) game.actors.get(actorId).setFlag('foundry-die-hard', 'activeFudges', actorFudges); + // Check if still have active fudges; + this.refreshActiveFudgesIcon(); } } @@ -220,5 +211,7 @@ export class DieHardDnd5e extends DieHardSystem{ game.settings.get('foundry-die-hard', 'dieHardSettings').system.wrappedRoll(options, this.actor.id, 'entityRollAttack') wrapped(options); } + + } diff --git a/scripts/classes/DieHardFudgeDialog.js b/scripts/classes/DieHardFudgeDialog.js index 2d64e4f..30a8a78 100644 --- a/scripts/classes/DieHardFudgeDialog.js +++ b/scripts/classes/DieHardFudgeDialog.js @@ -9,7 +9,7 @@ export class DieHardFudgeDialog extends FormApplication { submitOnClose: true, popOut: true, editable: game.user.isGM, - width: 500, + width: 1000, template: 'modules/foundry-die-hard/templates/die-hard-fudge-config.html', id: 'die-hard-fudge-config', title: 'Die Hard Fudge Config', @@ -19,49 +19,26 @@ export class DieHardFudgeDialog extends FormApplication { constructor() { dieHardLog(false, 'DieHardFudgeDialog - constructor') super(); - this.pendingWho = null; - this.pendingWhat = null; - this.pendingHow = null; this.operator = null; this.operatorValue = null; + Hooks.once('closeApplication', (app, html) => { + if (app.id === 'die-hard-fudge-config') { + game.settings.get('foundry-die-hard', 'dieHardSettings').system.refreshActiveFudgesIcon() + } + + }) } getData() { dieHardLog(false, 'DieHardFudgeDialog - getData') let dialogData = { - whoActors: game.settings.get('foundry-die-hard', 'dieHardSettings').system.getFudgeActors(), + whoActors: game.settings.get('foundry-die-hard', 'dieHardSettings').system.getActors(), whatOptions: game.settings.get('foundry-die-hard', 'dieHardSettings').system.getFudgeWhatOptions(), - activeFudge: this.getAllActiveFudges() - + actorFudges: game.settings.get('foundry-die-hard', 'dieHardSettings').system.getAllFudges(), }; return dialogData; } - getAllActiveFudges() { - let activeFudges = []; - let whatOptions = game.settings.get('foundry-die-hard', 'dieHardSettings').system.getFudgeWhatOptions() - let actors = game.settings.get('foundry-die-hard', 'dieHardSettings').system.getFudgeActors(); - for (let actorIndex = 0; actorIndex < actors.length; actorIndex++) { - try { - let actor = actors[actorIndex]; - let actorFudges = game.actors.get(actor.id).getFlag('foundry-die-hard', 'activeFudges'); - for (let fudgeIndex = 0; fudgeIndex < actorFudges.length; fudgeIndex++) { - activeFudges.push({ - id: actorFudges[fudgeIndex].id, - who: actor.id, - whoName: actor.name, - what: actorFudges[fudgeIndex].what, - whatName: whatOptions.find(element => element.id === actorFudges[fudgeIndex].what).name, - how: actorFudges[fudgeIndex].how - }) - } - } - catch (e) {} - } - dieHardLog(false, 'DieHardFudgeDialog - getAllActiveFudges', activeFudges) - return activeFudges; - } - _uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); @@ -128,77 +105,148 @@ export class DieHardFudgeDialog extends FormApplication { }; }; + _isFormError(event, formData) { + let formError = false; + let fudgeWhoHeader = document.getElementById('fudgeWhoHeader'); + let fudgeWhatHeader = document.getElementById('fudgeWhatHeader'); + let fudgeHowHeader = document.getElementById('fudgeHowHeader'); - async _updateObject(event, formData) { - dieHardLog(false, 'DieHardFudgeDialog : _updateObject') - - if (formData.draftFudgeWho != null) { - this.pendingWho = formData.draftFudgeWho; - } - if (formData.draftFudgeWhat != null) { - this.pendingWhat = formData.draftFudgeWhat; - } - if (formData.draftFudgeFormula != null) { + if (formData.fudgeFormula !== '') { //validate the formula - this.pendingHow = formData.draftFudgeFormula; - let parsedHow = this._parseFormula(formData.draftFudgeFormula) - if (formData.draftFudgeFormula === '') { - // Do nothing - } - else if (parsedHow === undefined) { - document.getElementById('draftFudgeFormula').style.backgroundColor = "#ff6961" - return; + let parsedHow = this._parseFormula(formData.fudgeFormula) + if (parsedHow === undefined) { + document.getElementById('fudgeFormula').style.backgroundColor = "#ff6961"; + fudgeHowHeader.classList.remove("die-hard-form-error"); + // Hack from here to reset animation- https://css-tricks.com/restart-css-animation/ + fudgeHowHeader.offsetWidth; + fudgeHowHeader.classList.add("die-hard-form-error"); + this.pendingHowOperator = null; + this.pendingHowOperatorValue = null; + formError = true; } else { - document.getElementById('draftFudgeFormula').style.backgroundColor = "" - this.pendingHow = parsedHow.how; + document.getElementById('fudgeFormula').style.backgroundColor = "initial"; + fudgeHowHeader.classList.remove("die-hard-form-error"); this.pendingHowOperator = parsedHow.operator; this.pendingHowOperatorValue = parsedHow.operatorValue; - document.getElementById('draftFudgeFormula').value = this.pendingHow; + document.getElementById('fudgeFormula').value = parsedHow.how; + } + } else { + document.getElementById('fudgeFormula').style.backgroundColor = "initial"; + } + if (formData.fudgeTimes !== '') { + //validate the fudge times + if(! Number.isInteger(Number.parseInt(formData.fudgeTimes))) { + document.getElementById('fudgeTimes').style.backgroundColor = "#ff6961"; + fudgeHowHeader.classList.remove("die-hard-form-error"); + // Hack from here to reset animation - https://css-tricks.com/restart-css-animation/ + fudgeHowHeader.offsetWidth; + fudgeHowHeader.classList.add("die-hard-form-error"); + formError = true; } + } else { + document.getElementById('fudgeTimes').style.backgroundColor = "initial"; } if (event.submitter?.name === 'create') { - dieHardLog(false, 'DieHardFudgeDialog : Create fudge for ' + this.pendingWho) + // Validate who and what is selected + if (formData.fudgeWho == null || formData.fudgeWho.length === 0) { + fudgeWhoHeader.classList.remove("die-hard-form-error"); + // Hack from here to reset animation - https://css-tricks.com/restart-css-animation/ + fudgeWhoHeader.offsetWidth; + fudgeWhoHeader.classList.add("die-hard-form-error"); + formError = true; + } else { + fudgeWhoHeader.classList.remove("die-hard-form-error"); + } - let actorFudges = game.actors.get(this.pendingWho).getFlag('foundry-die-hard', 'activeFudges'); - if (typeof actorFudges === 'undefined') { - actorFudges = []; + if (formData.fudgeWhat == null) { + fudgeWhatHeader.classList.remove("die-hard-form-error"); + // Hack from here to reset animation - https://css-tricks.com/restart-css-animation/ + fudgeWhatHeader.offsetWidth; + fudgeWhatHeader.classList.add("die-hard-form-error"); + formError = true; + } else { + fudgeWhatHeader.classList.remove("die-hard-form-error"); } - actorFudges.push({ - id: this._uuidv4(), - what: this.pendingWhat, - how: this.pendingHow, - operator: this.pendingHowOperator, - operatorValue: this.pendingHowOperatorValue - } - ) - game.actors.get(this.pendingWho).setFlag('foundry-die-hard', 'activeFudges', actorFudges); + if (this.pendingHowOperator == null) { + fudgeHowHeader.classList.remove("die-hard-form-error"); + // Hack from here to reset animation - https://css-tricks.com/restart-css-animation/ + fudgeHowHeader.offsetWidth; + fudgeHowHeader.classList.add("die-hard-form-error"); + formError = true; + } else { + fudgeHowHeader.classList.remove("die-hard-form-error"); + } - this.pendingWho = null; - this.pendingWhat = null; - this.pendingHow = null; - this.operator = null; - this.operatorValue = null; + } + return formError + } - formData.draftFudgeWho = null; - formData.draftFudgeWhat = null; - formData.draftFudgeFormula = null; - console.log('activeFudges', this.getAllActiveFudges()) - this.render(true) - return; + async _updateObject(event, formData) { + dieHardLog(false, 'DieHardFudgeDialog : _updateObject') + + // If any form errors, stop + if (this._isFormError(event, formData)) { + return } - if (event.submitter?.name === 'cancel') { + if (event.submitter?.name === 'create') { + dieHardLog(false, 'DieHardFudgeDialog : Create Fudge'); + + for (let actorIndex = 0; actorIndex < formData.fudgeWho.length; actorIndex++) { + let actorId = formData.fudgeWho[actorIndex]; + let actorName = ""; + let actorFudges = null; + if (actorId === 'gameMaster') { + actorFudges = game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges; + actorName = "Game Master" + } else { + let actor = game.actors.get(actorId); + actorFudges = actor.getFlag('foundry-die-hard', 'actorFudges'); + actorName = actor.name + } + + let whatOptions = game.settings.get('foundry-die-hard', 'dieHardSettings').system.getFudgeWhatOptions(); + if (typeof actorFudges === 'undefined') { + actorFudges = []; + } + let fudgeTimes = 1; + if (Number.isInteger(Number.parseInt(formData.fudgeTimes))) { + fudgeTimes = Number.parseInt(formData.fudgeTimes); + } + + let whatName = whatOptions.find(element => element.id === formData.fudgeWhat).name; + for (let loopIndex = 0; loopIndex < fudgeTimes; loopIndex++) { + actorFudges.push({ + id: this._uuidv4(), + who: actorId, + whoName: actorName, + what: formData.fudgeWhat, + whatName: whatName, + statusActive: true, + how: formData.fudgeFormula, + operator: this.pendingHowOperator, + operatorValue: this.pendingHowOperatorValue + } + ) + } + if (actorId === 'gameMaster') { + game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges = actorFudges; + } else { + game.actors.get(actorId).setFlag('foundry-die-hard', 'actorFudges', actorFudges); + } + this.pendingHowOperator = null; + this.pendingHowOperatorValue = null; + } + this.render(true) + } else if (event.submitter?.name === 'cancel') { dieHardLog(false, 'DieHardFudgeDialog : Cancel fudge') - this.pendingWho = null; - this.pendingWhat = null; - this.pendingHow = null; - this.operator = null; - this.operatorValue = null; + this.pendingHowOperator = null; + this.pendingHowOperatorValue = null; + this.close(); - return; } } @@ -206,20 +254,61 @@ export class DieHardFudgeDialog extends FormApplication { dieHardLog(false, 'DieHardFudgeDialog : deleteFudge', event) event.preventDefault(); - let actorFudges = game.actors.get(event.currentTarget.dataset.actor).getFlag('foundry-die-hard', 'activeFudges'); + let actorId = event.currentTarget.dataset.actor; + let actorFudges = null + if (actorId === 'gameMaster') { + actorFudges = game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges; + } else { + actorFudges = game.actors.get(actorId).getFlag('foundry-die-hard', 'actorFudges'); + } let fudgeIndex = actorFudges.findIndex(element => { return element.id === event.currentTarget.dataset.fudge;}); let deletedFudge = actorFudges.splice(fudgeIndex,1) - game.actors.get(event.currentTarget.dataset.actor).setFlag('foundry-die-hard', 'activeFudges', actorFudges); + if (actorId === 'gameMaster') { + game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges = actorFudges + } else { + game.actors.get(event.currentTarget.dataset.actor).setFlag('foundry-die-hard', 'actorFudges', actorFudges); + } + this.render() + } + + _toggleFudge(event) { + dieHardLog(false, 'DieHardFudgeDialog : _toggleFudge', event) + dieHardLog(false, 'DieHardFudgeDialog : _toggleFudge dataset', event.currentTarget.dataset) + + event.preventDefault(); + let actorId = event.currentTarget.dataset.actor; + let actorFudges = null + if (actorId === 'gameMaster') { + actorFudges = game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges; + } else { + actorFudges = game.actors.get(actorId).getFlag('foundry-die-hard', 'actorFudges'); + } + let fudgeIndex = actorFudges.findIndex(element => { return element.id === event.currentTarget.dataset.fudge;}); + actorFudges[fudgeIndex].statusActive = !actorFudges[fudgeIndex].statusActive + if (actorId === 'gameMaster') { + game.settings.get('foundry-die-hard', 'dieHardSettings').gmFudges = actorFudges + } else { + game.actors.get(event.currentTarget.dataset.actor).setFlag('foundry-die-hard', 'actorFudges', actorFudges); + } this.render() } _helpFudge(event) { - // ToDo: build this out + Dialog.prompt({ + title: "Fudge Help", + content: "
Operators:
" + + "