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

Line Breaks in an attribute - pass to template through script?

I noticed that the ability descriptions in my script cut off after line breaks. The formatting for the ability descriptions is necessary due to the wide range of ability types in the game I'm coding; some have success/fail conditions, some have upgrades, and it's much easier to include it all in one text field.  Before, I just sent these descriptions out via default template roll buttons and they worked fine, but I decided I wanted to do launch custom FX linked to the custom character sheets, so API was necessary.  Now, those descriptions are cutting off at the first line break.  No error message, but the rest is pasted outside of the roll template. Is there any way around this? I've looked for solutions but can't seem to find anyone addressing this.  Should I be using splitArgs somehow?  I'm at a loss.  The description attribute I have to output is "power", and it usually looks like: Make a Basic attack Roll Success: Do a thing. Failure: Do the thing, but at half effect and suffer X. Upgrade 1: Do it faster Upgrade 2: Do it cooler. Here's the button input: !fxpower --@{character_id} --@{target|character_id} --@{powername} --@{powercost} --@{powerfx} --@{selected|token_id} --@{target|token_id} --@{power} Here's the code: // wait till the ready event before registering a chat handler on('ready', () => {     // create a function to return attribute value, given character id and attribute name.     const getLocation = function(id, choice) {         let location = parseInt((findObjs({             type: 'attribute',             characterid: id,             name: choice         })[0] || {             get: () => -1         }).get('current'));         return location;     }; on('chat:message', (msg) => {         // make sure the message is an api command, then verify it starts with !fxpower         if ('api' === msg.type && /^!fxpower\b/i.test(msg.content)) {           const args = msg.content.split(/\s+--/);           log(args);             let c = getObj('character',args[1]);                      // verify we got a character             if(c){                          let name = getAttrByName(c.id, "character_name");     let skillAttr = findObjs({type:'attribute',characterid:args[1]})     log(name);           let t = getObj('character',args[2]);              if (t) {                                     let tname = getAttrByName(t.id, "character_name");                 log(tname);                         const pname = args[3];             const cost = args[4];              const fx = args[5];             log(fx);             const ctoken = args[6];             const ttoken = args[7];             const power = args[8];             log(power);             //find the right custom fx based on the attribute             let fxid = findObjs({_type: "custfx", name: fx})[0].id;             log(fxid);             //find the coordinates of a             const tokenCenter = (id) => {                 const token = getObj('graphic', id);               return {                x: Math.round(token.get('left')),                 y: Math.round(token.get('top'))           }         }; let output = `&{template:default} {{name= ${name} }} {{POWER= ${pname} }} {{COST= ${cost} }} {{DESC.= ${power} }}`;             sendChat('', output);                             if ((fx == "hammer") || (fx == "melee") || (fx == "stab") || (fx == "bite")){             let p = tokenCenter(ttoken);             spawnFx(p.x, p.y, fxid)             } else {             spawnFxBetweenPoints(tokenCenter(ctoken), tokenCenter(ttoken), fxid);             log(tokenCenter(ttoken));             log(tokenCenter(ctoken));             log(spawnFxBetweenPoints(tokenCenter(ctoken), tokenCenter(ttoken), fxid));             }            }           }         }     });  });      
1584846452
The Aaron
Roll20 Production Team
API Scripter
The reason this happens is because @{} references and ?{} queries perform simple substitutions before sending to the API.  The chat system sends each line as a separate message, so if an attribute has a line break in it, that signals a new command in chat.  If you take the ! off the front of a command, you can get a pretty good idea of what the API will see based on the text that shows up. There are two ways of handling this, both of which require a change to the script and they way you call it. 1) Delay attribute lookups until the API If instead of using a @{} reference, you pass the character id and attribute name, you can get the contents of the attribute and parse it in the API directly.  This avoids any issues with what might be in the attribute, but isn't a general purpose solution if you are wanting to embed the contents of an attribute in a larger string. 2) Wrap the arguments in {{ }} When Roll Templates were introduced, they brought with them a very handy change to the chat parser.  Since Roll Templates needed to included multi-line content, the parser will ignore line breaks wrapped in {{ }} when breaking input into separate messages.  You can take advantage of that by wrapping your arguments in {{ }}: !fxpower {{ --@{character_id} --@{target|character_id} --@{powername} --@{powercost} --@{powerfx} --@{selected|token_id} --@{target|token_id} --@{power} }} You'll get something like this for the message content: { "content": "!fxpower {{ ---Lff-orDvRF3prPQLBCl ---Kdzm9eFLbe149295ZQO --Sponge Bob<br/>\nSquare Pants<br/>\nPineapple<br/>\nUnder the Sea --$9.99 --LucasFilm ---LwRbrLYUPH5TdVZmMeH ---LwjcSvivC511Bm2ujKi --Pure Energy }}", "playerid": "-JS3qKxIUPHLzSbK24ve", "type": "api", "who": "The Aaron (GM)" } Which you will then need to parse to handle correctly.