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 not working from sendChat()

1608759231

Edited 1610217854
Richard @ Damery
Pro
API Scripter
I've seen at least 1 recent post stating that 3D dice have stopped working when a dice roll is called from an API via sendChat().&nbsp; Has anything been done about this?&nbsp; I'm getting the same issue, but I wonder if I'm doing something wrong. OS: Windows 10 Home 64-bit Build 18363 M/C: Intel Core i7-6700K CPU @4Ghx (no overclock) RAM: 16GB Graphics: NVIDIA GeForce GTX 1060 6GB Graphics driver: v27.21.14.5671 dated 9/30/2020 Browser: Google Chrome Version 87.0.4280.141 (Official Build) (64-bit) I've read the API Chat wiki entry and produced this piece of code to demonstrate the issue, which uses the {use3d: true} option.&nbsp; Loading this API Script and using the command !d3check --rolldice 1d4|test roll.|true&nbsp; &nbsp;should roll a d4 as a 3d dice roll.&nbsp; Use !d3check --help &nbsp;to see format of commands. /** * diceCheck.js * * * Copyright 2020: Richard @ Damery. * Licensed under the GPL Version 3 license. * <a href="http://www.gnu.org/licenses/gpl.html" rel="nofollow">http://www.gnu.org/licenses/gpl.html</a> * * This script is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The goal of this script is to demonstrate issues found with rolling * 3d dice using sendChat() API function * * v0.001 23/12/2020 Initial creation from diceCheck.js * */ var diceCheck = (function() { 'use strict'; var version = 0.001, author = 'RED', pending = null; var PR_Enum = Object.freeze({ YESNO: 'YESNO', CUSTOM: 'CUSTOM', }); var MenuState = Object.freeze({ ENABLED: false, DISABLED: true, }); var flags = { image: false, archive: false, dice3d: true, // RED: v1.207 determine if ChatSetAttr is present canSetAttr: true, }; var design = { grey_button: '"display: inline-block; background-color: lightgrey; border: 1px solid black; padding: 4px; color: dimgrey; font-weight: extra-light;"', selected_button: '"display: inline-block; background-color: white; border: 1px solid red; padding: 4px; color: red; font-weight: bold;"', boxed_number: '"display: inline-block; background-color: yellow; border: 1px solid blue; padding: 2px; color: black; font-weight: bold;"' }; var diceCheck_tmp = (function() { var templates = { button: _.template('&lt;a style="display: inline-block; font-size: 100%; color: black; padding: 3px 3px 3px 3px; margin: 2px 2px 2px 2px; border: 1px solid black; border-radius: 0.5em; font-weight: bold; text-shadow: -1px -1px 1px #FFF, 1px -1px 1px #FFF, -1px 1px 1px #FFF, 1px 1px 1px #FFF; background-color: #C7D0D2;" href="&lt;%= command %&gt;"&gt;&lt;%= text %&gt;&lt;/a&gt;'), confirm_box: _.template('&lt;div style="font-weight: bold; background-color: #FFF; text-align: center; box-shadow: rgba(0,0,0,0.4) 3px 3px; border-radius: 1em; border: 1px solid black; margin: 5px 5px 5px 5px; padding: 2px 2px 2px 2px;"&gt;' + '&lt;div style="border-bottom: 1px solid black;"&gt;' + '&lt;%= message %&gt;' + '&lt;/div&gt;' + '&lt;table style="text-align: center; width: 100%"&gt;' + '&lt;tr&gt;' + '&lt;td&gt;' + '&lt;%= confirm_button %&gt;' + '&lt;/td&gt;' + '&lt;td&gt;' + '&lt;%= reject_button %&gt;' + '&lt;/td&gt;' + '&lt;/tr&gt;' + '&lt;/table&gt;' + '&lt;/div&gt;') }; return { getTemplate: function(tmpArgs, type) { var retval; retval = _.find(templates, function(e,i) { if (type === i) { {return true;} } })(tmpArgs); return retval; }, hasTemplate: function(type) { if (!type) {return false;} return !!_.find(_.keys(templates), function(elem) { {return (elem === type);} }); } }; }()); /** * Init */ var init = function() { if (!state.diceCheck) {state.diceCheck = {};} if (!state.diceCheck.attrsToCreate) {state.diceCheck.attrsToCreate = {};} if (!state.diceCheck.debug) {state.diceCheck.debug = false;} log(`-=&gt; diceCheck v${version} &lt;=-`); }; // ------------------------------------------------ Deal with in-line expressions -------------------------------- /** * In the inline roll evaluator from ChatSetAttr script v1.9 * by Joe Singhaus and C Levett. **/ var processInlinerolls = function (msg) { if (msg.inlinerolls &amp;&amp; msg.inlinerolls.length) { return msg.inlinerolls.map(v =&gt; { const ti = v.results.rolls.filter(v2 =&gt; v2.table) .map(v2 =&gt; v2.results.map(v3 =&gt; v3.tableItem.name).join(", ")) .join(", "); return (ti.length &amp;&amp; ti) || v.results.total || 0; }) .reduce((m, v, k) =&gt; m.replace(`$[[${k}]]`, v), msg.content); } else { return msg.content; } }; // -------------------------------------- make dice rolls and roll queries ------------------------------------ /** * Use a callback from a sendChat dice roll to send the result as a --attkRoll command * rollCmd must be a /roll or a /gmroll dice roll * Alternatively, if rollCmd is anything else, the response will be processed for inline rolls * and the full response returned as a --attkQuery command (useful for roll queries) * If an array of args is supplied, these will be appended to the command string, each separated by '|' * so that they are passed back to the handler **/ var diceRoll = function( rollCmd, rollType, args ) { log( 'diceRoll called'); var rollResult, content; sendChat('',rollCmd,function(ops) { log( 'dice callback made'); _.each( ops, function( resultObj ) { if (resultObj.type == 'rollresult' || resultObj.type == 'gmrollresult') { rollResult = JSON.parse(resultObj.content); if (rollResult) { content = '!attk --attkroll ' + rollType + '|' + rollResult.total; for (let i=0; i&lt;args.length; i++) { content += '|' + args[i]; }; sendPublic( content ); }; } else if (resultObj.type != 'API' ) { rollResult = processInlinerolls( resultObj ); if (rollResult) { content = '!attk --attkroll ' + rollType + '|' + rollResult; for (let i=0; i&lt;args.length; i++) { content += '|' + args[i]; }; sendPublic( content ); }; }; }); }, {use3d:true} ); }; // -------------------------------------------- send messages to chat ----------------------------------------- /** * Send public message with 3d dice rolls (if enabled) */ var sendPublic = function(msg,dice3d,charCS) { if (!msg) {return undefined;} var who, roll3d; if (charCS) { who = 'character|'+charCS.id; } else { who = ''; } roll3d = !!dice3d; sendChat(who,msg,null,{use3d: roll3d}); }; /** * Sends a response with a 3d dice roll (if enabled) to everyone who controls the character */ var sendDiceRoll = function(charCS,msg,as,img) { if (!msg) {return null;} var to, content; if (!charCS || charCS.get('controlledby').length == 0) { to = '/w gm '; } else { to = '/w "' + charCS.get('name') + '" '; } content = to + '&lt;div style="position: absolute; top: 4px; left: 5px; width: 26px;"&gt;' + '&lt;img src="' + (img ? img:fields.feedbackImg) + '"&gt;' + '&lt;/div&gt;' + msg; sendChat((as ? as:fields.feedbackName),content,null,{noarchive:!flags.archive,use3d:flags.dice3d}); }; // -------------------------------------------- utility functions ---------------------------------------------- /** * Find the GM, generally when a player can't be found */ var findTheGM = function() { var playerGM, players = findObjs({ _type:'player' }); if (players.length !== 0) { if (!_.isUndefined(playerGM = _.find(players, function(p) { var player = p; if (player) { if (playerIsGM(player.id)) { return player.id; } } }))) { return playerGM.id; } } return undefined; } // ------------------------------------------ Command Functions -------------------------------------------- /** * Show help message */ var showHelp = function() { var content = '&lt;div style="background-color: #FFF; border: 2px solid #000; box-shadow: rgba(0,0,0,0.4) 3px 3px; border-radius: 0.5em; margin-left: 2px; margin-right: 2px; padding-top: 5px; padding-bottom: 5px;"&gt;' + '&lt;div style="font-weight: bold; text-align: center; border-bottom: 2px solid black;"&gt;' + '&lt;span style="font-weight: bold; font-size: 125%"&gt;DiceCheck v'+version+'&lt;/span&gt;' + '&lt;/div&gt;' + '&lt;div style="padding-left: 5px; padding-right: 5px; overflow: hidden;"&gt;' + '&lt;div style="font-weight: bold;"&gt;' + '!d3check --help' + '&lt;/div&gt;' + '&lt;li style="padding-left: 10px;"&gt;' + 'Display this message' + '&lt;/li&gt;' + '&lt;br&gt;' + '&lt;div style="font-weight: bold;"&gt;' + '!d3check --rolldice roll|message|use3d' + '&lt;/div&gt;' + '&lt;li style="padding-left: 10px;"&gt;' + 'Roll dice using the sendChat() API function.' + '&lt;/li&gt;' + '&lt;li style="padding-left: 20px;"&gt;' + '&lt;b&gt;roll&lt;/b&gt; this set of dice. Use the same format as used for \/roll.' + '&lt;/li&gt;' + '&lt;li style="padding-left: 20px;"&gt;' + '&lt;b&gt;message&lt;/b&gt; to display describing the roll.' + '&lt;/li&gt;' + '&lt;li style="padding-left: 20px;"&gt;' + '&lt;b&gt;use3d&lt;/b&gt; true or false. Passed to sendChat() as the value for the option key \'use3d\'.' + '&lt;/li&gt;' + '&lt;br&gt;' + '&lt;/li&gt;' + '&lt;br&gt;' + '&lt;/div&gt;' + '&lt;/div&gt;'; sendPublic(content); }; /** * Function to handle the internal --attkRoll command and return * a dice roll to where it came from **/ var doDiceRoll = function(args,playerId) { args = args.split('|'); if (args.length &lt; 2) { sendPublic( 'Internal diceCheck roll error' ); showHelp(); return; }; var content = '/roll ' + args[0] + ' ' + args[1] + ' Roll 3d is ', roll3d = !!args[2] || false; content += roll3d; sendPublic( content, roll3d ); }; // -------------------------------------------------------- Event Handlers -------------------------------------------------- /** * Handle chat message event * RED: v1.213 Updated to allow multiple actions per call * This allows procedural/linear processing of activity and overcomes * some of the limitations of Roll20 asynchronous processing */ var handleChatMessage = function(msg) { var args = processInlinerolls(msg), senderId = msg.playerid, selected = msg.selected; if (args.indexOf('!d3check') !== 0) {return;} args = args.split(' --'); args.shift(); _.each(args, function(e) { var arg = e; senderId = msg.playerid; if (_.isUndefined(senderId) || _.isUndefined(getObj('player',senderId))) { if (_.isUndefined(senderId = findTheGM())) { return; } }; if (msg.type === 'api') { if (arg.indexOf('rolldice') === 0) { arg = arg.replace('rolldice','').trim(); doDiceRoll(arg,senderId); } else if (arg.indexOf('help') === 0) { arg = arg.replace('help','').trim(); showHelp(); } else { sendPublic('&lt;span style="color: red;"&gt;Invalid command " &lt;b&gt;'+msg.content+'&lt;/b&gt; "&lt;/span&gt;'); showHelp(); } } }); }; // -------------------------------------------------------------- Register the API ------------------------------------------- /** * Register and bind event handlers */ var registerAPI = function() { on('chat:message',handleChatMessage); }; return { init: init, registerAPI: registerAPI }; }()); on("ready", function() { 'use strict'; diceCheck.init(); diceCheck.registerAPI(); });
1608764091
Oosh
Sheet Author
API Scripter
Yeah, still busted as far as I know. The example straight from the wiki doesn't work.
1609318392
GiGs
Pro
Sheet Author
API Scripter
It was broken before my hiatus from the forum about a month ago. It's disappointing that it is still broken.
Yes, definitely disappointing.&nbsp; My DnD 2E attackMaster API is severely limited without it, as the players really want to see the dice rolls everybody make (for the "ohh well done!" or the "oh, bad luck" type responses).&nbsp; So I'll need to stick with my attack macros library for now, but it does make the attack rolls slow for some players with poor connections or low spec machines.
Can I check if this is going to get looked at in the near future?
1610450157
Laurent
Pro
Sheet Author
API Scripter
I would be surprised if you got any answer.