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 .
Advertisement Create a free account Compendium in Game, Join Today

[Script] ColorEmote -- Release v0.1.2 -- Long form Colored Emotes based on Character, Token, or Player!

1457998937

Edited 1458001247
Saevar L. "Liquid-Sonic" said: Chris said: Alicia's got a point about adding the Character/Token name into this style setting, although I don't think I am having the problem where the text is set right against the image. I think it might be worth considering a merge of the two current settings (Short and Long), to keep the options from getting out of hand. The "Short" setting is cleaner than my original Heading layout, and if it is rebuilt a little we can accomplish everything with one main configuration and a couple simple toggle options, rather than two complete branches. A minor revision of the markup and CSS would allow you to float the image left, and everything else to the right. Start the text side with the optional "Token/ Character/Player Name" row, along with the Turn Tracker icon. Then the emote content proper can be set below it, with a little padding. (Examples shown, with and without Token Name being displayed). For me, that approach would be preferable to getting outrageous with the number of settings and configurations, all with separate style requirements. Dont suppose I could get a copy of this modification :&lt; Saevar, I am not sure if you wanted the script stylings you saw in the image example I used, or if you are simply talking about my suggestions for Aaron to consider for any updated version of his script. But I will share my "modified" version, in case you do want it. I have only changed a few lines (e.g. switching paddings and margins, and adding a line of code with inline styles to get the player name at the top of the Short From display style). As soon as Aaron makes any updates to his script, you'll want to go with that one. Note that this accommodates the particular configuration I prefer when using the script (Token: First; Short Form; Huge Image; No Vignette). Also, I designed my tokens specifically for use in the ColorEmote setup, adding the white image border. That's not being done by the script. One more note: I've added the "Name" back in to the display space. Since I use the Token First setup, it means I can remove it from the output simply by leaving the "Token Name" blank on the actual token. This is great, if you (like me) like to use this script for NPCs, who are sometimes mysterious and whose names are not known by the players. This is part of the power of using Token-based info rather than character sheet info. // Github: &nbsp; <a href="https://github.com/shdwjk/Roll20API/blob/master/C" rel="nofollow">https://github.com/shdwjk/Roll20API/blob/master/C</a>... // By: &nbsp; &nbsp; &nbsp; The Aaron, Arcane Scriptomancer // Contact: &nbsp; <a href="https://github.com/shdwjk/Roll20API/blob/master/C" rel="nofollow">https://github.com/shdwjk/Roll20API/blob/master/C</a>... var ColorEmote = ColorEmote || (function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; var version = '0.1.2', &nbsp; &nbsp; &nbsp; &nbsp; lastUpdate = 1455714420, &nbsp; &nbsp; &nbsp; &nbsp; schemaVersion = 0.4, &nbsp; &nbsp; &nbsp; &nbsp; symbols = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; whitePawn: '&#'+'9830;', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; blackPawn: '&#'+'9830;', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dropDown: '&#'+'9660;' &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; parseOrders = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'character first': ['character','token','player'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'token first': ['token','character','player'] &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; imageScales = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'small': '1em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'medium': '2.5em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'large': '4em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'huge': '6em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'gargantuan': '8em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'colossal': '12em' &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; vignetteModes = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'none': { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border':'0', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius':'0', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color':'none' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'thin-square':{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border':'.1em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius':'.25em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color':'#cccccc' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'thick-square':{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border':'.2em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius':'.25em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color':'#cccccc' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'thin-round':{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border':'.1em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius':'100%', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color':'#cccccc' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'thick-round':{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border':'.2em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius':'100%', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color':'#cccccc' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; defaults = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; button: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border': '1px solid #cccccc', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius': '1em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color': '#006dcc', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'margin': '0 .1em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-weight': 'bold', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '.1em .4em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'color': 'white' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emoteImageContainer: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '0 1em 0 0', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'float': 'left', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'overflow':'hidden' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emoteImage: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'height': 'auto', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'width': 'auto', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'margin-right':'.5em' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emoteHeader: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-bottom': '.2em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '.5em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-size': '1.25em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'text-align': 'center', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'position': 'relative' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emoteBody: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '1em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-size': '1em' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; turnMarker: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color': '#ffffff', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'color': '#1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-style': 'normal', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'margin-right': '-.25em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '0 .125em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-size': '1.25em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'float': 'right', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border': '.1em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius': '100%', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'box-shadow': '#000000 0 0 .1em' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emoteMsg: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border': '.2em solid #1d1d1d', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-style': 'italic', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'font-weight':'bold', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius': '.5em', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'margin': '0 0 0 -45px', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding': '0', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'overflow': 'hidden' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; templates = {}, &nbsp; &nbsp; buildTemplates = function() { &nbsp; &nbsp; &nbsp; &nbsp; templates.cssProperty =_.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%=name %&gt;: &lt;%=value %&gt;;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.style = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'style="&lt;%='+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '_.map(css,function(v,k) {'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'return templates.cssProperty({'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'defaults: defaults,'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'templates: templates,'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'name:k,'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'value:v'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '});'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '}).join("")'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ' %&gt;"' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.button = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;a &lt;%= templates.style({'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'defaults: defaults,'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'templates: templates,'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'css: _.defaults(css,defaults.css.button)'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '}) %&gt; href="&lt;%= command %&gt;"&gt;&lt;%= label||"Button" %&gt;&lt;/a&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.emoteImage = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: _.defaults(ccss||{},defaults.css.emoteImageContainer)}) %&gt; &gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;img &lt;%= templates.style({defaults: defaults,templates: templates,css: defaults.css.emoteImage}) %&gt; src="&lt;%=img %&gt;"/&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.turnMarker = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: _.defaults(css,defaults.css.turnMarker)}) %&gt; &gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; symbols.blackPawn+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.output = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: defaults.css.emoteMsg}) %&gt; &gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: _.defaults({},css,defaults.css.emoteHeader)}) %&gt;&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= templates.emoteImage({img: img, defaults: defaults, templates:templates, ccss: {}, css: defaults.css.emoteImage}) %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;% if(isTurn) { %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= templates.turnMarker({defaults: defaults,templates:templates,css:css.turnMarker}) %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;% } %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= name %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="clear:both;"&gt;&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css:_.defaults(css,defaults.css.emoteBody)}) %&gt;&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= message %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; templates.outputShortForm = _.template( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: defaults.css.emoteMsg}) %&gt; &gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div &lt;%= templates.style({defaults: defaults,templates: templates,css: _.defaults({},css,defaults.css.emoteBody)}) %&gt;&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= templates.emoteImage({img: img, defaults: defaults, templates:templates, ccss: {"font-size":"1.25em"}, css: defaults.css.emoteImage}) %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;% if(isTurn) { %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= templates.turnMarker({defaults: defaults,templates:templates,css:_.defaults({"font-size":"1.5625em"},css.turnMarker)}) %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;% } %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="font-style:normal;font-size:1.15em;padding-top:2px;padding-bottom:0.5em;"&gt;&lt;%= name %&gt;&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;%= message %&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="clear:both;"&gt;&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; setDynamicCSS = function(){ &nbsp; &nbsp; &nbsp; &nbsp; defaults.css.emoteImageContainer = _.defaults(vignetteModes[state.ColorEmote.config.vignetteMode],defaults.css.emoteImageContainer); &nbsp; &nbsp; &nbsp; &nbsp; defaults.css.emoteImageContainer.width = imageScales[state.ColorEmote.config.imageScale]; &nbsp; &nbsp; &nbsp; &nbsp; defaults.css.emoteImageContainer.height = imageScales[state.ColorEmote.config.imageScale]; &nbsp; &nbsp; &nbsp; &nbsp; defaults.css.emoteImage['max-width'] = imageScales[state.ColorEmote.config.imageScale]; &nbsp; &nbsp; &nbsp; &nbsp; defaults.css.emoteImage['max-height'] = imageScales[state.ColorEmote.config.imageScale]; &nbsp; &nbsp; }, &nbsp; &nbsp; getBrightness = function (hex) { &nbsp; &nbsp; &nbsp; var r,g,b; &nbsp; &nbsp; hex = hex.replace('#', ''); &nbsp; &nbsp; r = parseInt(hex.substr(0, 2),16); &nbsp; &nbsp; g = parseInt(hex.substr(2, 2),16); &nbsp; &nbsp; b = parseInt(hex.substr(4, 2),16); &nbsp; &nbsp; return ((r * 299) + (g * 587) + (b * 114)) / 1000; &nbsp; }, &nbsp; &nbsp; counterColor = function(color){ &nbsp; &nbsp; &nbsp; &nbsp; return (getBrightness(color) &lt; (255 / 2)) ? "#FFFFFF" : "#000000"; &nbsp; &nbsp; }, &nbsp; &nbsp; makeOutput = function (name,img,isTurn,message,color){ &nbsp; &nbsp; &nbsp; &nbsp; return templates[(state.ColorEmote.config.shortForm ? 'outputShortForm': 'output')]({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn: isTurn, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: message, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; templates: templates, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaults: defaults, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'color': counterColor(color), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color': color &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }, &nbsp; &nbsp; makeButton = function(command, label, backgroundColor, color){ &nbsp; &nbsp; &nbsp; &nbsp; return templates.button({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command: command, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; label: label, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; templates: templates, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaults: defaults, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color: color, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color': backgroundColor &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }, &nbsp; &nbsp; checkInstall = function() { &nbsp; &nbsp; &nbsp; log('-=&gt; ColorEmote v'+version+' &lt;=- &nbsp;['+(new Date(lastUpdate*1000))+']'); &nbsp; &nbsp; &nbsp; &nbsp; if( ! _.has(state,'ColorEmote') || state.ColorEmote.version !== schemaVersion) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log(' &nbsp;&gt; Updating Schema to v'+schemaVersion+' &lt;'); &nbsp; &nbsp; &nbsp; switch(state.ColorEmote && state.ColorEmote.version) { &nbsp; &nbsp; &nbsp; &nbsp; case 0.3: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.parseOrder = 'character first'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.shortForm = false; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* break; // intentional dropthrough */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'UpdateSchemaVersion': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.version = schemaVersion; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; version: schemaVersion, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; config: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; shortForm: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parseOrder: 'character first', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imageScale: 'medium', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vignetteMode: 'none' &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; setDynamicCSS(); &nbsp; &nbsp; &nbsp; &nbsp; buildTemplates(); &nbsp; &nbsp; }, &nbsp; &nbsp; ch = function (c) { &nbsp; &nbsp; &nbsp; &nbsp; var entities = { &nbsp; &nbsp; &nbsp; '&lt;' : 'lt', &nbsp; &nbsp; &nbsp; '&gt;' : 'gt', &nbsp; &nbsp; &nbsp; "'" : '#39', &nbsp; &nbsp; &nbsp; '@' : '#64', &nbsp; &nbsp; &nbsp; '{' : '#123', &nbsp; &nbsp; &nbsp; '|' : '#124', &nbsp; &nbsp; &nbsp; '}' : '#125', &nbsp; &nbsp; &nbsp; '[' : '#91', &nbsp; &nbsp; &nbsp; ']' : '#93', &nbsp; &nbsp; &nbsp; '"' : 'quot', &nbsp; &nbsp; &nbsp; '-' : 'mdash', &nbsp; &nbsp; &nbsp; ' ' : 'nbsp' &nbsp; &nbsp; }; &nbsp; &nbsp; if(_.has(entities,c) ){ &nbsp; &nbsp; &nbsp; return ('&'+entities[c]+';'); &nbsp; &nbsp; } &nbsp; &nbsp; return ''; &nbsp; }, &nbsp; &nbsp; makeConfigOption = function(config,command,text) { &nbsp; &nbsp; &nbsp; &nbsp; var buttonText = (_.isString(config) ? config : (config ? 'On' : 'Off' )), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color = (config ? '#5bb75b' : '#faa732' ); &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border: 1px solid #ccc;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'border-radius: .2em;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'background-color: white;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'margin: 0 1em;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'padding: .1em .3em;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="float:right;"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; makeButton(command,buttonText,color)+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="clear:both;"&gt;&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; getConfigOption_ShortForm = function() { &nbsp; &nbsp; &nbsp; &nbsp; return makeConfigOption( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.shortForm, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem-config --toggle-short-form', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;b&gt;Short Form&lt;/b&gt; determines if the emote should be condensed into just the header space.' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; getConfigOption_ParseOrder = function() { &nbsp; &nbsp; &nbsp; &nbsp; return makeConfigOption( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.parseOrder+symbols.dropDown, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem-config --set-parse-order ?{Parse Order|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.parseOrder+' (current),'+ state.ColorEmote.config.parseOrder+'|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.keys(parseOrders).join('|')+'}', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;b&gt;Parse Order&lt;/b&gt; determines the order which images are searched for between Characters, Tokens, and Players.' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; getConfigOption_ImageScale = function() { &nbsp; &nbsp; &nbsp; &nbsp; return makeConfigOption( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.imageScale+symbols.dropDown, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem-config --set-image-scale ?{Image Scale|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.imageScale+' (current),'+ state.ColorEmote.config.imageScale+'|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.keys(imageScales).join('|')+'}', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;b&gt;Image Scale&lt;/b&gt; determines the size of the representative image in the header of an emote.' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; getConfigOption_VignetteMode = function() { &nbsp; &nbsp; &nbsp; &nbsp; return makeConfigOption( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.vignetteMode+symbols.dropDown, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem-config --set-vignette-mode ?{Vignette Mode|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.vignetteMode+' (current),'+ state.ColorEmote.config.vignetteMode+'|'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.keys(vignetteModes).join('|')+'}', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;b&gt;Vignette Mode&lt;/b&gt; determines how the representative image is framed and clipped.' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; getAllConfigOptions = function() { &nbsp; &nbsp; &nbsp; &nbsp; return getConfigOption_ShortForm() + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getConfigOption_ParseOrder() + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getConfigOption_ImageScale() + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getConfigOption_VignetteMode(); &nbsp; &nbsp; }, &nbsp; &nbsp; showHelp = function(playerid) { &nbsp; &nbsp; &nbsp; &nbsp; var who=getObj('player',playerid).get('_displayname'); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w "'+who+'" '+ '&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;'+ &nbsp; '&lt;div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;"&gt;'+ &nbsp; &nbsp; 'ColorEmote v'+version+ &nbsp; '&lt;/div&gt;'+ &nbsp; '&lt;div style="padding-left:10px;margin-bottom:3px;"&gt;'+ &nbsp; &nbsp; '&lt;p&gt;ColorEmote provides a long form emote block with a colored background and header based on the Character, Token, or Player speaking. &nbsp;The header contains a representative image for the speaker (Character Avatar, Token Image, or Player Image) as well as the name of the speaker.&lt;/p&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;p&gt;The speaker is the first one of the following to be found:&lt;/p&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;ol&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;An explicit Token or Character ID specified with the bracketed command syntax:'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;pre style="white-space:normal;word-break:normal;word-wrap:normal;"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem'+ch('[')+ch('@')+ch('{')+'target'+ch('|')+'token_id'+ch('}')+ch(']')+' Does the things!'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/pre&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;The selected token'+ch("'")+'s character.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;The selected token.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;The character the player is speaking as.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;The player.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/ol&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;p&gt;Background color is determined based on what is speaking. &nbsp;The foreground color will be either black or white depending on the brightness of the background color. &nbsp;The background color is chosen using the following methods:&lt;/p&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;ul&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;&lt;b&gt;Characters&lt;/b&gt; will have the color stored in an attribute named &lt;b&gt;color&lt;/b&gt; or the player color. &nbsp;The &lt;b&gt;color&lt;/b&gt; attribute must be specified in standard html form with the # sign. &nbsp;ex: #ff3322 or #f32 &lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;&lt;b&gt;Tokens&lt;/b&gt; will have their aura2 color.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;li&gt;&lt;b&gt;Players&lt;/b&gt; will have their player color.&lt;/li&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/ul&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;p&gt;If it is currently the speaker'+ch("'")+'s turn, a black pawn ('+symbols.blackPawn+') on a white circle will be displayed on the right side. (Does not apply to Players speaking.)&lt;/p&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; '&lt;p&gt;Multi-line emote messages may be specified by surrounding them in '+ch('{')+ch('{')+' and '+ch('}')+ch('}')+'. &nbsp;You can insert new lines by pressing shift-enter. &nbsp;Example:&lt;/p&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;pre style="white-space:normal;word-break:normal;word-wrap:normal;"&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '!cem {{ Does the things!&lt;br&gt;&lt;br&gt;But it fails in the usual way... }}'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/pre&gt;'+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; '&lt;/div&gt;'+ &nbsp; '&lt;b&gt;Commands&lt;/b&gt;'+ &nbsp; '&lt;div style="padding-left:10px;"&gt;'+ &nbsp; &nbsp; '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!cem'+ch('[')+' token_id '+ch('|')+' character_id '+ch(']')+' '+ch('[')+' '+ch('&lt;')+'Message'+ch('&gt;')+' '+ch('|')+' '+ch('{')+ch('{')+' '+ch('&lt;')+'Multi-line Message'+ch('&gt;')+' '+ch('}')+ch('}')+' '+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ &nbsp; &nbsp; '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ &nbsp; &nbsp; &nbsp; '&lt;p&gt;Outputs an Emote. Note that the optional bracketed syntax has no space between the !cem and leading '+ch('[')+'.&lt;/p&gt;'+ &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; '&lt;div style="padding-left:10px;"&gt;'+ &nbsp; &nbsp; '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!wcem'+ch('[')+' token_id '+ch('|')+' character_id '+ch(']')+' '+ch('[')+' '+ch('&lt;')+'Message'+ch('&gt;')+' '+ch('|')+' '+ch('{')+ch('{')+' '+ch('&lt;')+'Multi-line Message'+ch('&gt;')+' '+ch('}')+ch('}')+' '+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ &nbsp; &nbsp; '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ &nbsp; &nbsp; &nbsp; '&lt;p&gt;Identical to !cem except that the output is whispered to the player emoting and the GM.&lt;/p&gt;'+ &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; ( playerIsGM(playerid) &nbsp; &nbsp; &nbsp; &nbsp; ? &nbsp;'&lt;b&gt;Configuration&lt;/b&gt;' + getAllConfigOptions()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : '' &nbsp; &nbsp; )+ '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; getCharacterAndTokenTurn = function(){ &nbsp; &nbsp; &nbsp; &nbsp; var token = getObj('graphic',(JSON.parse(Campaign().get('turnorder')||'[]')[0]||{id:null}).id); &nbsp; &nbsp; &nbsp; &nbsp; if(token){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cid: token.get('represents'), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tid: token.id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cid:null, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tid:null &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; }, &nbsp; &nbsp; performOutput = function(details){ &nbsp; &nbsp; &nbsp; &nbsp; var output=makeOutput(details.name,details.img,details.isTurn,details.message,details.color); &nbsp; &nbsp; &nbsp; &nbsp; if(details.whisper){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w gm '+output); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(!playerIsGM(details.playerid)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+details.who+' '+output); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct '+output); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; handleInput = function(msg_orig) { &nbsp; &nbsp; &nbsp; &nbsp; var msg = _.clone(msg_orig), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args, cmd, matches, ctid, turnData, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parsers={}, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; player,character,token,data, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img, name, text, color,who, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn = false, whisper=false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; &nbsp; &nbsp; &nbsp; &nbsp; if (msg.type !== "api") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if(_.has(msg,'inlinerolls')){ &nbsp; &nbsp; &nbsp; msg.content = _.chain(msg.inlinerolls) &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m['$[['+k+']]']=v.results.total || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m; &nbsp; &nbsp; &nbsp; &nbsp; },{}) &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m.replace(k,v); &nbsp; &nbsp; &nbsp; &nbsp; },msg.content) &nbsp; &nbsp; &nbsp; &nbsp; .value(); &nbsp; &nbsp; } &nbsp; &nbsp; args = msg.content &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .replace(/&lt;br\/&gt;\n/g, '&lt;br/&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .replace(/(\{\{(.*?)\}\})/g," $2 ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .split(/\s+/); &nbsp; &nbsp; &nbsp; &nbsp; cmd=args.shift(); &nbsp; &nbsp; &nbsp; &nbsp; matches=cmd.match(/^(!\S+)\[([^\]]+)\]/); &nbsp; &nbsp; &nbsp; &nbsp; if(matches){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cmd=matches[1]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctid=matches[2]; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; switch(cmd) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '!wcem': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; whisper=true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* break; // intentional drop thru */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '!cem': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( 0 === args.length || _.contains(args,'--help')) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showHelp(msg.playerid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; player=getObj('player',msg.playerid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; turnData=getCharacterAndTokenTurn(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text=args.join(' '); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // explicit token &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(ctid){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character=getObj('character',ctid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token=getObj('graphic',ctid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // selected token's character or token &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !(character || token) && msg.selected && msg.selected.length){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token=getObj('graphic',(_.find(msg.selected,function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'graphic'===o._type; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })||{_id:null})._id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character=getObj('character',(token && token.get('represents'))||''); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // speaking as character &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !(character || token) ){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character=filterObjs(function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'character'===o.get('type') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; && o.id === player.get('speakingas').split(/\|/)[1]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })[0]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parsers={ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character: function(){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name=character.get('name'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn = character.id === turnData.cid; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color=getAttrByName(character.id,'color'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color=(color && color.match(/#[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?/) ? color : player.get('color') ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character.get('defaulttoken',function(dt){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img=character.get('avatar') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || (JSON.parse(dt||'')||{imgsrc:''}).imgsrc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || '<a href="https://app.roll20.net/users/avatar/'+player.get('d20userid')+'/150#.png" rel="nofollow">https://app.roll20.net/users/avatar/'+player.get('d20userid')+'/150#.png</a>'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; performOutput({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerid: msg.playerid, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; who: player.get('displayname'), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn: isTurn, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color: color, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; whisper: whisper, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: text &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; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token: function(){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name=token.get('name'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img=token.get('imgsrc'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn = token.id === turnData.tid; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color=token.get('aura2_color')||player.get('color'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; performOutput({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerid: msg.playerid, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; who: player.get('displayname'), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn: isTurn, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color: color, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; whisper: whisper, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: text &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; player: function(){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name=player.get('displayname'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img='<a href="https://app.roll20.net/users/avatar/'+player.get('d20userid')+'/150#.png" rel="nofollow">https://app.roll20.net/users/avatar/'+player.get('d20userid')+'/150#.png</a>'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color=player.get('color'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; performOutput({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerid: msg.playerid, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; who: player.get('displayname'), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isTurn: isTurn, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color: color, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; whisper: whisper, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message: text &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; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data={ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character:character, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token:token, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; player:player &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.find(parseOrders[state.ColorEmote.config.parseOrder],function(k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(data[k]){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parsers[k](); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true; &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; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '!cem-config': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(!playerIsGM(msg.playerid)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args = _.rest(msg.content.split(/\s+--/)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.contains(args,'help')) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showHelp(msg.playerid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; who=getObj('player',msg.playerid).get('_displayname'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(!args.length) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w "'+who+'" '+ '&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;'+ &nbsp; '&lt;div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;"&gt;'+ &nbsp; &nbsp; 'ColorEmote v'+version+ &nbsp; '&lt;/div&gt;'+ &nbsp; &nbsp; '&lt;b&gt;Configuration&lt;/b&gt;'+ &nbsp; &nbsp; getAllConfigOptions()+ '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each(args,function(a){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var opt=a.split(/\s+/); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(opt.shift()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'toggle-short-form': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.shortForm=!state.ColorEmote.config.shortForm; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w "'+who+'" ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +getConfigOption_ShortForm() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &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; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'set-parse-order': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opt=opt.join(' '); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(parseOrders,opt)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.parseOrder=opt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +getConfigOption_ParseOrder() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div&gt;&lt;b&gt;Unsupported Parse Order:&lt;/div&gt; '+opt+'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'set-image-scale': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(imageScales,opt[0])){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.imageScale=opt[0]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +getConfigOption_ImageScale() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setDynamicCSS(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div&gt;&lt;b&gt;Unsupported Image Scale:&lt;/div&gt; '+opt[0]+'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'set-vignette-mode': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(vignetteModes,opt[0])){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.ColorEmote.config.vignetteMode=opt[0]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +getConfigOption_VignetteMode() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setDynamicCSS(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div&gt;&lt;b&gt;Unsupported Vignette Mode:&lt;/div&gt; '+opt[0]+'&lt;/div&gt;' &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; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/w '+who+' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div&gt;&lt;b&gt;Unsupported Option:&lt;/div&gt; '+a+'&lt;/div&gt;' &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; &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; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; registerEventHandlers = function() { &nbsp; &nbsp; &nbsp; &nbsp; on('chat:message', handleInput); &nbsp; &nbsp; }; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; CheckInstall: checkInstall, &nbsp; &nbsp; &nbsp; &nbsp; RegisterEventHandlers: registerEventHandlers &nbsp; &nbsp; }; &nbsp; &nbsp;&nbsp; }()); on('ready',function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; ColorEmote.CheckInstall(); &nbsp; &nbsp; ColorEmote.RegisterEventHandlers(); }); &nbsp;
I've found what I believe is a bug: When I use the full hex for a dark background color— e.g. #006600 — the text correctly renders as white. However, when I use the shorthand hex— #060 — the text renders as black (on, in this case, dark green). Thought you'd like to know! Awesome script, as always! :-)
1458221423
The Aaron
Forum Champion
API Scripter
Ah, I'll add that to the list of things to fix, thanks!
Yeap I did want your version of it. Thanks! :)