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

3D Dice rolling via API

April 20 (10 years ago)

Edited April 20 (10 years ago)
The players for my group are craving the anticipation of throwing the dice!
Awesomeness: Roll20 does that with 3D Dice!
Problem: Not when the rolls are sent to chat from API it seems :(
Why is it a problem?: The damage rolling in this system is time consuming to type out and painfully spammy when done via macro so I wrote some API (with forum's aid) to handle it easily. type the roll once, tell it how many times it needs doing and boom! its done! Now I'm trying to add in the suspense and anticipation of rolling dem dice!
But it doesn't show the 3D dice with my API script rolls :( The rolls will almost always (90% of the time) be 2d6+X so it should always be a reasonable to see the 3D dice.

Is there a way to either force 3D dice (as in the option, if roll20 decides the roll is too silly for 3D dice thats fine) or just to make 3D dice happen via API sendChat()?
OR is there another function (IE Not sendChat) that I should be using?
FYI the end result in chat should look nice so: "/em Doing 12 Damage to the Left Arm" would be acceptable,
EDIT:
Thanks in advance :)
Love messing with the API btw, nice script editor.
April 20 (10 years ago)
The Aaron
Pro
API Scripter
There is not a way for the API to generate 3d Dice.

If you "Have to Have It!", the only option I can think of is a two step process:
  1. Your API command creates or updates a Macro that each player has by setting it equal to a regular text string containing the roll and formatting.
  2. Your Player clicks that macro in their macro bar to perform the roll.

In some regards, that might work better, as the extra click for the rolling of the dice may increase the anticipation of the rolls.
April 20 (10 years ago)
Interesting, hadn't considered that...
Is it possible to trigger a macro from the API?
Not all players are Roll20 literate, so if I could foolproof this by altering an existing macro and then rolling it right away that could work nicely.
Also: How do I obtain a macro in the API? Feel free to just link a page or something if its a pain to type out. I'm starting to get the hang of this API shizzle :)
April 20 (10 years ago)
The Aaron
Pro
API Scripter
No, the API can't trigger the macro, and any hack that would let it seem like it triggered the macro would just be the same problem as it would involve parsing the macro's text and manually sending it to the chat with sendChat().

As for how to get macros, I pretty much live on this page when doing API work: https://wiki.roll20.net/API:Objects#Finding.2FFilt...

Something like this would find the macro and create it if it didn't exist, then set the action to your roll (bonus, your location table ought to work now):
var dice_expression = '[[3d6+8]]',
    table_expression = '[[ 1t[some-location-table] ]]';

(findObjs({
  type: 'macro',
  name: 'Roll the Dice',
  playerid: msg.playerid
})[0] || createObj('macro',{
  name: 'Roll the Dice',
  playerid: msg.playerid
})).set('action','/em Doing'+dice_expression+' to the '+location_expression);

You'd need to talk the players through turning on their macro bar and checking that macro on in the settings tab, but after that , it would always just be there in their macro bar below the names of the players.

Just a note, I didn't test the above, but It should work. you can definitely break that up over multiple lines and do some if checks if you're more comfortable with that. =D
April 20 (10 years ago)
Nice. Gave that link a quick once over while my boss was away, looks like I have my reading material for the train ride home :p
I never even considered the (find || create).set bit, took me a while to realise thats what it was. Makes so much sense now that I've seen it.
Anyway, thanks, I'll give it a shot tonight / tomorrow.

Cheers Aaron.
April 20 (10 years ago)
The Aaron
Pro
API Scripter
No worries, let me know how it goes!
April 22 (10 years ago)
I have re-written this post a half dozen times now over the last 12 hours.
I keep coming up with something new to try every time I start writing...
...
...
Nope finally out of ideas xD
Got a question though: Trying to get the roll result of an inline roll in a template. There is only one roll and I have already successfully identified the template being rolled as the one I am interested in.
My aim is to trigger some more rolls should this inline roll be at least above 0. (which indicated some degree of success)
However! It just tells me that:
msg.inlinerolls[0].total
is undefined.
At first I thought it was because I had 3D dice turned on and it was delaying the result and hence it was not yet defined. Great theory but wrong. Turned off 3D dice and still no love.
Any idea what I am doing wrong?

Also just tried this:
log(JSON.parse(msg.inlinerolls[0]).total);
and its giving me some funky error that I am guessing means inline rolls are not just rollresults and hence I cannot parse them as you would a rollresult type message.

:(
April 22 (10 years ago)
The Aaron
Pro
API Scripter
Can you throw a log(msg); in there and post the results?
April 22 (10 years ago)
{"content":" {{name= Attack }} {{Attack Roll = $[[0]]}} ","inlinerolls":[{"expression":"(50)-(1d100)","results":{"resultType":"sum","rolls":[{"expr":"(50)-(","type":"M"},{"dice":1,"results":[{"v":38}],"sides":100,"type":"R"},{"expr":")","type":"M"}],"total":12,"type":"V"},"rollid":"-JnXx1gry8ilTGgZ1M12","signature":"4c0517f72d9b1ef44758c4a7950389ddaa65e386aa0cb7f7aad51ff354e939ce114a8a9260ffaac37abe7f934baa5a43cc6161c4ad6694e21f56000d4f56d14f"}],"playerid":"-JnILwonPu_5199Se_sg","rolltemplate":"default","type":"general","who":"Smethane (GM)"}
April 22 (10 years ago)
The Aaron
Pro
API Scripter
msg.inlinerolls[0].results.total

{
    "content": " {{name= Attack }} {{Attack Roll = $[[0]]}} ",
    "inlinerolls": [
        {
            "expression": "(50)-(1d100)",
            "results": {
                "resultType": "sum",
                "rolls": [
                    {
                        "expr": "(50)-(",
                        "type": "M"
                    },
                    {
                        "dice": 1,
                        "results": [
                            {
                                "v": 38
                            }
                        ],
                        "sides": 100,
                        "type": "R"
                    },
                    {
                        "expr": ")",
                        "type": "M"
                    }
                ],
                "total": 12,
                "type": "V"
            },
            "rollid": "-JnXx1gry8ilTGgZ1M12",
            "signature": "4c0517f72d9b1ef44758c4a7950389ddaa65e386aa0cb7f7aad51ff354e939ce114a8a9260ffaac37abe7f934baa5a43cc6161c4ad6694e21f56000d4f56d14f"
        }
    ],
    "playerid": "-JnILwonPu_5199Se_sg",
    "rolltemplate": "default",
    "type": "general",
    "who": "Smethane (G
April 22 (10 years ago)
damnit.
This is why we need intelisense xD
Thanks man, feeling dumb, but not gonna forget that in a hurry.
April 22 (10 years ago)
The Aaron
Pro
API Scripter
:). I have to check that all the time... :)
April 22 (10 years ago)

Edited April 22 (10 years ago)
Ok, the final result of all my hard work, and I am now over an hour past my bed time, so this DOES count as hard work, is... Some thankyous first:
Thanks Aaron, you been a great help, couldn't have done it without you buddy.
Thanks to my boss for not giving a shit when I take a 2 hour lunch break to work on this instead of whatever I'm being paid a small fortune (its all relative) to work on.
And thank you to... ehm... Who else... My Mom! Cause why not?
The results look like this btw:

Without further ado, the script:

on('chat:message', function(msg){
    
    var parts = msg.content.split(" ");
    var name = parts[2];//should be the bit after "&{template:default} {{name=" 
    //IE the name of the macro / template / whatever
    
    if(name.toLowerCase() === "attack")
    {
        var result = msg.inlinerolls[0].results.total;
        if (result > 0)
        {
            var numRolls = Math.max(Math.floor(result/10), 1);
            var damage = " ?{Damage Roll|2d6} ";
            sendChat("player|"+msg.playerid, "[Roll Damage!](!err" + damage + numRolls+")");
        }
    }
    else return;
});


on('chat:message', function(msg) {
    if (msg.type !== 'api') return;
    
    var parts = msg.content.split(' ');
    var command = parts.shift().substring(1);


    if (command.toLowerCase() === 'err' && parts.length > 1) {
        var roll = parts.slice(0, parts.length - 1);
        var repeat = parseInt(parts.pop());
        if (!repeat) return;
        
        var location;
        var output = genOutput(roll);
        delayRoll('player|'+msg.playerid, output, repeat, true, roll);
    }
    
    function delayRoll(id, text, repeatsLeft, firstRoll, roll) {
        if(repeatsLeft > 0) 
        {
            if(firstRoll) sendChat(id, text);
            else setTimeout(function(){ sendChat(id, text); }, 2000);
            text = genOutput(roll);
            delayRoll(id, text, repeatsLeft-1, false, roll);
        }
    }
    
    function genOutput(roll)
    {
        var output = '/em ';
        var tableRoll = randomInteger(100);
        if(tableRoll <=50) location =                           "Body";
        else if(tableRoll <=60 && tableRoll > 50) location =    "Head";
        else if(tableRoll <=70 && tableRoll > 60) location =    "Left Arm";
        else if(tableRoll <=80 && tableRoll > 70) location =    "Right Arm";
        else if(tableRoll <=90 && tableRoll > 80) location =    "Left Leg";
        else if(tableRoll <=100 && tableRoll > 90) location =   "Right Leg";
        else location = "Error";
        return output += " Doing [[" + roll + "]] Damage to the <a>"+location+"</a>";
    }
});

Thanks again, no doubt I will be back with more silly ideas for API thingies as my mate continues to develop his rule set.
Smethane