Skip to content

Commit

Permalink
Remove GoDice, add modifier support
Browse files Browse the repository at this point in the history
  • Loading branch information
cswendrowski committed May 25, 2023
1 parent 0d8c564 commit 726c9e7
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 296 deletions.
207 changes: 0 additions & 207 deletions apps/godice-resolver.js

This file was deleted.

24 changes: 15 additions & 9 deletions scripts/FulfillableRoll.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import FulfillableRollTerm from "./FulfillableRollTerm.mjs";
import GodiceResolver from "../apps/godice-resolver.js";
import ManualResolver from "../apps/manual-resolver.js";

export class FulfillableRoll extends Roll {
Expand Down Expand Up @@ -45,9 +44,8 @@ export class FulfillableRoll extends Roll {
this.terms = FulfillableRoll.simplifyTerms(this.terms, validating);

// Step 3 - Determine what terms need to be fulfilled

const config = game.settings.get("unfulfilled-rolls", "diceSettings");
console.dir(this.terms);
//console.dir(this.terms);
const toFulfill = this.terms.reduce( (array, term) => {
const dieSize = `d${term.faces}`;
const fulfillmentMethod = config[dieSize] || "fvtt";
Expand All @@ -67,31 +65,28 @@ export class FulfillableRoll extends Roll {
// Display a dialog if there are terms to fulfill
let fulfilled = null;
if ( toFulfill.length ) {
console.dir(this, toFulfill);
//console.dir(this, toFulfill);
const promise = new Promise(resolve => {

// If any of the terms are bluetooth, grab the current bluetooth resolver. Otherwise, grab the manualResolver
const needsBluetooth = toFulfill.some(term => term.fulfillmentMethod === "bluetooth");
const config = game.settings.get("unfulfilled-rolls", "diceSettings");
const bluetoothResolver = CONFIG.Dice.BluetoothDieProviders[config.bluetoothDieProvider].app;
const resolverApp = needsBluetooth ? bluetoothResolver : ManualResolver;

const resolver = new resolverApp(toFulfill, this, (data) => {
resolve(data);
});
resolver.render(true);
});
fulfilled = await promise;
console.dir(fulfilled);
//console.dir(fulfilled);
}

// Step 4 - Evaluate the final expression
for ( let term of this.terms ) {
if ( !term._evaluated ) await term.evaluate(
{minimize, maximize, async: true, fulfilled: fulfilled});
}

// Step 4 - Evaluate the final expression
this._total = this._evaluateTotal();
return this;
}
Expand Down Expand Up @@ -136,7 +131,18 @@ export class FulfillableRoll extends Roll {
// For any terms of type Die, see if we should replace them with a FulfillableRollTerm
for ( let [i, t] of result.entries() ) {
if ( t.faces ) {
result[i] = new FulfillableRollTerm({faces: t.faces, number: t.number});
result[i] = new FulfillableRollTerm({
number: t.number,
faces: t.faces,
modifiers: t.modifiers,
results: t.results,
options: t.options
});

result[i].MODIFIERS = Object.entries(t.constructor.MODIFIERS).reduce((obj, entry) => {
obj[entry[0]] = t[entry[1]];
return obj;
}, {});
}
}
return result;
Expand Down
94 changes: 64 additions & 30 deletions scripts/FulfillableRollTerm.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export default class FulfillableRollTerm extends DiceTerm {

MODIFIERS = {};

/* -------------------------------------------- */

evaluate({minimize=false, maximize=false, async=false, fulfilled=null}={}) {
if ( this._evaluated ) {
throw new Error(`The ${this.constructor.name} has already been evaluated and is now immutable`);
Expand Down Expand Up @@ -33,7 +37,7 @@ export default class FulfillableRollTerm extends DiceTerm {
const id = `d${this.faces}-${n}`;
if ( fulfilled && fulfilled.has(id) ) {
const result = fulfilled.get(id);
roll.result = result;
roll.result = Number.parseInt(result);
}
else {
roll.result = await this._fulfillRoll();
Expand All @@ -46,35 +50,7 @@ export default class FulfillableRollTerm extends DiceTerm {
/* -------------------------------------------- */

async _fulfillRoll() {
//if ( this._fromData ) return;
console.log("FulfillableRollTerm._fulfillRoll");
const config = game.settings.get("unfulfilled-rolls", "diceSettings");

const dieSize = `d${this.faces}`;
const fulfillmentMethod = config[dieSize] || "fvtt";
console.log(`Fulfillment method for ${dieSize}: ${fulfillmentMethod}`);

// if (fulfillmentMethod === "input") {
//
// const result = await Dialog.prompt({
// title: `${dieSize} roll`,
// content: `<p>Enter the result of the roll. Number should be between 1 and ${this.faces}</p>
// <input type="number" name="result" min="1" max="${this.faces}" value="${Math.ceil(CONFIG.Dice.randomUniform() * this.faces)}">
// <p>Press OK to submit the roll, or Cancel to cancel the roll.</p>`,
// label: "Roll",
// callback: html => html.find('[name="result"]').val()
// });
// if (result) {
// return parseInt(result);
// }
//
// // const result = prompt(`Enter the result of the ${dieSize} roll`, this.faces);
// // if (result) {
// // return parseInt(result);
// // }
// }

// Default to the original FVTT roller
// This term was not already fulfilled, so use the original FVTT roller
return Math.ceil(CONFIG.Dice.randomUniform() * this.faces);
}

Expand All @@ -86,4 +62,62 @@ export default class FulfillableRollTerm extends DiceTerm {
term._fromData = true;
return term;
}

/* -------------------------------------------- */

/**
* Sequentially evaluate each dice roll modifier by passing the term to its evaluation function
* Augment or modify the results array.
* @private
*/
_evaluateModifiers() {
const requested = foundry.utils.deepClone(this.modifiers);
this.modifiers = [];

// Iterate over requested modifiers
for ( let m of requested ) {
let command = m.match(/[A-z]+/)[0].toLowerCase();

// Matched command
if ( command in this.MODIFIERS ) {
this._evaluateModifier(command, m);
continue;
}

// Unmatched compound command
// Sort modifiers from longest to shortest to ensure that the matching algorithm greedily matches the longest
// prefixes first.
const modifiers = Object.keys(this.MODIFIERS).sort((a, b) => b.length - a.length);
while ( !!command ) {
let matched = false;
for ( let cmd of modifiers ) {
if ( command.startsWith(cmd) ) {
matched = true;
this._evaluateModifier(cmd, cmd);
command = command.replace(cmd, "");
break;
}
}
if ( !matched ) command = "";
}
}
}

/* -------------------------------------------- */

/**
* Evaluate a single modifier command, recording it in the array of evaluated modifiers
* @param {string} command The parsed modifier command
* @param {string} modifier The full modifier request
* @private
*/
_evaluateModifier(command, modifier) {
let fn = this.MODIFIERS[command];
if ( typeof fn === "string" ) fn = this[fn];
if ( fn instanceof Function ) {
const result = fn.call(this, modifier);
const earlyReturn = (result === false) || (result === this); // handling this is backwards compatibility
if ( !earlyReturn ) this.modifiers.push(modifier.toLowerCase());
}
}
}
Loading

0 comments on commit 726c9e7

Please sign in to comment.