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

Whisper on an API that doesn't have a whisper mode

1639361665
Jiboux
Pro
Sheet Author
Compendium Curator
Hello all, This may seem a very basic question, but I couldn't find the answer on the Wiki... I just installed 2 apis (fumbler and namegen), that don't seem to have their own whisper toggle ( i.e. they don't seem to accept a !fumble -w) As a GM, I prefer the players not to know if I am improvising or not, so I wouldn't like them to see the name coming from the name generator in the chat. Is there any way in the syntax to call the API to declare to roll20 that any result it sends to the chat are for my eyes only ?
1639362653
Andrew R.
Pro
Sheet Author
You could wrap them in a ScriptCards macro, perhaps? 
1639364445
David M.
Pro
API Scripter
Even called from a scriptcard, though, the individual scripts would still output normally. I couldn't find the namegen script, but you could try this modification of fumbler based on the one-click version. I just added a "/w gm " to the start of the four sendChat commands so it will always whisper to GM. var fumbler = fumbler || (function() { 'use strict'; let version = '0.2.0', /* Eclectic collection of fumbles */ fumble = [ {low: 1, high: 10, result: "Distracted", effect: "Roll DEX or fall down."}, {low: 11, high: 14, result: "Negligent", effect: "Fall down."}, {low: 15, high: 20, result: "Careless", effect: "Lost footing. -1 to hit on next turn."}, {low: 21, high: 25, result: "Delinquent", effect: "Slip. Do the splits. -2 to hit on next turn."}, {low: 26, high: 39, result: "Clumsy", effect: "Fall down. Roll DEX or drop primary weapon."}, {low: 40, high: 50, result: "Very Clumsy", effect: "Fall, drop primary weapon, roll DEX or be stunned for 1 round."}, {low: 51, high: 53, result: "Useless", effect: "Fall. Stunned for 1 round."}, {low: 54, high: 57, result: "Dazed", effect: "Fall. Drop primary weapon. Stunned for 1 round."}, {low: 58, high: 59, result: "Stunned", effect: "Fall. Stunned for 1 round."}, {low: 60, high: 60, result: "Dazed and Stunned", effect: "Fall. Drop primary weapon. Stunned for 1d4 rounds."}, {low: 61, high: 61, result: "Unconscious", effect: "Fall, knocked head on floor, knocked out for 1d4 rounds."}, {low: 62, high: 62, result: "Inept", effect: "Weapon disarmed by opponent and thrown d20 ft in random direction."}, {low: 63, high: 64, result: "Very Inept", effect: "Weapon or appendage breaks or is broken."}, {low: 65, high: 65, result: "Fail", effect: "Hit Self in groin. Roll CON or double over in pain, go last next round."}, {low: 66, high: 66, result: "Loser", effect: "Hit Self in groin. Double over in pain, go last next round."}, {low: 67, high: 67, result: "Klutz", effect: "Twist ankle, 1/2 movement."}, {low: 68, high: 69, result: "Dangerous Klutz", effect: "Twist knee, 1/4 movement."}, {low: 70, high: 70, result: "Untrained", effect: "Twist wrist, weapon arm incapacitated, drop weapon."}, {low: 71, high: 71, result: "Vulnerable", effect: "Opponent steps on foot, go last next round."}, {low: 72, high: 72, result: "Knocked Silly", effect: "Helm twists, blind till end of next round. Roll again if not wearing helm."}, {low: 73, high: 74, result: "Poor Judgement", effect: "Wrong move, opponent's next attack +4 to hit."}, {low: 75, high: 76, result: "Handled Badly", effect: "Knuckles hit, -4 to hit until next round."}, {low: 77, high: 79, result: "Embarrassing", effect: "Armor piece knocked off, strap cut, belt cut, clothes torn, lose 2 AC until fixed."}, {low: 80, high: 80, result: "Nards", effect: "Opponent's parry hits groin, 1/2 move, -4 to hit for 3 rounds."}, {low: 81, high: 81, result: "Not Funny", effect: "Opponent's parry hits funny bone in weapon arm, -2 damage for 3 rounds."}, {low: 82, high: 82, result: "Blind Eye", effect: "Dirt blinds one eye, -1 to hit until cleaned."}, {low: 83, high: 83, result: "Blind Mans Bluff", effect: "Dirt blinds two eyes, -3 to hit until cleaned."}, {low: 84, high: 85, result: "Fool", effect: "Hit self. Normal damage."}, {low: 86, high: 86, result: "Useless Fool", effect: "Hit self. Normal damage. Stunned for 1 round."}, {low: 87, high: 88, result: "Moron", effect: "Hit self. Double damage."}, {low: 89, high: 89, result: "Useless Moron", effect: "Hit self. Double damage. Stunned for 1 round."}, {low: 90, high: 90, result: "Complete Moron", effect: "Hit self. Critical hit."}, {low: 91, high: 92, result: "Unaware", effect: "Hit friend, normal damage."}, {low: 93, high: 93, result: "Very Unaware", effect: "Hit friend, normal damage. Friend stunned for 1 round."}, {low: 94, high: 95, result: "Unaware Moron", effect: "Hit friend, double damage."}, {low: 96, high: 96, result: "Liability", effect: "Hit friend, double damage. Friend stunned for 1 round."}, {low: 97, high: 97, result: "Big Liability", effect: "Hit friend. Critical hit."}, {low: 98, high: 98, result: "Big Trouble", effect: "Roll twice on fumble chart. If this comes up again re-roll."}, {low: 99, high: 99, result: "Big Trouble in Little China", effect: "Roll thrice on fumble chart. If this comes up again re-roll."}, {low: 100, high: 100, result: "Disaster", effect: "Roll thrice on fumble chart. If this comes up again add two more rolls."} ], /** * Given a fumble chart name (handouts without the 'fumbler-' return the handout object) * @param chartName * @returns {T} */ getFumblerHandout = function (chartName) { let handouts = findObjs({_type: "handout"}); return _.find(handouts, function (handout) { return (handout.get('name') === 'fumbler-' +chartName); }); }, /** * Utility function to determine if a variable is a number. * @param obj * @returns {boolean} */ isNumeric = function(obj) { return !isNaN(obj - parseFloat(obj)); }, /** * Display in chat the result of the fumble for the given chart and roll. * @param fumbleChart * @param rolled */ showFumble = function(fumbleChart, rolled) { let whoops = _.find(fumbleChart, function (idiot) { return (rolled >= idiot.low && rolled <= idiot.high); }); // Sanity check if (whoops) { // Send the fumble result as a formatted string in chat sendChat('Fumbler', "/w gm " + rolled.toString() + "% <b>" + whoops.result + "</b><br>" + whoops.effect); } else { sendChat('Fumbler', '/w gm Invalid % roll given, or something went wrong. GM makes something up.'); } }, /** * Performs the actual logic to determine what chart to use and roll value. * @param fumbleParams */ parseFumble = function(fumbleParams) { let rolled = randomInteger(100); // Default to a random roll. let chart = fumble; // Use the default fumble chart. // No parameters so display the default chart and a random roll. if (fumbleParams.length === 0) { showFumble(chart, rolled); return; } // Single parameter that is numeric so set the roll value to the parameter and use the default fumble chart. if (fumbleParams.length === 1 && isNumeric(fumbleParams[0])) { rolled = parseInt(fumbleParams[0]); showFumble(chart, rolled); return; } // Two parameters so the second parameter must be a percentage. if (fumbleParams.length === 2) { rolled = parseInt(fumbleParams[1]); } // The 1st parameter is the name of the fumble chart (without 'fumbler-') in the handout. let fumbleHandout = getFumblerHandout(fumbleParams[0]); if (fumbleHandout) { // URI-escape the notes and remove the HTML elements from the notes. fumbleHandout.get('notes', function (notes) { try { notes = decodeURIComponent(notes).trim(); } catch (err) { notes = decodeURI(notes).trim(); } if (notes) { try { notes = notes.split(/<[/]?.+?>/g).join(''); chart = JSON.parse(notes); showFumble(chart, rolled) } catch (err) { sendChat('Fumbler', '/w gm The fumble chart handout has errors: ' + err.message); } } }); } else { sendChat('Fumbler', '/w gm Can not find the fumble chart handout named: ' + fumbleParams[0]); } }, /** * Handle chat events * * @param {object} msg */ handleChatMessage = function(msg) { // Is the message the `!fumble` command? if (msg.type !== "api") { return; } if (msg.content.substr(0,7) !== "!fumble") { return; } let content = msg.content; let words = content.split(' '); // Split each word into an array. words.shift(); // Remove "!fumble" parseFumble(words); // Parse the fumble parameters. }, /** * Start fumbler and handle chat events. */ init = function() { log('Starting Fumbler v' + version); on("chat:message", function(msg) { handleChatMessage(msg) }); }; return { init: init }; }()); /** * Fires when the page has loaded. */ on("ready", function() { 'use strict'; fumbler.init(); });
1639366083
Jiboux
Pro
Sheet Author
Compendium Curator
Thanks !!