kakaroto / Beyond20

D&D Beyond Character Sheet Integration in Roll20
GNU General Public License v3.0
497 stars 145 forks source link

Chromatic Orb difficult to cast with advantage / disadvantage #1022

Closed matthewbstroud closed 2 years ago

matthewbstroud commented 2 years ago

Describe the bug Trying cast chromatic orb with advantage launches a damage type dialog, which doesn't automatically honor the advantage/disadvantage modifier.

To Reproduce Steps to reproduce the behavior:

  1. Have Chromatic Orb in your spell list
  2. Hold down shift and click the attack roll. image
  3. A popup will show asking for damage type.
    image
  4. Choose a damage type and click okay.
  5. A single d20 will roll.

Expected behavior You should only be prompted for a damage type when rolling damage for chromatic orb, since if you miss the damage is meaningless. Or Clicking the attack roll should honor the advantage/disadvantage modifiers.

Workaround Holding shift when you click the Roll button in the dialog does make the advantage roll work.

Browser Info (please complete the following information):

Errors image

kakaroto commented 2 years ago

Nice find, thanks for the report. The popup dialog is definitely interfering here!

Aeristoka commented 2 years ago

To clarify, no, it should absolutely do the dialogue to specify damage here, since it's going to give you the "Roll Damages" button, as it does when you use DnDBeyond Digital Dice. If it didn't do it here, we've lost the easy facility to do that.

Yes, it absolutely should respect advantage all the way through.

the utils.ts error is unrelated to Beyond20.

matthewbstroud commented 2 years ago

image

Aeristoka commented 2 years ago

image

Context of what you were doing when you saw this?

matthewbstroud commented 2 years ago

Clicking on the Chromatic Org to Hit button over and over.

matthewbstroud commented 2 years ago

so, this seems to fix the issue

async function buildAttackRoll(character, attack_source, name, description, properties,
                         damages = [], damage_types = [], to_hit = null,
                         brutal = 0, force_to_hit_only = false, force_damages_only = false, {weapon_damage_length=0}={}) {
    const roll_properties = {
        "name": name,
        "attack-source": attack_source,
        "description": description,
        "rollAttack": force_to_hit_only || !force_damages_only,
        "rollDamage": force_damages_only || (!force_to_hit_only && character.getGlobalSetting("auto-roll-damage", true)),
        "rollCritical": false
    }
    // store the key modifier in the request prior to launching any dialog
    if (key_modifiers.advantage)
        roll_properties["advantage"] = RollType.ADVANTAGE;
    else if (key_modifiers.disadvantage)
        roll_properties["advantage"] = RollType.DISADVANTAGE;
    if (key_modifiers.super_advantage)
        roll_properties["advantage"] = RollType.SUPER_ADVANTAGE;
    else if (key_modifiers.super_disadvantage)
        roll_properties["advantage"] = RollType.SUPER_DISADVANTAGE;
    else if (key_modifiers.normal_roll)
        roll_properties["advantage"] = RollType.NORMAL;

async function sendRoll(character, rollType, fallback, args) {
    let whisper = parseInt(character.getGlobalSetting("whisper-type", WhisperType.NO));
    const whisper_monster = parseInt(character.getGlobalSetting("whisper-type-monsters", WhisperType.YES));
    let is_monster = character.type() == "Monster" || character.type() == "Vehicle";
    if (is_monster && whisper_monster != WhisperType.NO)
        whisper = whisper_monster;
    // Let the spell card display appear uncensored
    if (rollType === "spell-card" && whisper === WhisperType.HIDE_NAMES)
        whisper = WhisperType.NO;

    advantage = parseInt(character.getGlobalSetting("roll-type", RollType.NORMAL));
    if (args["advantage"] == RollType.OVERRIDE_ADVANTAGE)
        args["advantage"] = advantage == RollType.SUPER_ADVANTAGE ? RollType.SUPER_ADVANTAGE : RollType.ADVANTAGE;
    if (args["advantage"] == RollType.OVERRIDE_DISADVANTAGE)
        args["advantage"] = advantage == RollType.SUPER_DISADVANTAGE ? RollType.SUPER_DISADVANTAGE : RollType.DISADVANTAGE;

    // Default advantage/whisper would get overriden if (they are part of provided args;
    const req = {
        action: "roll",
        character: character.getDict(),
        type: rollType,
        roll: cleanRoll(fallback),
        advantage: advantage,
        whisper: whisper
    }
    for (let key in args)
        req[key] = args[key];
    // if advantage has already been set, use the value
    if (args["advantage"]) {
        req["advantage"] = args["advantage"];
    } else if (key_modifiers.advantage)
        req["advantage"] = RollType.ADVANTAGE;
    else if (key_modifiers.disadvantage)
        req["advantage"] = RollType.DISADVANTAGE;
    if (key_modifiers.super_advantage)
        req["advantage"] = RollType.SUPER_ADVANTAGE;
    else if (key_modifiers.super_disadvantage)
        req["advantage"] = RollType.SUPER_DISADVANTAGE;
    else if (key_modifiers.normal_roll)
        req["advantage"] = RollType.NORMAL;
Aeristoka commented 2 years ago

Would help more to submit a Pull Request.

matthewbstroud commented 2 years ago

Okay, let me see if i can figure out how to do that.
The issue is a race condition.

The solution is to store the key modifiers in roll_properties prior to launching the dialog.

matthewbstroud commented 2 years ago

image I do not have access to make a PR

Aeristoka commented 2 years ago

You absolutely do. You fork the Repo, make the branch on your fork, then submit it as a PR.

matthewbstroud commented 2 years ago

Okay, give me a minute.

matthewbstroud commented 2 years ago

@Aeristoka for the PR, should it be to a branch or main?

Aeristoka commented 2 years ago

I personally ALWAYS do a branch, and keep my Main synced with upstream. It's a lot cleaner.

matthewbstroud commented 2 years ago

https://github.com/kakaroto/Beyond20/pull/1023/files

matthewbstroud commented 2 years ago

My fix just solves a race condition, but it fails the principle of DRY. I could move the logic to get the advantage from key_modifiers into its own function, but I wanted to see if I was even in the ballpark.

matthewbstroud commented 2 years ago

@Aeristoka thanks for the help, this is my first time forking something.