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

Hidden Rolls Messages

1627623350
Ergo
Pro
Marketplace Creator
This script wasn't working for me so I made some changes and it seems to be working now. I commented out the globalconfig code as it was creating an undefined. I changed this line because it was anything defined as a character. &nbsp; &nbsp; }).filter((obj) =&gt; obj.get("controlledby") != ""&nbsp; &nbsp;&amp;&amp;&nbsp; ! playerIsGM(this.GM.id)&nbsp; &amp;&amp; obj.get("controlledby") != "all" ); It originally used&nbsp;&nbsp; &nbsp;}).filter((obj) =&gt; obj.get("controlledby") != "" &amp;&amp; obj.get("controlledby") != this.GM.get("displayname")); I'm not sure why the&nbsp; &nbsp;!= "" &amp;&amp; obj.get("controlledby") != this.GM.get("displayname")); didn't work other that when I logged the value it looked like the id. Still very very new at this but I have a script that works for me now. // Author: Phillip Tran /* &nbsp; Description:&nbsp; &nbsp; &nbsp; &nbsp; Inspired by Disco Elysium, this script will roll a check for the player in &nbsp; &nbsp; &nbsp; the background then whisper the player if they pass that check.&nbsp; &nbsp;&nbsp; &nbsp; Purpose:&nbsp; &nbsp; &nbsp; &nbsp; One of the things I found immersion breaking was that other players would &nbsp; &nbsp; &nbsp; know the results of certain checks like Knowledge or Lore checks. Now&nbsp; &nbsp; &nbsp; &nbsp; normally DMs would take time to whisper to the person the results of the&nbsp; &nbsp; &nbsp; &nbsp; check if they wanted to keep this secret, but this takes time and can be&nbsp; &nbsp; &nbsp; &nbsp; impractical to do in certain situations like if the DM wants the user to&nbsp; &nbsp; &nbsp; &nbsp; do a Lore check in the middle of their narration. This script seeks to add&nbsp; &nbsp; &nbsp; &nbsp; an easy way for DMs to do hidden rolls and let the player know information &nbsp; &nbsp; &nbsp; without distracting from the flow of the campaign &nbsp; &nbsp; &nbsp;&nbsp; */ 'use strict'; var hidden_roll_messages = hidden_roll_messages || {}&nbsp; hidden_roll_messages.roll_controller = class { &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; constructor() { &nbsp; &nbsp; &nbsp; &nbsp; /*--- User Config if no global config --- */ &nbsp; &nbsp; &nbsp; &nbsp; let dice_sides = 20; &nbsp; &nbsp; &nbsp; &nbsp; let HRM_identifier = "!!!"; &nbsp; &nbsp; &nbsp; &nbsp; /*-----------------------------------------*/ /* Commented out &nbsp; &nbsp; &nbsp; &nbsp; if(globalconfig){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dice_sides = globalconfig.dice_sides; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HRM_identifier = globalconfig.HRM_identifier; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;*/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.dice_sides = dice_sides; &nbsp; &nbsp; &nbsp; &nbsp; this.HRM_identifier = HRM_identifier; // the symbols used at the begining of a handout name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// signify it should be a hidden roll message &nbsp; &nbsp; &nbsp; &nbsp; log("globalconfig") &nbsp; &nbsp; &nbsp; &nbsp; // edit down here if you know what you're doing &nbsp; &nbsp; &nbsp; &nbsp; this.name_json_map = {}; // key: name of the handout, value: the json info&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.GM = undefined; &nbsp; &nbsp; &nbsp; &nbsp; this.iden_length = this.HRM_identifier.length;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log("Got HRM Length") &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.GM = this.getGM(); &nbsp; &nbsp; &nbsp; &nbsp; this.setup_listeners(); &nbsp; &nbsp; &nbsp; &nbsp; this.process_all_current_HRMS(); &nbsp; &nbsp; &nbsp; &nbsp; sendChat("hidden_roll_messages", "Script successfully loaded", null, {noarchive:true} ); &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; getGM() { &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Iterates through the players and return who is the GM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- (Player Obj) -&gt; Player who is the GM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called from:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; constructor() &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let players = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _type: "player",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let i = 0; &nbsp; &nbsp; &nbsp; &nbsp; for (i = 0; i &lt; players.length; i++){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(playerIsGM(players[i].get("id"))){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return(players[i]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } &nbsp; &nbsp; setup_listeners() { &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Sets up any event listeners when object is created.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called from:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; constructor() &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Set up custom handlers below! &nbsp; &nbsp; &nbsp; &nbsp; on("change:handout", this.edit_hidden_roll_message.bind(this)); &nbsp; &nbsp; &nbsp; &nbsp; on("destroy:handout", this.process_handout.bind(this)); &nbsp; &nbsp; &nbsp; &nbsp; on("chat:message", this.parse_command.bind(this)); &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; edit_hidden_roll_message(handout, prev){ &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; param:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@handout (handout_event) -&gt; The handout that was just created &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@prev (list) -&gt; list of previous values &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Parses the handout for `!!!` at the begining of the handout name. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;If found, obtain the JSON data and store it within the class. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called from: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;constructor() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp; let handout_name = handout.get("name"); &nbsp; &nbsp; &nbsp; &nbsp; let tag_check = ((handout_name.slice(0,this.iden_length) === this.HRM_identifier) ? true : false); &nbsp; &nbsp; &nbsp; &nbsp; let potential_HRM_tag = handout_name.slice(0, 5); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(tag_check) { // creating a new [HRM] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let new_name = "[HRM] " + handout_name.slice(this.iden_length); // replace the identifier with [HRM] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handout.set("name", new_name); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handout.get("notes", this.extract_note_data.bind(this, handout)); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else if(potential_HRM_tag === "[HRM]") { // Editing an existing [HRM] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.edit_HRM(handout, prev) &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; extract_note_data(handout, note){ &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; param:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@note (note object) -&gt; The notes corresponding to our HRM handout &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@handout (handout object) -&gt; the handout object containing the note &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Parses the note and formats it, then converts it to json and stores it&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;within the name_json_map &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called from: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;add_hidden_roll_message() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let name = handout.get("name"); &nbsp; &nbsp; &nbsp; &nbsp; let json_string = note.replace(/(&lt;([^&gt;]+)&gt;)/gi, ""); &nbsp; &nbsp; &nbsp; &nbsp; json_string = json_string.replace(/&amp;nbsp;/gi, ''); &nbsp; &nbsp; &nbsp; &nbsp; try{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(json_string.length == 0) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw "not valid Json"; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let json = JSON.parse(json_string); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.name_json_map[name] = json; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(name, "/w " + this.GM.get("displayname") + " Status: &lt;b&gt;SUCCESS&lt;/b&gt;", null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; catch(err){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(name, "/w " + this.GM.get("displayname") + " Status: &lt;b&gt;FAILED&lt;/b&gt; \n Json Formatter: <a href="https://jsonformatter.curiousconcept.com/" rel="nofollow">https://jsonformatter.curiousconcept.com/</a>", null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handout.set("name", "Invalid JSON Handout"); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; process_handout(handout, delete_handout=true) { &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; param:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@handout (handout Object) -&gt; The handout that was just deleted &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@delete_handout (boolean) -&gt; boolean to determine whether or not to delete the handout after the handout has finished rolling &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Parses the recently deleted handout and checks to see if it's an [HRM] handout. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if it is, handle the roll and process the json data.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called from: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;constructor() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let handout_name = handout.get("name"); &nbsp; &nbsp; &nbsp; &nbsp; let tag_check = ((handout_name.slice(0,5) === "[HRM]") ? true : false); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(tag_check) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let characters = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _type: "character",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).filter((obj) =&gt; obj.get("controlledby") != "" &amp;&amp; obj.get("controlledby") &amp;&amp; ! playerIsGM(this.GM.id) &amp;&amp; obj.get("controlledby") != "all" ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.roll(characters, handout_name);&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(delete_handout) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delete this.name_json_map[handout_name] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch(error) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log(error); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("[HRM]", "Something went horribly wrong with the Json parsing! Are you sure that your format is the same in the documentation and that the attribute actually exists?", null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; edit_HRM(handout, prev) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@handout (handout Object) -&gt; The handout that was just deleted &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@prev {handout Object} -&gt; Reference to the previous handout &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; This callback function will be called when the user is editing an existing [HRM] handout &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; It will remove the previous reference in our dictionary and update it with the new information. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ## make sure the name still contains the [HRM] tag in the front or things will not work. &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None, but updates the information in our name_json_map &nbsp; &nbsp; &nbsp; &nbsp; called from: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process_handout() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp; delete this.name_json_map[prev["name"]]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handout.get("notes", this.extract_note_data.bind(this, handout)) &nbsp; &nbsp; } &nbsp; &nbsp; roll(characters, handout_name) { &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @characters -&gt; an array of all the characters not controlled by the DM&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @handout_name -&gt; the name of the recently deleted handout &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Iterates through the array of characters and simulates a roll. Then checks the json&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; and messages the player with the on_pass message if passed &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called From: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process_handout() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let handout_json_dat = this.name_json_map[handout_name]; &nbsp; &nbsp; &nbsp; &nbsp; let attr_to_check = handout_json_dat["attr"]; &nbsp; &nbsp; &nbsp; &nbsp; let pass_value = handout_json_dat["pass"]; &nbsp; &nbsp; &nbsp; &nbsp; let msg = handout_json_dat["on_pass"]; &nbsp; &nbsp; &nbsp; &nbsp; let on_failed = handout_json_dat["on_failed"]; // optional json parameter &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let i = 0; &nbsp; &nbsp; &nbsp; &nbsp; for(i = 0; i &lt; characters.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let character = characters[i]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let dice_roll = ((this.dice_sides != 0) ? randomInteger(this.dice_sides) : 0) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let result = parseInt(getAttrByName(character.id, attr_to_check)) + dice_roll; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(result &gt;= pass_value){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let recipient = character.get("name").split(" ")[0]; // get first name only &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let command = "/w " + recipient + " [&lt;b&gt;SUCCESS: " + result + "&lt;/b&gt;] " + msg; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(attr_to_check, command, null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if(on_failed != undefined) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let recipient = character.get("name").split(" ")[0]; // get first name only &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let command = "/w " + recipient + " [&lt;b&gt;FAILED: " + result + "&lt;/b&gt;] " + on_failed; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(attr_to_check, command, null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // either way, whisper the result to the GM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let command = "/w " + this.GM.get("displayname") + " &lt;b&gt; RESULT: " + character.get("name") + " | " + (result &gt;= pass_value) + "&lt;/b&gt;"; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("[HRM]", command, null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; process_all_current_HRMS(){ &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Iterates through all current handouts and addes all the [HRM] and their corrponding &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSON data to the name_json_map &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called From: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; constructor() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let handouts = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _type: "handout",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let i = 0; &nbsp; &nbsp; &nbsp; &nbsp; for( i = 0; i &lt; handouts.length; i++ ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let handout_name = handouts[i].get("name"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let tag_check = ((handout_name.slice(0,5) === "[HRM]") ? true : false); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(tag_check){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handouts[i].get("notes", this.extract_note_data.bind(this, handouts[i])); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } &nbsp; &nbsp; parse_command(command){ &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @command {Chat Object} -&gt; The text recieved by the api &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parses the command to see if it's a hrm command then execute a function &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called From: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setup_listeners() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp; if(command.type == "api" &amp;&amp; command.content.indexOf("!hrm ") !== -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command = command.content.split( " " ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(command[1] === "play"){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let handout_name = command.slice(2).join(" "); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.play_HRM(handout_name); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } &nbsp; &nbsp; play_HRM(handout_name){ &nbsp; &nbsp; &nbsp; &nbsp; /* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @handout_name {string} -&gt; name of the HRM handout you want to play w/o [HRM] tag &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Desc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Finds the handout name in our name_json_map and executes the hidden roll without deleting the hangout. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Returns:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Called From: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parse_command() &nbsp; &nbsp; &nbsp; &nbsp; */ &nbsp; &nbsp; &nbsp; &nbsp;let handout = findObjs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _type: "handout",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).filter((obj) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let name = obj.get("name") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name = name.slice(5).trim() // remove [HRM] tag and any weird spaces &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(name === handout_name) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false &nbsp; &nbsp; &nbsp; &nbsp; });; &nbsp; &nbsp; &nbsp; &nbsp; if(handout.length == 0){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let command = "/w " + this.GM.get("displayname") + " &lt;b&gt; No handout exists with that name &lt;/b&gt;"; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("[HRM]", command, null, {noarchive:true} ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.process_handout(handout[0], false) &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } } on("ready", function() { &nbsp; &nbsp; var controller = new hidden_roll_messages.roll_controller(); })
1627628103
GiGs
Pro
Sheet Author
API Scripter
You added this: playerIsGM(this.GM.id)&nbsp; the this keyword is not functional on roll20.
I forget who posted it but there is a "Blind Check" api floating around that is absolutely beautiful and I use it religiously at table.&nbsp;&nbsp;
This is the Blind check API I use. I love it. <a href="https://gist.github.com/BaldarSilveraxe/57de44c1262965d502780b9539de7e15" rel="nofollow">https://gist.github.com/BaldarSilveraxe/57de44c1262965d502780b9539de7e15</a>
That would be it, that thing is absolutely amazing, it looks so good and the players enjoy the blind check system.&nbsp;&nbsp;
Ya it is and my players have been enjoying it too.
1627712592
vÍnce
Pro
Sheet Author
If you play 5e(official sheet) or Pathfinder (community sheet), you might like this Blind Checks script.
Thats the one I have, I thought it was what Snow was linking lol
Those both are the same, I just link the script.&nbsp; vÍnce&nbsp; linked the posting. I couldn't find the posting.