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 Roll from Handout

I have figured out how to roll dice from a handout.  Can I Whisper Roll (default template) a roll to the chat?
1763086029
timmaugh
Forum Champion
API Scripter
Yes, but it takes a little setup. The problem is that when you use a colon in a link in a handout (like you have to for template designation), it immediately changes it to the HTML entity :, then the template designation gets eaten when you try to send the message. You only get the text of the trailing syntax of un-templated fields. To get around this, create an attribute on a character sheet (I created a character called "SyntaxMule" that I'll use for this). The attribute I called "template default", and I put this into the current value of that attribute: &{template:default} That "offloads" the colon to a later resolution, allowing your command to continue. So from there, you just have to edit your handout, write the verbiage that will serve as the hyperlinked text, then select it and click on the "Insert Link" button. In the destination field, write something like: `/w gm @{SyntaxMule|template default} {{name=D100 Roll}} {{Roll=[[1d100]]}} That is obviously a basic d100 roll, but you can format the template however you see fit. Just start your link with the tick mark, then the "whisper" syntax (/w gm), followed by the reference to your new attribute, and finally any template parts you want to include.
Do I have it correct here?
1763164695
timmaugh
Forum Champion
API Scripter
Yes. That should work.
With the script in the handout it does nothing.  I have to have something wrong. `/w gm @{SyntaxMule|template default} {{name=D100 Roll}} {{Roll=[[1d100]]}}   
1763170911

Edited 1763170977
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
spolebitski  said: With the script in the handout it does nothing.  I have to have something wrong. `/w gm @{SyntaxMule|template default} {{name=D100 Roll}} {{Roll=[[1d100]]}}   Hi spolebitski! You have a space in the attribute name in your example. Try: `/w gm @{SyntaxMule|templatedefault} {{name=D100 Roll}} {{Roll=[[1d100]]}}  
Thank You Keith!  It works.
So this script is working&nbsp; `/w gm @{SyntaxMule|templatedefault} {{name=Obadiah The Harbinger}} {{Loot=[[5d6]] CP}}&nbsp; However when I exit roll 20 (and return to roll 20) the script changes to this <a href="https://app.roll20.net/editor/%60/w%20gm%20@%7BSyntaxMule%7Ctemplatedefault%7D%20%7B%7Bname=Obadiah%20The%20Harbinger%7D%7D%20%7B%7BLoot=[[5d6]]%20CP%7D%7D" rel="nofollow">https://app.roll20.net/editor/%60/w%20gm%20@%7BSyntaxMule%7Ctemplatedefault%7D%20%7B%7Bname=Obadiah%20The%20Harbinger%7D%7D%20%7B%7BLoot=[[5d6]]%20CP%7D%7D</a> It then says "page not found".&nbsp; Anyway to not have the script change?
1763317541
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
What is happening is that the HTML in the link is expanding (spaces being replaced by %20, for instance). This happens when you copy and paste the button in a handout. I assume that's what's going on--buttons that aren't copied and pasted generally preserve their link just fine. Here is a short script that the Aaron wrote for me that keeps this from happening. If you open the handout with the bad button, and make a change anywhere, this script should fix it when you save, and keep future buttons from misbehaving. on('ready',()=&gt;{ &nbsp; const JournalCommandDecoder = (t) =&gt; { &nbsp; &nbsp; const fixStart = t =&gt; t.replace(/^"https:\/\/app.roll20.net\/editor\/%60/,'"`'); &nbsp; &nbsp; const percentOut = t =&gt; t.replace(/%{/g,'::PERCENT_OPEN_CURLY::'); &nbsp; &nbsp; const percentIn = t =&gt; t.replace(/::PERCENT_OPEN_CURLY::/g,'%{'); &nbsp; &nbsp; return percentIn(decodeURIComponent(percentOut(fixStart(t)))); &nbsp; }; &nbsp; const fixHandoutURLs = (data) =&gt; { &nbsp; &nbsp; const re = new RegExp(`"<a href="https://app.roll20.net/editor/%60[^&quot;]*&quot;`,'g" rel="nofollow">https://app.roll20.net/editor/%60[^"]*"`,'g</a>'); &nbsp; &nbsp; return data.replace(re,JournalCommandDecoder); &nbsp; }; &nbsp; const alterHandout = (obj)=&gt;obj.get('notes',(notesPrime)=&gt;obj.get('gmnotes',(gmnotesPrime)=&gt;{ &nbsp; &nbsp; let notes = fixHandoutURLs(notesPrime); &nbsp; &nbsp; let gmnotes = fixHandoutURLs(gmnotesPrime); &nbsp; &nbsp; if(notes !== notesPrime){ &nbsp; &nbsp; &nbsp; setTimeout(()=&gt;obj.set('notes',notes), 1000); &nbsp; &nbsp; } &nbsp; &nbsp; if(gmnotes !== gmnotesPrime){ &nbsp; &nbsp; &nbsp; setTimeout(()=&gt;obj.set('gmnotes',gmnotes), 2000); &nbsp; &nbsp; } &nbsp; })); &nbsp; on('chat:message',msg=&gt;{ &nbsp; &nbsp; if('api'===msg.type &amp;&amp; /^!fix-all-handout-urls(\b\s|$)/i.test(msg.content) &amp;&amp; playerIsGM(msg.playerid)){ &nbsp; &nbsp; &nbsp; const who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); &nbsp; &nbsp; &nbsp; let handouts=findObjs({type:'handout'}); &nbsp; &nbsp; &nbsp; let c = handouts.length; &nbsp; &nbsp; &nbsp; sendChat('',`/w "${who}" processing ${c} handout(s)"`); &nbsp; &nbsp; &nbsp; const burndown = () =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; let h = handouts.shift(); &nbsp; &nbsp; &nbsp; &nbsp; if(h) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; alterHandout(h); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setTimeout(burndown,0); &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('',`/w "${who}" examined ${c} handout(s)"`); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; burndown(); &nbsp; &nbsp; } &nbsp; }); &nbsp; on('change:handout',alterHandout); });
1763318423
vÍnce
Pro
Sheet Author
@Keith thank you for sharing The Aaron's patch/code.&nbsp; Why isn't this the "built-in" behavior for the VTT?&nbsp;&nbsp;(not directed at you obviously) :-)
1763320249
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
I am actually in the process of following up on that.