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

DM view only player rolls.

1522928676

Edited 1522959882
Hi all, I'm a pro subscriber but don't really use the pro features.  As a group we would like to have some rolls which are hidden from the players (e.g. insight roll to see if an NPC is lying to the character) in order to insulate the players from potentially knowing the NCPs motives based on how well they did on the roll. However, some of my players would still like to be the ones who "throw the dice" as it were. Is it possible for the player to initiate a d20 roll that only the DM can see?  I'm looking for a Roll20 equivalent of the player dropping a d20 in to the top of a dice tower which only the DM can see the bottom of. Thanks in advance, Lee
1522928935

Edited 1522929614
Ziechael
Forum Champion
Sheet Author
API Scripter
The  powercards API script can do this as well as one called  blindroll :) I believe Blind Roll does this natively whereas powercards can be used to set who to whisper a roll to, including just the DM.
1522967822

Edited 1522968042
Ziechael said: The  powercards API script can do this as well as one called  blindroll :) I believe Blind Roll does this natively whereas powercards can be used to set who to whisper a roll to, including just the DM. Thank you! Blind Roll is pretty much exactly what I wanted. However.... I'm now trying to be more ambitious and trying to combine a macro which pulls in the information from the character sheet with the .js of blindroll: on("chat:message", function(msg) { var cmdName = "!broll "; var msgTxt = msg.content; var msgWho = msg.who; var msgFormula = msgTxt.slice(cmdName.length); if(msg.type == "api" && msgTxt.indexOf(cmdName) !== -1) { sendChat(msgWho, "/gmroll " + msgFormula); sendChat(msgWho, "/w " + msgWho + " secret roll sent to GM (" + msgFormula + ")"); }; }); With the macro I use to roll NPC attributes: /w gm &{template:default} {{name=Skill Checks for @{selected|token_name}}} {{Arcana= [[1d20+@{selected|arcana_bonus}]] | [[1d20+@{selected|arcana_bonus}]]}} {{Deception = [[1d20+@{selected|deception_bonus}]] | [[1d20+@{selected|deception_bonus}]]}} {{Insight = [[1d20+@{selected|insight_bonus}]] | [[1d20+@{selected|insight_bonus}]]}} {{Intimidation = [[1d20+@{selected|intimidation_bonus}]] | [[1d20+@{selected|intimidation_bonus}]]}} {{Investigation = [[1d20+@{selected|investigation_bonus}]] | [[1d20+@{selected|investigation_bonus}]]}} {{Perception = [[1d20+@{selected|perception_bonus}]] | [[1d20+@{selected|perception_bonus}]]}} {{Persuasion = [[1d20+@{selected|persuasion_bonus}]] | [[1d20+@{selected|persuasion_bonus}]]}} Unfortunately I can't seem to get it to process the @{selected... stuff.  It just regurgitates it verbatim giving "Skill Checks Sent for @{selected|token_name}" rather than "Skill Checks for Zanril" Any ideas? Or am I pushing it too far and expecting too much? Thanks, Lee
1522968733
The Aaron
Pro
API Scripter
The expansion of @{selected} and the like happen in the client before the message is sent to the API.  The API doesn't deal with expanding those references.  You have a few options: 1) reimplement your macro as part of the API replacing all the @{selected} references with looking up the attributes with getAttrByName(). 2) building a parser to replace all the 2{selected} references dynamically before sending the text to the chat (I do this in GroupInitiative if you want a reference).
1523966100

Edited 1523969086
Thank you for all your help! Looking through examples it turned out to be fairly easy.  I'm liking the API scripting :) BlindSkills.js
1523971628
The Aaron
Pro
API Scripter
Not bad!  I recommend wrapping all scripts in the on('ready',...) event just to create a new scope and prevent polluting the global scope.  Not such a big deal on this script, but it's good habit to get into. Nice work!
So, the on("ready",... seems to be an asynchronous event handler like the on("chat:message",... no? How do you scope one event handler in another? Or am I supposed to be putting in a global flag which prevents the content of the chat:message event function from running unless "ready" is triggered first? Or am I completely mis-understanding the on("...  mechanism?  Do you have any examples of the "ready" used with "chat:message"?
1524002741
The Aaron
Pro
API Scripter
Basically, you just put something like: on('ready',()=>{ /* your code */ }); So something like: on('ready', () => {   on("chat:message", function(msg) {     var cmdName = "!bskills";     var msgTxt = msg.content;     var msgWho = msg.who;     var msgSelected = msg.selected;     if(msg.type == "api" && msgTxt.indexOf(cmdName) !== -1) {       if (msg.selected !== undefined) {         _.each(msg.selected, function(a) {           var token = getObj("graphic", a._id);           if (token.get("represents") != "") {             var character = getObj("character", token.get("represents"));             sendChat(msgWho, "/w " + msgWho + " &{template:default} {{name=Skill Checks Sent for " + character.get("name") + "}} ");             sendChat(msgWho, "/w gm &{template:default} {{name=Skill Checks for " + character.get("name") + "}}  {{Arcana= [[1d20+" +  getAttrByName(character.id, "arcana_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "arcana_bonus") + "]]}} {{Deception = [[1d20+" +  getAttrByName(character.id, "deception_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "deception_bonus") + "]]}} {{Insight = [[1d20+" +  getAttrByName(character.id, "insight_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "insight_bonus") + "]]}} {{Intimidation = [[1d20+" +  getAttrByName(character.id, "intimidation_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "intimidation_bonus") + "]]}} {{Investigation = [[1d20+" +  getAttrByName(character.id, "investigation_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "investigation_bonus") + "]]}} {{Perception = [[1d20+" +  getAttrByName(character.id, "perception_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "perception_bonus") + "]]}} {{Persuasion = [[1d20+" +  getAttrByName(character.id, "persuasion_bonus") + "]] | [[1d20+" +  getAttrByName(character.id, "persuasion_bonus") + "]]}}");           }         });       } else {         sendChat(msgWho, "/w gm Needs to select a token");         sendChat(msgWho, "/w " + msgWho + " Select a token for the !bskills command");       }     };   }); }); Basically, when the 'ready' event fires, it registers your other function to handle 'chat:message' events.
Ah, ok, I was mis-understanding. So the  on("...  is essentially a function which registers an event handler rather than being the definition of an event handler. I think I'm used to static coding too much. Thanks again :)
1524005652
The Aaron
Pro
API Scripter
Yeah, it takes some getting used to, no problem. on() is just a function that registers a callback to be called when a given event occurs.  In the case of the 'ready' event, it only happens once after the API is fully loaded, so putting your code inside it means that you won't set anything up until everything has loaded.  The API concatenates all the scripts together and executes them in one go, which means that the only thing that will get executed after the initial load are event handler callbacks.  The order of operations for the API startup is basically: Concatenate and execute the API script. Load all objects into the API (firing various add events) Issue the 'ready' event. Issue events as the Game changes.