flamewave000 / dragonflagon-fvtt

DragonFlagon FoundryVTT Modules
BSD 3-Clause "New" or "Revised" License
64 stars 59 forks source link

DF Manual Rolls: API to Temporarily Disable Manual Rolls #441

Closed KelSolaar closed 1 year ago

KelSolaar commented 1 year ago

Is your feature request related to a problem? Please describe. Manual Rolls is triggered by some of my functions and I would need a way to temporarily disable it.

Describe the solution you'd like The ManualRolls class has an override here: https://github.com/flamewave000/dragonflagon-fvtt/blob/master/df-manual-rolls/src/ManualRolls.ts#L24 but I'm not sure how to change it from the game.

Describe alternatives you've considered (Optional) N/A

Additional context (Optional) N/A

flamewave000 commented 1 year ago

That boolean is an unfortunate hack that was needed to better support Pathfinder v1, so it is not accessible.

Are you working on a Macro or a module? Either way, you could spoof it a little by doing a fast change of the module settings, but you would have to await the setting change promise.

This snippet will safely disable DFMR and then invoke the provided roll function. It will attempt to await the your roll function before continuing to restore the DFMR.

async function performNonManualRoll<T>(performRoll: () => Promise<T> | void): Promise<T | void> {
    // Safely disable the manual rolls module if it is enabled
    const pcState = game.settings.get("df-manual-rolls", "pc");
    if (pcState !== "disabled")
        await game.settings.set("df-manual-rolls", "gm", "disabled");
    let gmState = null;
    if (game.user.isGM) {
        gmState = game.settings.get("df-manual-rolls", "gm");
        if (gmState !== "disabled")
            await game.settings.set("df-manual-rolls", "pc", "disabled");
    }
    const result = await performRoll();
    await new Roll("2d20kh").evaluate({async: true});
    // Restore the manual rolls module to its original state
    if (pcState !== "disabled")
        await game.settings.set("df-manual-rolls", "gm", pcState);
    if (gmState !== null)
        await game.settings.set("df-manual-rolls", "pc", gmState);
    return result;
}

It can be used as follows:

// Inline roll statement
let myResult = await performNonManualRoll(() => new Roll("2d20kh").evaluate({async: true}));

// External roll and result
const myRoll = new Roll("2d20kh");
await performNonManualRoll(async () => {
    myResult = await myRoll.evaluate({async: true});
});

I don't plan on adding a disabling API as a module might disable it temporarily but not restore it. This way the actual settings are being changed which a user can easily fix if something goes wrong. Whereas a hidden boolean would require the user to refresh the page in order to fix that.

KelSolaar commented 1 year ago

Hi @flamewave000,

Are you working on a Macro or a module?

A module so to keep things clean and tidy I would have been keen to keep the boiler plate code to manage ThirdParty modules to the minimum. I considered using settings but wanted to ask for the API first (because as your example shows, it is quite a bit intrusive).

Cheers,

Thomas