asacolips-projects / pbta

Run games for any PbtA system in Foundry VTT!
https://asacolips.gitbook.io/pbta-system
MIT License
3 stars 7 forks source link

options.stat empty on dialogRolls (esp. data.rollType=="ask") #208

Closed fe5hua closed 5 months ago

fe5hua commented 5 months ago

Hi, how would I go about checking debility on data.rollType === "ask" where options.stat === "". I am trying to automatically handle debilities as disadvantages when rolling:

Hooks.once("ready", async () => {
  if (!game.user.isGM) return;
  // Override the default rollPbtA function to handle Disadvantage on debilities.
  CONFIG.Dice.RollPbtA = new Proxy(CONFIG.Dice.RollPbtA, {
    construct: (target, args, newTarget) => {
      const [_, data, options] = args;
      const stat = options.stat;
      // TODO: check for debilities on data.rollType === "ask"
      // options.stat is empty
      const debility = data.stats[stat]?.toggle;
      if (debility) options.rollMode = "dis";
      return Reflect.construct(
        target,
        [...args.slice(0, -1), options],
        newTarget,
      );
    },
  });
});

This works for normal rolls but not with any type of dialog.

Thanks, hope this is the right place to ask.

mclemente commented 5 months ago

I've recently changed the logic to fix an issue with advantage/disadvantage. I've done it for Advantage and forgot to copy the fix for the Ask roll type to the Disadvantage getter.

With version 1.0.3 you'll be able to tell by just calling this.hasDisadvantage (or this.checkAdvantageDisadvantage("div") if you want to override it), so I'm not sure if your wrapping will be required.

Not gonna lie, RollPbtA's code is a bit messy and I'm sorry about that. The latest major release solved some of its issues, but it still has some room for improvements.

mclemente commented 5 months ago

https://github.com/asacolips-projects/pbta/commit/d098c6749919ccc06beee103a70549e3c721d7f4

fe5hua commented 5 months ago

thanks alot. But to be honest I am still a bit puzzled about how to use these functions. I am quite new to Foundry (but not JS). It would be awesome if you could point me in the right direction and maybe give an example on how to check each roll for a debility on the selected stat and set a disadvantage accordingly. Currently the check is called as soon as I initiate the click on the sheet, before the ask dialog.

mclemente commented 5 months ago

I'm not 100% sure what you mean by "set a disadvantage accordingly", if you want to set a string to be displayed instead of PbtA's "Disadvantage", you probably want to override RollPbtA#configureModifiers to add the condition you want, like this

configureModifiers() {
    const r = this.terms[0];

    if (this.hasAdvantage) {
        // ...
    } else if (this.hasDisadvantage) {
        r.modifiers.push(`kl${r.number}`);
        r.number += 1; // maybe change this
        r.options.disadvantage = true;
        this.options.conditions.push("CHANGE ME HERE");
    }

    this._formula = this.constructor.getFormula(this.terms);

    // ...
}

Also, don't override the constructor if it's just for that, it should be redundant now as long as you're either rolling with Disadvantage or the Stat Toggle's modifier is "dis".


I'm not familiar with Proxies in JS (if you're used to it, that's fine), but you could just subclass pbta.dice.RollPbtA and do this instead:

CONFIG.Dice.RollPbtA = MyOwnRollClass;
CONFIG.Dice.rolls.push(MyOwnRollClass);

It can be done as early as the init hook. The timing shouldn't matter for your case, though.

fe5hua commented 5 months ago

I am basically just tying to setup a pbta system where debilities are not handled by changing the stat value by some modifier (eg -1) but by giving players a disadvantage on the roll (eg 2d6 + 2 --> 3d6kl2 + 2).

the Stat Toggle's modifier is "dis".

I guess I am looking for statToggle.modifier: "dis" but that isn't working.

mclemente commented 5 months ago

All you need is this on the TOML:

[statToggle]
  label = "Foo"
  modifier = "dis"
fe5hua commented 5 months ago

I tried this: (using js object instead of toml file in custom module)

game.pbta.sheetConfig = {
    ...,
    statToggle: {
      label: game.i18n.localize("PBTA.Disadvantage"),
      modifier: "dis",
    },
...
}

but it gives error:

foundry-esm.js:62864
Uncaught (in promise) SyntaxError: Expected [%*/], [+\-], end of input, or whitespace but "d" found.
    at new peg$SyntaxError (foundry-esm.js:62864:22)
    at peg$buildStructuredError (foundry-esm.js:63239:14)
    at Object.peg$parse [as parse] (foundry-esm.js:64213:13)
    at RollPbtA.parse (foundry-esm.js:62442:45)
    at new Roll (foundry-esm.js:61789:37)
    at new RollPbtA (rolls.js:1:16)
    at ItemPbta.roll (item.js:72:14)
    at ActorPbta._onRoll (actor.js:175:9)
    at PbtaActorSheet._onRollable (actor-sheet.js:662:14)
    at HTMLSpanElement.dispatch (jquery.min.js:2:40035)
mclemente commented 5 months ago

I can't reproduce this error, what is the formula you're using?

fe5hua commented 5 months ago

I'm on Foundry v12.325, with pbta v1.0.5 getting the mentioned error on moves that specify a stat to roll. Direct stat rolls (without moves) and the ask dialog (move) actually work. I use the following code in custom module:

Hooks.once("pbtaSheetConfig", () => {
  if (!game.user.isGM) return;
  game.settings.set("pbta", "sheetConfigOverride", true);
  game.pbta.sheetConfig = {
    rollFormula: "2d6",
    statToggle: {
      label: game.i18n.localize("brein.character.debility"),
      modifier: "dis",
    },
    rollResults: {...},
    actorTypes: {...}
  }
}
mclemente commented 5 months ago

Ah, I see. Just pushed a fix to it, version 1.0.6 should run fine now.

fe5hua commented 5 months ago

thanks alot. especially for your patients with me figuring what the problem actually is.

Edit: Sry, should have checked first. It seems that now the error is gone, but the roll still does not use the toggled disadvantage