DiceCloud Extender

Adds additional capabilities to Dicecloud, like rest functions. Coming soon: dice roller, automatic color coding for spell descriptions, spell and preview on hover.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         DiceCloud Extender
// @namespace    https://ofdiceandmagic.com/
// @version      1
// @description  Adds additional capabilities to Dicecloud, like rest functions. Coming soon: dice roller, automatic color coding for spell descriptions, spell and preview on hover.
// @author       atill91
// @match        https://dicecloud.com/character/*
// @require      https://code.jquery.com/jquery-3.5.1.min.js
// @run-at       document-idle
// @grant        none
// ==/UserScript==


$.noConflict();
jQuery(document).ready(function($){
    'use strict';




    //DISPLAY DCE MESSAGE
    function dcemessage(title,text){
        $("#DCEmessage p").html("<b>"+title+":</b> "+text);
        $("#DCEmessage").fadeIn(800);
    }


    //CONTAINS FUNCTION...finds all elements that contain the text
    //...returns the elements selected not their children
    function contains(selector, text) {
          let elements = document.querySelectorAll(selector);
          return Array.prototype.filter.call(elements, function(element){
            return RegExp(text).test(element.textContent);
          });
        }

    //DICE ROLLER
    //the codepen... https://codepen.io/Atill91/pen/bGEJpJJ?editors=0100

    //function to roll one type of dice
    function roll(numdice,sides,mod) {
        let a = Array(numdice);
        for (let i = 0; i < numdice; i++){
            a[i] = Math.floor(Math.random() * sides) + 1;
        }
        let add = (a, b) => a + b; // function for adding two numbers.
        let result = a.reduce(add); // use reduce to sum the array
        let modifier = mod || 0;
        return result+modifier;
    }

    //function to extract data from standard dice format text
    function extractdice(text){
        let str = text;
        //define result obj
        let result = {
            fullText: str,
            dice: [],
            plusOminus: [],
            numdice: [],
            sides: [],
            mods: [],
            modsTotal: 0, //this will be used later after we call this funciton
            total: 0 //so will this
        }
        const diceExp = /([\+\-]?)(\d+)d(\d+)/gi;
        const modsExp = /([\+\-](\d+)(?!d))/gi;
        //save the diceExp search as an array...also modsExp
        let dice = str.match(diceExp);
        //extract data from dice and save to result obj
        dice.forEach(function(item, i, arr){
            let die = diceExp.exec(item);
            diceExp.lastIndex = 0; //reset search index to perform a second search starting from the beginning. Without this diceExp.exec(item) returns null on the second iteration.
            result.dice = die[0];
            if (die[1] == ""){ result.plusOminus[i] = "+"; }else{ result.plusOminus[i] = die[1]; }
            result.numdice[i] = parseInt(die[2]);
            result.sides[i] = parseInt(die[3]);
        });
        //save mods to result obj
        let mods = str.match(modsExp) || 0; //sets mods to 0 if there are no matches
        if(mods != 0){
            mods.forEach(function(item,i,arr){
                result.mods[i] = parseInt(mods[i]);
            });
        } else{result.mods = 0;}

        return result

    }

    let dicerolltotal = "";
    function displaydice(text){
        let $str = text;
        let dicedata = extractdice($str);
        //roll all the dice and add the total
        dicedata.numdice.forEach(function(item,i,arr){
            let rollresult = parseInt(dicedata.plusOminus[i] + roll(dicedata.numdice[i],dicedata.sides[i]));
            dicedata.total = dicedata.total + rollresult;
        });
        //sum the mods and add it to the total
        if (dicedata.mods != 0){
            let add = (a, b) => a + b;
            let sum = dicedata.mods.reduce(add);
            dicedata.modsTotal = sum;
        }

        dicedata.total = dicedata.total + dicedata.modsTotal;

        dicerolltotal = dicedata.total;

        //add a new paragraph to the container with the result
        let resultText = dicedata.fullText+" = "+"<b>"+dicedata.total+"</b>";
        $("#DCEdicerollerResultContainer").append("<p class='DCEdicerollerResult'>"+resultText+"</p>");

        //scroll the result container to the bottom
        $("#DCEdicerollerResultContainer").animate({ scrollTop: $("#DCEdicerollerResultContainer").prop("scrollHeight")}, 10);

        //show the dice result flash
        $("#DCEdiceresultflash p").html(dicedata.total);
        $("#DCEdiceresultflash").stop(true,true).fadeIn(400).delay(3000).fadeOut(400); //stop() stops the currently running animation

    }//end diceroll()


    //STYLES
    const styles = document.createElement("style");
    styles.innerHTML = `
        #DCEbox{
            width : 256px;
            height : 96px;
            position : absolute;
            top : 50px;
            left : 0;
        }

        #DCE-ShortRest-button{
            position : absolute;
            top : 5px;
            left : 20px;
        }

        #DCE-ShortRest-check{
            color : #76ff76;
            display : none;
            position : absolute;
            top : 7px;
            left : 2px;
        }

        #DCE-LongRest-button{
            position : absolute;
            top : 30px;
            left : 20px;
        }

        #DCE-LongRest-check{
            color : #76ff76;
            display : none;
            position : absolute;
            top : 32px;
            left : 2px;
        }

        #DCE-dawn-button{
            position : absolute;
            top : 55px;
            left : 20px;
        }

        #DCE-dawncheck-check{
            color : #76ff76;
            display : none;
            position : absolute;
            top : 57px;
            left : 2px;
        }

        #DCEmessage{
            background : #5fb962;
            width : 100%;
            height : 100%;
            position : absolute;
            box-shadow : 0 0 8px inset;
            top : 0;
            left : 0;
            display : none;
            z-index : 1;
        }

        #DCEmessage p{
            padding : 0 8px;
            width : calc(100% - 20px);
            color : #ccf2e3;
            margin : 2px;
        }

        #DCEmessagex{
            position : absolute;
            top : 0;
            right : 0;
            margin : 5px 5px 0 0;
            font-size : 1.3em;
            cursor : pointer;
        }

        #DCEdiceroller{
            width : 150px;
            height : 100%;
            position : absolute;
            top : 0;
            right : 0;
            box-shadow: inset 1px 6px 9px -6px black;
        }

        #DCEdicerollerResultContainer{
            width : 100%;
            overflow-y : scroll;
            overflow-x : hidden;
            height : calc(100% - 1.2em);
        }

        .DCEdicerollerResult{
            color: #ccc;
            margin: 0.25em 2px;
            text-align: center;
        }
        .DCEdicerollerResult:last-child{
            color: #fff;
        }
        .DCEdicerollerResult:last-child b{
            font-size: 1.2em;
        }

        #DCEdicerollerinput{
            width : 100%;
            position : absolute;
            bottom : 0;
            text-align : center;
        }

        #DCEdicerollerQ{
            position : absolute;
            top : 2px;
            left : 2px;
            color : #ccc;
            cursor : pointer;
        }
        #DCEdicerollerQ:hover{
            color: #fff;
        }
        #DCEdiceresultflash{
            background: #4caf50;
            width: 100px;
            height: 100px;
            position: fixed;
            top: 10px;
            left: calc(50% - 25px + 255.996px/2);
            border-radius: 8px;
            box-shadow: 0 0 8px inset #a4d7a6;
            border-bottom: 5px solid rgb(0 0 0 / 50%);
            display:none;
        }
        #DCEdiceresultflash p{
            text-align:center;
            margin-top: .5em;
            font-size: 40px;
            color: #eee;
        }

        .paper-font-subhead.modifier:hover,
        .skill-mod:hover,
        #tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(9) > paper-material > div.numbers.paper-font-display1 > div:hover,
        #tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(10) > paper-material > div.numbers.paper-font-display1:hover
        {
            color:white;
            background: #4caf50;
            border-radius:8px;
            box-shadow: 0 0 8px inset #a4d7a6;
            font-size: 1.2em;
        }
        .DCEatkhit:hover{
            color:white;
            background: #4caf50;
            border-radius:8px;
            box-shadow: 0 0 8px inset #a4d7a6;
        }
        .DCEatkdam:hover{
            color:white;
            background: #d13b2e;
            border-radius:8px;
            box-shadow: 0 0 8px inset #e79992;
        }
    `;
    document.head.appendChild(styles);





    //ADD ELEMENTS TO PAGE

    //add font awesome to head (used for checkmarks)
    const fascript = document.createElement('script');
    fascript.type = 'text/javascript';
    fascript.src = 'https://kit.fontawesome.com/a0a5cdaf04.js';
    document.head.appendChild(fascript);

    //add Overlay Scrollbars to head
    const overlayscrollbarsLink = document.createElement("link");
    overlayscrollbarsLink.rel = "stylesheet";
    overlayscrollbarsLink.href = "https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/1.12.0/css/OverlayScrollbars.min.css";
    document.head.appendChild(overlayscrollbarsLink);
    const overlayscrollbarsScript = document.createElement("script");
    overlayscrollbarsScript.type = "text/javascript";
    overlayscrollbarsScript.src = "https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/1.12.0/js/jquery.overlayScrollbars.min.js";
    document.head.appendChild(overlayscrollbarsScript);

    //Add DiceCloud Extender box and buttons and such
    const sidebarnav = document.querySelector("#accountSummary");
    const DCEbox = document.createElement("div");
    DCEbox.id = "DCEbox";
    sidebarnav.appendChild(DCEbox);

    const DCEmenu = document.querySelector("#DCEbox");

    const shortrestButton = document.createElement("button");
    shortrestButton.id = "DCE-ShortRest-button";
    shortrestButton.type = "button";
    shortrestButton.textContent = "Short Rest";
    DCEmenu.appendChild(shortrestButton);

    const shortrestcheck = document.createElement("i");
    shortrestcheck.id = "DCE-ShortRest-check";
    shortrestcheck.classList.add("fas", "fa-check-circle");
    DCEmenu.appendChild(shortrestcheck);

    const longrestButton = document.createElement("button");
    longrestButton.id = "DCE-LongRest-button";
    longrestButton.type = "button";
    longrestButton.textContent = "Long Rest";
    DCEmenu.appendChild(longrestButton);

    const longrestcheck = document.createElement("i");
    longrestcheck.id = "DCE-LongRest-check";
    longrestcheck.classList.add("fas", "fa-check-circle");
    DCEmenu.appendChild(longrestcheck);

    const dawnButton = document.createElement("button");
    dawnButton.id = "DCE-dawn-button";
    dawnButton.type = "button";
    dawnButton.textContent = "Dawn";
    DCEmenu.appendChild(dawnButton);

    const dawncheck = document.createElement("i");
    dawncheck.id = "DCE-dawncheck-check";
    dawncheck.classList.add("fas", "fa-check-circle");
    DCEmenu.appendChild(dawncheck);

    const DCEmessage = document.createElement("div");
    DCEmessage.id = "DCEmessage";
    DCEmenu.appendChild(DCEmessage);
    const DCEmessageP = document.createElement("p");
    document.querySelector("#DCEmessage").appendChild(DCEmessageP);
    const DCEmessagex = document.createElement("i");
    DCEmessagex.id = "DCEmessagex";
    DCEmessagex.classList.add("fas", "fa-times");
    document.querySelector("#DCEmessage").appendChild(DCEmessagex);
    $("#DCEmessagex").click(function(){
        $("#DCEmessage").fadeOut(800);
    });

    const DCEdiceroller = document.createElement("div");
    DCEdiceroller.id = "DCEdiceroller";
    document.querySelector("#DCEbox").appendChild(DCEdiceroller);
    const DCEdicerollerResultContainer = document.createElement("div");
    DCEdicerollerResultContainer.id = "DCEdicerollerResultContainer";
    document.querySelector("#DCEdiceroller").appendChild(DCEdicerollerResultContainer);
    const DCEdicerollerinput = document.createElement("input");
    DCEdicerollerinput.id = "DCEdicerollerinput";
    DCEdicerollerinput.type = "text";
    DCEdicerollerinput.value = "1d20";
    document.querySelector("#DCEdiceroller").appendChild(DCEdicerollerinput);
    //roll the dice and show the result when the user hits enter in the input
    $("#DCEdicerollerinput").keypress(function(e) {
        if(e.which == 13) { //13 is the enter key
            displaydice( $("#DCEdicerollerinput").val() );
        }
    });
    const DCEdicerollerQ = document.createElement("i");
    DCEdicerollerQ.id = "DCEdicerollerQ";
    DCEdicerollerQ.classList.add("fas", "fa-info-circle");
    document.querySelector("#DCEdiceroller").appendChild(DCEdicerollerQ);
    $("#DCEdicerollerQ").click(function(){
        dcemessage("DCE Dice Roller","Type a dice formula (no spaces) and hit enter to display the result. Only + and - are supported at this time.");
    });
    const diceresultflash = document.createElement("div");
    diceresultflash.id = "DCEdiceresultflash";
    document.querySelector("body").appendChild(diceresultflash);
    const diceresultflashP = document.createElement("p");
    document.querySelector("#DCEdiceresultflash").appendChild(diceresultflashP);



    //STAT ROLLS
    //Whenever you click any of the following, roll it: abilities, skills, saving throws, initiative, proficiency bonus.

    //define variables and assign click event to each
    const statrollsInterval = setInterval(function(){
        const strnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(1) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const dexnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(2) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const connum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(3) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const intnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(4) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const wisnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(5) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const chanum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(6) > paper-material > div.numbers > div.paper-font-subhead.modifier");
        const initnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(9) > paper-material > div.numbers.paper-font-display1 > div");
        const profnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(10) > paper-material > div.numbers.paper-font-display1");
        const strsavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(1) > div > div.skill-mod");
        const dexsavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(2) > div > div.skill-mod");
        const consavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(3) > div > div.skill-mod");
        const intsavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(4) > div > div.skill-mod");
        const wissavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(5) > div > div.skill-mod");
        const chasavenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(12) > paper-material > div.bottom.list > div:nth-child(6) > div > div.skill-mod");
        const acrobaticsnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(1) > div > div.skill-mod");
        const animalhandlingnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(2) > div > div.skill-mod");
        const arcananum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(3) > div > div.skill-mod");
        const athleticsnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(4) > div > div.skill-mod");
        const deceptionnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(5) > div > div.skill-mod");
        const historynum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(6) > div > div.skill-mod");
        const insightnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(7) > div > div.skill-mod");
        const intimidationnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(8) > div > div.skill-mod");
        const investigationnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(9) > div > div.skill-mod");
        const medicinenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(10) > div > div.skill-mod");
        const naturenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(11) > div > div.skill-mod");
        const perceptionnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(12) > div > div.skill-mod");
        const performancenum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(13) > div > div.skill-mod");
        const persuasionnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(14) > div > div.skill-mod");
        const religionnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(15) > div > div.skill-mod");
        const sleightofhandnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(16) > div > div.skill-mod");
        const stealthnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(17) > div > div.skill-mod");
        const survivalnum = document.querySelector("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(14) > paper-material > div.bottom.list > div:nth-child(18) > div > div.skill-mod");

        //define an array of all the above vars we want to click
        const numstoclick = [strnum,dexnum,connum,intnum,wisnum,chanum,initnum,profnum,strsavenum,dexsavenum,consavenum,intsavenum,wissavenum,chasavenum,acrobaticsnum,animalhandlingnum,arcananum,athleticsnum,deceptionnum,historynum,insightnum,intimidationnum,investigationnum,medicinenum,naturenum,perceptionnum,performancenum,persuasionnum,religionnum,sleightofhandnum,stealthnum,survivalnum];

        //loop through the array and assign an onclick event to each element in the numstoclick array. Get the element's text (parse it) and roll the dice onclick.
        numstoclick.forEach(function(val){
            val.addEventListener("click",function(e){
                let mod = parseInt( val.textContent );
                let dicetxt = "1d20+"+mod;
                displaydice(dicetxt);

                e.stopPropagation(); //needed to stop the card from expanding. Must be placed at the end of the function.
            });
        });//forEach end

        //ATTACK ROLLS
        const featurestab = document.querySelector("#tabsContent > paper-tab:nth-child(3)");

        //when the features tab is clicked, define atkhits and atkdams.
        //...then when each atkhit is clicked, check if it's a number.
        //...if so, roll the dice.

        featurestab.addEventListener('click',function(){
            const featurestabwait = setTimeout(function(){
                const atkhits = document.querySelectorAll("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.animation-slider > div:nth-child(1) > paper-material > div.bottom.list > div > div > div > div.paper-font-headline.layout.horizontal.center");
                const atkdams = document.querySelectorAll("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.animation-slider > div:nth-child(1) > paper-material > div.bottom.list > div > div > div > div.flex.layout.vertical > div:nth-child(2)");

                for (let i=0; i<atkhits.length; i++){
                    let mod = parseInt(atkhits[i].textContent);
                    if (isNaN(mod)){
                        console.log("mod ( "+atkhits[i].textContent+" ) isn't a number");
                    } else{
                        atkhits[i].addEventListener('click',function(e){
                            let dicetxt = "1d20+"+mod;
                            displaydice(dicetxt);

                            e.stopPropagation();
                        });//atkhit click end
                        atkhits[i].classList.add('DCEatkhit');
                    }

                    //testing the regex... https://regex101.com/r/GFABKl/1
                    let damtxt = atkdams[i].textContent;
                    let dicetxtregex = /([\+\-]?)(\d+)d(\d+)([\+\-]?)(\d+)?(d(\d+))?([\+\-]?)(\d+)?(d(\d+))?([\+\-]?)(\d+)?(d(\d+))?/gi ;
                    let damdice = damtxt.match(dicetxtregex);
                    if (damdice && damdice.length){ //if it found dicetxt, add the click event
                         atkdams[i].addEventListener('click',function(e){
                             let dicetxt = damdice[0];
                             displaydice(dicetxt);
                             e.stopPropagation();
                         });
                        atkdams[i].classList.add('DCEatkdam');
                    } else{ console.log("no dicetxt found in damtxt"); }
                }//loop end
            },100);
        });//featurestab click end






        //check if the stats were saved to the numstoclick array (if not, they weren't loaded yet so we want the interval to keep running).
        if (numstoclick != null){
            clearInterval(statrollsInterval);
        }

    },100);//setInterval end.




    //RESTROLL FORMULA
    function restroll(searchtxt){
        //Rest=Short=Roll[dice text]
        let dicetxtregex = /([\+\-]?)(\d+)d(\d+)([\+\-]?)(\d+)?(d(\d+))?([\+\-]?)(\d+)?(d(\d+))?([\+\-]?)(\d+)?(d(\d+))?/gi ;
        let dicetxtps = contains("paper-material.featureCard > div.bottom.flex > p",searchtxt);
        console.log("dicetxtps = "+dicetxtps+". dicetxtps[0] = "+dicetxtps[0]);
        if(!dicetxtps[0]){return;} //if no p's with searchtxt are found, exit the function
        let i = dicetxtps.length - 1;
        let interval = setInterval(function(){
             //get the dicetxt and roll the dice
            let dicetxt = dicetxtps[i].textContent.match(dicetxtregex)[0];
            displaydice(dicetxt);
            //get the current(old) value of its uses...
            let usestxt = dicetxtps[i].parentNode.parentNode.firstElementChild.firstElementChild.nextElementSibling;
            let olduses = /(\d+)\/(\d+)/g.exec(usestxt.textContent)[1];
            //click the reset button
            let resetbtn = dicetxtps[i].parentNode.nextElementSibling.lastElementChild;
            $(resetbtn).trigger("click");
            //click use btn it a number of times = old value + the roll
            let usebtn = dicetxtps[i].parentNode.nextElementSibling.firstElementChild;
            //If the old value + the roll = current value or if the old value + the roll = the max uses, clear the subinterval
            // else click the use button
            let subinterval = setInterval(function(){
                let theroll = dicerolltotal;
                let currentuses = /(\d+)\/(\d+)/g.exec(usestxt.textContent)[1];
                let maxuses = /(\d+)\/(\d+)/g.exec(usestxt.textContent)[2];
                let newuses = parseInt(olduses) + parseInt(theroll);
                if(newuses == parseInt(currentuses) || newuses >= parseInt(maxuses)){
                    clearInterval(subinterval);
                }else{
                    $(usebtn).trigger("click");
                }
            },10);
            i--;
            if(i < 0){ clearInterval(interval); }
        },100);
    }//function end





    //LONG REST
    document.querySelector('#DCE-LongRest-button').onclick = function(){
        //Reset all feature cards containing the text  Rest=Long, Rest=Long=Roll, Rest=Short, and Rest=Short=Roll
        $("paper-material.card:contains('Rest=Long') paper-button:contains('Reset')").trigger("click");
        restroll("Rest=Long=Roll");
        $("paper-material.card:contains('Rest=Short') paper-button:contains('Reset')").trigger("click");
        restroll("Rest=Short=Roll");

        /*
        //Hit Points
        //not working as of now
        const $hpinput = $("#hitPointSlider").children(":nth-child(2)").children(":first").children(":nth-child(2)").children(":first").children(":nth-child(2)"); //for the label, change last :second to first
        let $hpmax = $hpinput.attr("max");
        console.log("id="+$hpinput.attr("id")+". $hpmax="+$hpmax);
        $hpinput.val("999");
        */


        //Hit Dice... this doesn't work if you have multiple types of hit dice.
        const $uparrow = $("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(11) > paper-material > div.left.green.paper-font-display1.white-text.layout.horizontal > div:nth-child(1) > paper-icon-button.resourceUp.x-scope.paper-icon-button-0");
        const $hd = $("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(11) > paper-material > div.left.green.paper-font-display1.white-text.layout.horizontal > div.resourceValue.layout.vertical.center > div:nth-child(1)");
        let $oldhd = parseInt($hd.text());
        let interval = setInterval (function(){   //this must be set as a variable. every 10ms, it clicks the up arrow if it isn't disabled. if it is it cancels the interval, which ends the clicking.
            if ($uparrow.attr("aria-disabled") == "false"){
                $uparrow.trigger("click");
            } else{
                clearInterval(interval);
                //now the hit dice are set to the max, which we don't want.
                //we need to click the down arrow until we get to a number = $oldhd + $maxhd*0.5. We'll use another interval to do this.
                let $downarrow = $("#tabPages > div.tab-page.fit.iron-selected > div > div.column-container.thin-columns > div:nth-child(11) > paper-material > div.left.green.paper-font-display1.white-text.layout.horizontal > div:nth-child(1) > paper-icon-button.resourceDown.x-scope.paper-icon-button-0");
                let $maxhd = parseInt($hd.text());
                let $newhd = Math.floor( $maxhd*0.5 + $oldhd );
                if ($newhd >= $maxhd) $newhd = $maxhd;
                let subinterval = setInterval (function(){
                  if (parseInt($hd.text()) != $newhd){
                    $downarrow.trigger("click");
                  } else {
                      clearInterval(subinterval);
                  }
                },10);
            }
        },10);

        dcemessage("DCE Long Rest","HP and Spell Slots need to be manually reset for now.");

        //fade in the checkmark
        $("#DCE-LongRest-check").fadeToggle(800).delay(3000).fadeToggle(800);
    };

    //SHORT REST
    document.querySelector('#DCE-ShortRest-button').onclick = function(){
        restroll("Rest=Short=Roll");

        $("paper-material.card:contains('Rest=Short') paper-button:contains('Reset')").trigger("click");

        $("#DCE-ShortRest-check").fadeToggle(800).delay(3000).fadeToggle(800);
    };

    //DAWN (this is for all of the x/day features)
    document.querySelector('#DCE-dawn-button').onclick = function(){

        restroll("Dawn=Roll");

        //Dawn=Full
        $("paper-material.card:contains('Dawn=Full') paper-button:contains('Reset')").trigger("click");

        //checkmark
        $("#DCE-dawncheck-check").fadeToggle(800).delay(3000).fadeToggle(800);
    };

});//documentready end