Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[Script] 5e Alternate Exhaustion

January 07 (1 year ago)

Edited January 08 (1 year ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

The upcoming version of D&D is likely to institute a popular alternative to the standard exhaustion rules.  Each level of exhaustion simply subtracts -1 from all d20 rolls. There are other proposed penalties, such as a -1 to spell save DC and -5 ft. of movement, but the d20 test is all this script addresses. The other stuff is more messy to implement on the D&D 5th Edition by Roll20 Sheet.

Every time you change the exhaustion level on a PC, it will modify the core die roll to add an exhaustion penalty. Changing the exhaustion level to 0 will remove all modifications and restore the core roll to "1d20". The script recognizes changes made by ChatSetAttr

There are some limitations:

  • This only affects the core 1d20 roll used for attacks, ability checks and saving throws. Movement, spell DC or other proposed changes are not covered.
  • It only affects the first roll. If you have always roll advantage turned on, the second roll does not suffer the penalty. I can't do anything about this, that second roll is created by the roll template as far as I can tell
  • This script only manages PCs and unique NPCs. NPCs use a statblock that has no visible for exhaustion. You can set it on an NPC using the ChatSetAttr script, but keep in mind that if you have one sheet representing multiple creatures (ex. a horde of goblins), ALL tokens represented by that sheet will share exhaustion level. The script is best used on PCs, or NPC statblocks that only represent a unique creature.
  • Toggle the sheet setting that allows for exhaustion tracking. This allows players to easily track their own exhaustion. They can ignore the standard exhaustion listing on the sheet if you use this script.


The Code:

on('ready', () => {

const registerWithCSA = () => {
    setTimeout(() => {
        if (typeof(ChatSetAttr) === 'object') {
            ChatSetAttr.registerObserver('change', onChangeAttribute);
        }
        else {
            // notify GM that CSA changes won't work
        }
    }, 100);
}

registerWithCSA();



    function setExhaustion(obj) {
        let cID = obj.get("_characterid");
        let exhaustionLevel = parseInt(obj.get('current'));
        let rollString = {
            core_die: "1d20"
        };
        if (exhaustionLevel > 0) {
            rollString = {
                core_die: "-" + exhaustionLevel + "[Exhaustion]+1d20"
            };
        }
        setAttrs(cID, rollString);
    }


    const onChangeAttribute = function(obj, prev) {
        if (obj.get('name') === 'exhaustion_level') {
            setExhaustion(obj);
        }
    };


    on("change:attribute", onChangeAttribute);
    

});


Sample ChatSetAttr macro:

!setattr --sel --exhaustion_level|?{Choose Exhaustion Level}


Disclaimer: As always with one of my scripts, test carefully. The only thing this script should be able to change is the "core_die" attribute. If anything needs to be reset manually, you can change this on the Attributes and Abilities tab of the character journal. The default value is "1d20".


January 07 (1 year ago)

Nice! 

Just a thought though: the standard Exhaustion tracking on the D&D 5E by Roll20 sheet can only be manually changed to a maximum of 6, which means that players will not be able to change their exhaustion level on the sheet itself (they’ll have to use ChatSetAttr to adjust above 6) and they’ll see the effects of the standard Exhaustion rules on their sheet. I’m also not sure if the standard Exhaustion will automatically adjust Speed or other stats at higher levels of exhaustion, or if scripts like the Companion scripts will do that along with ammo tracking  

If instead a repeating resource is used, then it can be tracked separately from the standard Exhaustion Attribute. So it might be a good alternative to have the script look for a repeating resource called ‘Exhaustion’ and use that instead!

https://app.roll20.net/forum/post/11701939/tracking-onednd-exhaustion/?pageforid=11701981#post-11701981

January 07 (1 year ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

Should be easy enough to do. I'll look into it tonight. Thanks!

January 08 (1 year ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

Actually, it turns out that the field can accept a manual value of any integer. Entering a negative integer does cause issues though, so the script above is amended only to change the core die on an integer of a or above. On a zero or any other value, it reverts to "1d20".

January 08 (1 year ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

BTW, thanks for linking that thread. I had forgotten I had posted the token marker version. I think this version works much better for what most groups would use it for.

January 08 (1 year ago)

Edited January 08 (1 year ago)

Ah you're right that it can be manually adjusted; it just can't be adjusted with the up/down buttons on the sheet beyond level 6.  I definitely remember getting some weird errors happening when manually adjusting it beyond 6, so maybe that has been changed on the sheet now in possible preparation for OneDnD Exhaustion updates or something. (That was confirmed by Zack in the other thread as well.)

If the script is able to do it, then another nice feature (that might help reduce confusion for players) would be to modify the 'exhaustion effects' status messages that appear in the 'Exhaustion Level' box.  It might not be possible, because It looks like the sheetworkers automatically refresh the effects (and attributes) when the levels are adjusted.

These are the attributes that the are used for exhaustion:

exhaustion_toggle: 0 (off) or 1 (on)
exhaustion_level: (current level of exhaustion)
exhaustion_0: • No effect
exhaustion_1: • Disadvantage on ability checks
exhaustion_2: • Speed halved
exhaustion_3: • Disadvantage on attack rolls and saving throws
exhaustion_4: • Hit point maximum halved
exhaustion_5: • Speed reduced to 0
exhaustion_6: • Death

It would be awesome if the script was able to override the sheetworkers and simply change the 'exhaustion_1' attribute to show the negative adjustment to d20 rolls, and keep all of the other 'exhaustion_#' attributes blank. So if a character had 6 levels of exhaustion, then 'exhaustion 1' would have this: 

-6 to all d20 rolls

And the Exhaustion area on the sheet would look like this:

(I tried sticking @{exhaustion_level} in the 'exhaustion_1' field, but it doesn't autocalculate for display on the sheet, but it will autocalculate for any attribute references in chat.)

It looks like the sheetworkers automatically replace each 'exhaustion_#' any time the 'exhaustion_level' is changed to that number or higher, so the script would have to passively watch for those changes and then revert them after the sheetworkers.  I'm just not sure if that's possible, in terms of timing the script to take effect after the sheetworkers.


From my checking, I don't think your current script will do anything for NPC characters.  NPCs don't use the 'core_die' attribute as far as I can tell. They use the 'd20' attribute instead, so if that is adjusted then any reference to an exhaustion level will work for NPCs as well.


I just tested it on an NPC, by manually adding the 'd20' attribute on the Attributes & Abilities tab, and changing it to '-@{exhaustion_level}[Exhaustion]+1d20' and then using ChatSetAttr to set the 'exhaustion_level' to 9 (!setattr --sel --exhaustion_level|?{Choose Exhaustion Level}) worked for an NPC to roll Advantage and have both rolls affected by the Exhaustion.



I also tested using Always, Query, Toggle, and Never settings, and it was working correctly the whole time for both rolls.

Nevermind - the 'd20' attribute is normally a hidden attribute that simply references the 'core_die' attribute, which can be confirmed by changing the 'core_die' attribute on an NPC and then checking the 'd20' attribute with @{selected|d20} - you'll get the result of the 'core_die' attribute.


keithcurtis said:

  • It only affects the first roll. If you have always roll advantage turned on, the second roll does not suffer the penalty. I can't do anything about this, that second roll is created by the roll template as far as I can tell

I'm not having that issue - it is working for me on advantage and disadvantage rolls to affect both rolls.