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

[tokenmod][shaped][5e] New Player Token Setup

Ok, so a couple of weird things are happening in this process. &nbsp;I'll try to be as detailed as possible. 1) My players are not seeing "Use Selected Token" in their character sheet (which is beyond odd, because when I was playing I thought I remember seeing it. &nbsp;Now that I'm a GM, I sometimes have NO idea what players see) so they can't select and move a token from the startup token board. &nbsp;This was a slight embarrassment to Session Zero tonight. &nbsp;***Cringes*** 2) So ok, enter GM to the rescue. &nbsp;Well, 5 players... &nbsp;So I wanted to automate as much as possible to limit the time spent on this. &nbsp;I went to&nbsp; <a href="https://www.youtube.com/watch?v=V2h8LdK0gTs&amp;t=347s" rel="nofollow">https://www.youtube.com/watch?v=V2h8LdK0gTs&amp;t=347s</a> &nbsp;to see some solutions (you don't have to watch that, but the description contains related macros) and I thought, I can modify that to suit my needs. /w gm &amp;{template:5e-shaped}{{title=Token Setup for @{selected|character_name}}}{{ ... Setup Begun... }} !token-mod {{ --set bar1_link|hp --set bar2_link|ac --set bar3_link|speed --set name|@{selected|character_name} --on showname --on showplayers_name --on showplayers_bar1 --on showplayers_aura1 --on showplayers_aura2 --on light_hassight }} !token-mod {{?{What Type of Vision - DIM/BRIGHT|None / Blind,--set light_radius&amp;#124; --set light_dimradius&amp;#124; --off light_otherplayers |Torch - 40/20, --set light_radius&amp;#124;40 --set light_dimradius&amp;#124;20 --on light_otherplayers |Lantern or Sunrod - 60/30, --set light_radius&amp;#124;60 --set light_dimradius&amp;#124;30 --on light_otherplayers |Lamp - 30/15, --set light_radius&amp;#124;30 --set light_dimradius&amp;#124;15 --on light_otherplayers |Candle - 5/0, --set light_radius&amp;#124;5 --set light_dimradius&amp;#124;0 --on light_otherplayers |Dark Vision 60/0, --set light_radius&amp;#124;60 --set light_dimradius&amp;#124;0 --off light_otherplayers |Devil Sight 120/0, --set light_radius&amp;#124;120 --set light_dimradius&amp;#124;0 --off light_otherplayers}}} /w gm &amp;{template:5e-shaped}{{title=Token Setup for @{selected|character_name}}}{{... Setup Completed...}} That yielded no feedback (not even errors) at the API screen, or results on the selected token, only the Setup Begun and Setup Completed messages in chat (It LIED!!! &nbsp;lol.) 3) Is there a way to use a roll query to assign who a brand new token represents? &nbsp;That I would also like to setup as the first line in this global macro, which I imagine would need a moment to process before moving on to the next bits, though I don't know if that would matter so much. &nbsp;If it does, some of the non-character specifics (turning on showname, hassight, auras,) could be run until the character specifics get involved.
1531756916

Edited 1531759921
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
You can set the represented character with&nbsp; represents|@{bob|character_id} or !token-mod {{ --set represents|rook controlledby|="bob 'tacos' slayer"&nbsp; }} for example, but I always do that particular step manually. Also, it's pretty important to put in one final setup command: !token-mod --set defaulttoken Without setting that token as the default for the character, you will wind up with one example of a perfectly set up token, but dragging that character from the journal to the map will give you nothing but a generic token. Setting as default token ensures that a subsequent placement will use your specific, prepared token for that character. Full instructions are here .
1531758025
The Aaron
Pro
API Scripter
Wolf Thunderspirit said: 1) My players are not seeing "Use Selected Token" in their character sheet (which is beyond odd, because when I was playing I thought I remember seeing it. &nbsp;Now that I'm a GM, I sometimes have NO idea what players see) so they can't select and move a token from the startup token board. &nbsp;This was a slight embarrassment to Session Zero tonight. &nbsp;***Cringes*** To get the Use Selected Token button, they have to click edit on the bio page.&nbsp; I bet they're skipping that step. Wolf Thunderspirit said: 2) So ok, enter GM to the rescue. &nbsp;Well, 5 players... &nbsp;So I wanted to automate as much as possible to limit the time spent on this. &nbsp;I went to&nbsp; <a href="https://www.youtube.com/watch?v=V2h8LdK0gTs&amp;t=347s" rel="nofollow">https://www.youtube.com/watch?v=V2h8LdK0gTs&amp;t=347s</a> &nbsp;to see some solutions (you don't have to watch that, but the description contains related macros) and I thought, I can modify that to suit my needs. /w gm &amp;{template:5e-shaped}{{title=Token Setup for @{selected|character_name}}}{{ ... Setup Begun... }} !token-mod {{ --set bar1_link|hp --set bar2_link|ac --set bar3_link|speed --set name|@{selected|character_name} --on showname --on showplayers_name --on showplayers_bar1 --on showplayers_aura1 --on showplayers_aura2 --on light_hassight }} !token-mod {{?{What Type of Vision - DIM/BRIGHT|None / Blind,--set light_radius&amp;#124; --set light_dimradius&amp;#124; --off light_otherplayers |Torch - 40/20, --set light_radius&amp;#124;40 --set light_dimradius&amp;#124;20 --on light_otherplayers |Lantern or Sunrod - 60/30, --set light_radius&amp;#124;60 --set light_dimradius&amp;#124;30 --on light_otherplayers |Lamp - 30/15, --set light_radius&amp;#124;30 --set light_dimradius&amp;#124;15 --on light_otherplayers |Candle - 5/0, --set light_radius&amp;#124;5 --set light_dimradius&amp;#124;0 --on light_otherplayers |Dark Vision 60/0, --set light_radius&amp;#124;60 --set light_dimradius&amp;#124;0 --off light_otherplayers |Devil Sight 120/0, --set light_radius&amp;#124;120 --set light_dimradius&amp;#124;0 --off light_otherplayers}}} /w gm &amp;{template:5e-shaped}{{title=Token Setup for @{selected|character_name}}}{{... Setup Completed...}} That yielded no feedback (not even errors) at the API screen, or results on the selected token, only the Setup Begun and Setup Completed messages in chat (It LIED!!! &nbsp;lol.) Just a note, when placing TokenMod commands in a Roll Query, you can use # as a separator instead of | (&amp;#124;), which is much easier to edit and maintain.&nbsp; Also, since you can't have multiple lines in a Roll Query, there's no need to put {{ }} around it. !token-mod ?{What Type of Vision - DIM/BRIGHT|None / Blind,--set light_radius# --set light_dimradius# --off light_otherplayers |Torch - 40/20, --set light_radius#40 --set light_dimradius#20 --on light_otherplayers |Lantern or Sunrod - 60/30, --set light_radius#60 --set light_dimradius#30 --on light_otherplayers |Lamp - 30/15, --set light_radius#30 --set light_dimradius#15 --on light_otherplayers |Candle - 5/0, --set light_radius#5 --set light_dimradius#0 --on light_otherplayers |Dark Vision 60/0, --set light_radius#60 --set light_dimradius#0 --off light_otherplayers |Devil Sight 120/0, --set light_radius#120 --set light_dimradius#0 --off light_otherplayers} Try the commands separately and manually to make sure they are doing what you think they should.&nbsp; Note that @{selected|character_name} won't have a value (and might cause an error) if the token doesn't already represent a character. Wolf Thunderspirit said: 3) Is there a way to use a roll query to assign who a brand new token represents? &nbsp;That I would also like to setup as the first line in this global macro, which I imagine would need a moment to process before moving on to the next bits, though I don't know if that would matter so much. &nbsp;If it does, some of the non-character specifics (turning on showname, hassight, auras,) could be run until the character specifics get involved. I'm not sure it will help what you're trying to do, but TokenMod will form a minimal match based on name for the character you tell it you want represented.&nbsp; You can use a partial name like this: !token-mod --set represents|"?{name}" If you have a token named Vorgalt the Magnificent , you could just type in " vorgalt " if there are no other characters with that name.&nbsp; (Or even just " vor " or " gal " or&nbsp;" v " if they would only match one character.)
1531760197
The Aaron
Pro
API Scripter
Just a side note after discussing this with Keith:&nbsp; You won't be able to both set the represents character and use @{selected|...} to access character attributes in one go.&nbsp; You can either replace your @{selected|...} with @{character's name|...}, or do this in two separate buttons.&nbsp; This is because the @{selected|...} is resolved on the client side before sending to the API, which means the token won't have been changed to represent the character until after all the @{selected|...} references are resolved.
OK ... So 'modifying to suit my needs' wasn't a total trick, some of the examples given were just outright not going to work. &nbsp;For example, hp is not the same thing as HP, and therefore didn't link to bar 1. &nbsp;Stuff like that. &nbsp;But I fixed it, so I digress. I have a very powerful working example of the script I want to share with everyone who wants a global macro to speed that process up. &nbsp;But it is a rough draft currently, as there are some things I would also like to adjust, and one thing that didn't work and should have. &nbsp; The thing that didn't work was setting the default token. &nbsp;When I went into the sheet to check if it had done so, it didn't. &nbsp;If that's the worst of my worries though, ha, that's one thing I can do, since this script does all the pointy clicky stuff, and I only have to tweak it here and there. &nbsp; I may make my own Vision Macro as a seperate one, as that's something to change on the fly regularly in game (lighting/ dousing torches) and that one that was listed as part of this just didn't work at all for me. /w gm &amp;{template:5e-shaped} {{title=Token Setup for ?{Name of Character} }}{{... Setup Begun...}} !token-mod --set represents|"?{Name of Character}" !token-mod --set name|?{Name of Character} !token-mod --on showname !token-mod --on showplayers_name !token-mod --set bar1_link|HP !token-mod --on showplayers_bar1 !token-mod --set bar2_link|AC !token-mod --set bar3_link|speed !token-mod --on showplayers_aura1 !token-mod --on showplayers_aura2 !token-mod --set light_radius|5&nbsp; !token-mod --set light_dimradius|0 !token-mod --on light_hassight !token-mod --set defaulttoken /w gm &amp;{template:5e-shaped}{{title=Token Setup for ?{Name of Character} }}{{... Setup Completed...}} The things I want to be able to adjust are: &nbsp; &nbsp; Under Edit Token &gt; Advanced Tab &gt; Emits Light Section: 1st Row, Right Side: &nbsp;What do I need to do to set that angle to 360 degrees? &nbsp; &nbsp; Same place as above, after Has Sight / Angle : &nbsp;What do I need to do to set that angle to 360 degrees? &nbsp; &nbsp; Under Advanced Fog of War : How do I set that to 10 feet?
1531785448
The Aaron
Pro
API Scripter
Sorry, I didn't mean to imply you should remove all multi-line.&nbsp; I'd rewrite the above like this: !token-mod {{ --on showname showplayers_name showplayers_bar1 showplayers_aura1 showplayers_aura2 light_hassight --set represents|"?{Name of Character}" name|"?{Name of Character}" bar1_link|HP bar2_link|AC bar3_link|speed light_radius|5 light_dimradius|0 defaulttoken }} That will let it operate in one command, which will be the most efficient. You also don't need to specify --set and --on over and over, and be sure to quote strings like the name. For setting up your sight commands, you can use: !token-mod --set light_angle|360 to set the angle of the light, and&nbsp; !token-mod --set light_losangle|360 to set the angle of vision. I don't think I've added the advanced fog of war settings yet, but I'll try to knock that out real quick later tonight.
Oh, crap Aaron, no rush. &nbsp;I don't use AFoW that much anyway, it's just nice to know these things. &nbsp;I've been learning a lot - really quickly - from you, Kryx, Keith, and Jakob. &nbsp;You all have spent a lot of time answering my questions and getting me on point to present an awesome game for my players in Curse of Strahd (which starts on the 28th with session 1). &nbsp;Session Zero has had some hitches, but overall, has been good - they were impressed with things like groupinit, turnmarker, calendar, the Shaped Sheet, etc., and they don't even know all the things like tokenmod and chatsetattr that go on behind the scenes. Anyway - enough praising. &nbsp;lol I'll try the multiline, but when I went to use that before, something didn't like it. &nbsp;I'll see if your edits work better and let you know. &nbsp;I'll also add the sight commands you clued me in on.
1531786659
The Aaron
Pro
API Scripter
No worries! &nbsp;If it doesn’t work, definitely let me know. It should work.&nbsp;
/w gm &amp;{template:5e-shaped} {{title=Token Setup for ?{Name of Character} }}{{... Setup Begun...}} !token-mod {{ &nbsp; --on &nbsp; &nbsp; showname &nbsp; &nbsp; showplayers_name &nbsp; &nbsp; showplayers_bar1 &nbsp; &nbsp; showplayers_aura1 &nbsp; &nbsp; showplayers_aura2 &nbsp; &nbsp; light_hassight &nbsp; --set &nbsp; &nbsp; represents|"?{Name of Character}" &nbsp; &nbsp; name|"?{Name of Character}" &nbsp; &nbsp; bar1_link|HP &nbsp; &nbsp; bar2_link|AC &nbsp; &nbsp; bar3_link|speed &nbsp; &nbsp; light_radius|5&nbsp; &nbsp; &nbsp; light_dimradius|0 &nbsp; &nbsp; light_angle|360 &nbsp; &nbsp; light_losangle|360 &nbsp; &nbsp; defaulttoken }} /w gm &amp;{template:5e-shaped}{{title=Token Setup for ?{Name of Character} }}{{... Setup Completed...}} No Go on the multiline. &nbsp;It's possible, because I'm running Vista which can't update the Google browser anymore, that my old PC may be the issue. &nbsp;It did throw the Sandbox off when I fired it, with this error: TypeError: Cannot set property 'playing' of undefined TypeError: Cannot set property 'playing' of undefined &nbsp; &nbsp; at changeHandler (apiscript.js:8479:38) &nbsp; &nbsp; at eval (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:65:16) &nbsp; &nbsp; at Object.publish (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:70:8) &nbsp; &nbsp; at TrackedObj.set (/home/node/d20-api-server/api.js:1028:14) &nbsp; &nbsp; at updateLocalCache (/home/node/d20-api-server/api.js:1318:18) &nbsp; &nbsp; at /home/node/d20-api-server/api.js:1530:7 &nbsp; &nbsp; at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 &nbsp; &nbsp; at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) &nbsp; &nbsp; at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546) &nbsp; &nbsp; at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489) &nbsp; &nbsp; at Rd.Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425)&nbsp; ... Or it's firing order, which I specifically did think out when I put it together as below. /w gm &amp;{template:5e-shaped} {{title=Token Setup for ?{Name of Character} }}{{... Setup Begun...}} !token-mod --set represents|"?{Name of Character}" !token-mod --set name|"?{Name of Character}" !token-mod --on showname !token-mod --on showplayers_name !token-mod --set bar1_link|HP !token-mod --on showplayers_bar1 !token-mod --set bar2_link|AC !token-mod --set bar3_link|speed !token-mod --on showplayers_aura1 !token-mod --on showplayers_aura2 !token-mod --set light_radius|5&nbsp; !token-mod --set light_dimradius|0 !token-mod --set light_angle|360 !token-mod --on light_hassight !token-mod --set light_losangle|360 !token-mod --set defaulttoken /w gm &amp;{template:5e-shaped}{{title=Token Setup for ?{Name of Character} }}{{... Setup Completed...}} However, I tried the light angles and they aren't doing anything (the macro seems to ignore them), and still no luck on setting default token. &nbsp;I'm wondering if I need to define in a substring who they are going to from the&nbsp;?{Name of Character} query, i.e.: !token-mod --set defaulttoken|" ?{Name of Character}" or something similar ...
1531788628
The Aaron
Pro
API Scripter
Hmm.&nbsp; Vista shouldn't matter... playing is a setting on a jukebox track.&nbsp; Do you have an audio script running? Try disabling it and running the multiline command.&nbsp; I'm going to guess that some other script is mangling the msg object before it gets to TokenMod.&nbsp; This has been a problem in the past, where people assume the objects passed to them in events are only passed to their script, when in reality, the same object is passed to every callback, so changes to the input object in one script cause repercussions in other scripts.&nbsp; Also try running the multiline with with this script enabled and copy the results from the API log back here: on('ready',()=&gt;on('chat:message',(msg)=&gt;log(msg)));
will do
From API {"content":" {{title=Token Setup for TESTY }}{{... Setup Begun...}}","playerid":"-LGrD5x4_PCSWg_nzRyd","rolltemplate":"5e-shaped","target":"gm","target_name":"GM","type":"whisper","who":"Wolf Thunderspirit (GM)"} {"content":"!token-mod {{&lt;br/&gt;\n &nbsp;--on&lt;br/&gt;\n &nbsp; &nbsp;showname&lt;br/&gt;\n &nbsp; &nbsp;showplayers_name&lt;br/&gt;\n &nbsp; &nbsp;showplayers_bar1&lt;br/&gt;\n &nbsp; &nbsp;showplayers_aura1&lt;br/&gt;\n &nbsp; &nbsp;showplayers_aura2&lt;br/&gt;\n &nbsp; &nbsp;light_hassight&lt;br/&gt;\n &nbsp;--set&lt;br/&gt;\n &nbsp; &nbsp;represents|\"TESTY\"&lt;br/&gt;\n &nbsp; &nbsp;name|\"TESTY\"&lt;br/&gt;\n &nbsp; &nbsp;bar1_link|HP&lt;br/&gt;\n &nbsp; &nbsp;bar2_link|AC&lt;br/&gt;\n &nbsp; &nbsp;bar3_link|speed&lt;br/&gt;\n &nbsp; &nbsp;light_radius|5 &lt;br/&gt;\n &nbsp; &nbsp;light_dimradius|0&lt;br/&gt;\n &nbsp; &nbsp;light_angle|360&lt;br/&gt;\n &nbsp; &nbsp;light_losangle|360&lt;br/&gt;\n &nbsp; &nbsp;defaulttoken&lt;br/&gt;\n}}","playerid":"-LGrD5x4_PCSWg_nzRyd","selected":[{"_id":"-LGruZXWJlaNufSAG7fR","_type":"graphic"}],"type":"api","who":"Wolf Thunderspirit (GM)"} {"content":"{{title=Token Setup for TESTY }}{{... Setup Completed...}}","playerid":"-LGrD5x4_PCSWg_nzRyd","rolltemplate":"5e-shaped","target":"gm","target_name":"GM","type":"whisper","who":"Wolf Thunderspirit (GM)"}
1531789927
The Aaron
Pro
API Scripter
Update v0.8.40 &nbsp;-- Added adv_fow_view_distance setting (Thanks&nbsp; Wolf Thunderspirit ) Numbers or Blank Just like the Numbers fields, except you can set them to blank as well. Available Numbers or Blank Properties: light_radius light_dimradius light_multiplier aura1_radius aura2_radius adv_fow_view_distance Here is setting a standard DnD 5e torch, turning off aura1 and setting aura2 to 30. Note that the&nbsp; | &nbsp;is still required for setting a blank value, such as aura1_radius below. !token-mod --set light_radius|40 light_dimradius|20 aura1_radius| aura2_radius|30 Just as above, you can use&nbsp; = ,&nbsp; + ,&nbsp; - ,&nbsp; * , and&nbsp; / &nbsp;when setting these values. Here is setting a standard DnD 5e torch, with advanced fog of war revealed for 30. !token-mod --set light_radius|40 light_dimradius|20 adv_fow_view_distance|30
The Aaron said: Hmm.&nbsp; Vista shouldn't matter... playing is a setting on a jukebox track.&nbsp; Do you have an audio script running? Try disabling it and running the multiline command.&nbsp; I'm going to guess that some other script is mangling the msg object before it gets to TokenMod.&nbsp; This has been a problem in the past, where people assume the objects passed to them in events are only passed to their script, when in reality, the same object is passed to every callback, so changes to the input object in one script cause repercussions in other scripts.&nbsp; Also try running the multiline with with this script enabled and copy the results from the API log back here: on('ready',()=&gt;on('chat:message',(msg)=&gt;log(msg))); As far as Vista, no, but because of Vista, I haven't been able to update Google Chrome past&nbsp; Version 49.0.2623.112 m &nbsp;they are up to Version&nbsp; 67.0.3396.99 &nbsp;right now
Nice - I got Credit ... lmao
1531790190
The Aaron
Pro
API Scripter
Yeah, there should be nothing wrong with that command.&nbsp; What other scripts do you have running?
1531790407
The Aaron
Pro
API Scripter
Everyone get's credit. =D Since API scripts run on a server in the cloud, that script I wrote above lets us verify that nothing weird is happening to the message when it gets sent to the API.&nbsp; That output is basically what the API script sees, and I ran the multi-line parsing code on it and it parsed fine: ["!token-mod","on showname showplayers_name showplayers_bar1 showplayers_aura1 showplayers_aura2 light_hassight","set represents|\"TESTY\" name|\"TESTY\" bar1_link|HP bar2_link|AC bar3_link|speed light_radius|5 light_dimradius|0 light_angle|360 light_losangle|360 defaulttoken "] That indicates it isn't an issue with an outdated browser corrupting the inputs.&nbsp; Not an editor issue either, for that matter. At this point, I'm leaning toward another script crashing because of something in the multi-line version.&nbsp; I'd dearly like to know what script that is so it can be fixed. =D
Of those that I just sent, I honestly can't recall ever using Roll20AM or Powercards (Lack of understanding what strengths they'd give me/ how to program them. &nbsp;I use the jukebox in Roll20 when needed. &nbsp;And Powercards was recommended but I haven't gotten around to creating anything with it yet; the default and shaped templates work fine for me so far)
I have modified the Welcome Package and the Calendar scripts to customize them to my game. Welcome Package (made the message less generic - another factor I want to change is that it somehow bypasses the configuration setup of the Shaped companion API, we use things like Sanity, and it doesn't give 'that' sheet to the players): (() =&gt; { 'use strict'; const CREATE_CHARACTER_CMD = '!welcomePackageCreateCharacter'; const CSS = { 'menu': { 'background': '#fff', 'border': 'solid 1px #a88cd5', 'border-radius': '5px', 'font-weight': 'bold', 'margin-bottom': '1em', 'overflow': 'hidden' }, 'menuBody': { 'padding': '5px', 'text-align': 'center' }, 'menuHeader': { 'background': '#a88cd5', 'color': '#fff', 'text-align': 'center' } }; /** * Creates a character creation macro for a player if they don't already * have the macro. * @param {Player} player */ function addCharacterCreateMacro(player, name) { let playerId = player.get('_id'); let macroName = 'CreateACharacter'; let macro = findObjs({ _type: 'macro', _playerid: playerId, name: macroName })[0]; if(!macro) { createObj('macro', { _playerid: playerId, name: macroName, action: '!welcomePackageCreateCharacter ?{Character Name:}' }); } } /** * Creates a character for a player if they don't already have any characters. * @param {Player} player * @param {string} [name] The name of the character. If this is provided, * the character will be created regardless of whether * the player has a character already. */ function createPlayerCharacter(player, name) { let playerId = player.get('_id'); let who = player.get('_displayname'); let characters = findObjs({ _type: 'character', controlledby: playerId }); if(characters.length === 0 || name) { if(!name) name = `${who}'s character`; setTimeout(() =&gt; { let character = createObj('character', { controlledby: playerId, inplayerjournals: playerId, name }); showCharacterLink(who, character); }, 3000); } } /** * Shows a player the link to their new character with a welcoming message. * @param {string} who The player's display name. * @param {Character} character */ function showCharacterLink(who, character) { let menu = new HtmlBuilder('.menu'); menu.append('.menuHeader', 'Welcome to The Devil Strahd Wants To Play...!'); let content = menu.append('.menuBody'); content.append('div', 'A blank character has been created for you!'); content.append('div', ' '); content.append('div', 'Add the PC Menu from your list of Macros by checking IN BAR next to it.'); content.append('div', 'Then click on the PC Menu from the bottom of your screen.'); content.append('div', 'Click ROLL ABILITY SCORES to get your Stats.'); content.append('div', ' '); content.append('div', 'Click On Your Character to start building: '); content.append('a', character.get('name'), { href: '<a href="http://journal.roll20.net/character/" rel="nofollow">http://journal.roll20.net/character/</a>' + character.get('_id'), style: { color: '#a08' } }); let html = menu.toString(CSS); sendChat('Welcome Package', '/w ' + who + ' ' + html); } // When a player logs in, create a character for them if they don't have one. on('change:player:_online', player =&gt; { if(player.get('_online') &amp;&amp; !playerIsGM(player.get('_id'))) { createPlayerCharacter(player); addCharacterCreateMacro(player); } }); on('ready', () =&gt; { log('🎁🎁🎁 Initialized Welcome Package 🎁🎁🎁'); }); /** * Process chat commands. */ on('chat:message', msg =&gt; { let playerId = msg.playerid; if(msg.content.startsWith(CREATE_CHARACTER_CMD)) { let player = getObj('player', playerId); let argv = msg.content.split(' '); let name = argv.slice(1).join(' '); createPlayerCharacter(player, name); } }); })(); The calendar script I updated the "Modern" Calendar to reflect Ravenloft (January = 1st Moon, etc.): // Calendar and down day counter for Faerun, Greyhawk, Eberron and Modern Settings // Created by Kirsty (<a href="https://app.roll20.net/users/1165285/kirsty" rel="nofollow">https://app.roll20.net/users/1165285/kirsty</a>) // API Commands: // !cal - for the GM displays the menu in the chat window, for a player displays date, weather, moon(s) and down days // Red Colour: #7E2D40 rgb(126, 45, 64) var Calendar = Calendar || (function() { 'use strict'; var version = '3.1.1', setDefaults = function() { state.Calendar = { now: { version: '3.1.1', world: 1, ordinal: 1, year: 1486, down: 0, divider: 0, weather: "It is a cool but sunny day.", timetype: "OFF", time: "Noon", startdate: "1,Hammer,1486" }, }; }, checkDefaults = function() { if( state.Calendar.now.version != version ){ state.Calendar.now.version = version; } if( ! state.Calendar.now.world){state.Calendar.now.world = 1}; if( ! state.Calendar.now.ordinal){state.Calendar.now.ordinal = 1}; if( ! state.Calendar.now.year){state.Calendar.now.year = 1486}; if( ! state.Calendar.now.down){state.Calendar.now.down = '0'}; if( ! state.Calendar.now.divider){state.Calendar.now.divider = '0'}; if( ! state.Calendar.now.weather){state.Calendar.now.weather = "It is a cool but sunny day."}; if( ! state.Calendar.now.timetype){state.Calendar.now.timetype = "OFF"}; if( ! state.Calendar.now.time){state.Calendar.now.time = "Noon"}; if( ! state.Calendar.now.startdate){state.Calendar.now.startdate = "1,Hammer,1486"}; }, handleInput = function(msg) { var args = msg.content.split(","); if (msg.type !== "api") { return; } if(playerIsGM(msg.playerid)){ switch(args[0]) { case '!cal': calmenu(); break; case '!setworld': state.Calendar.now.world=args[1]; calmenu(); break; case '!startdate': state.Calendar.now.startdate=args[1]+','+args[2]+','+args[3]; calmenu(); break; case '!setday': switch(Number(state.Calendar.now.world)) { case 1: getFaerunOrdinal(msg); break; case 2: getGreyhawkOrdinal(msg); break; case 3: getModernOrdinal(msg); break; case 4: getEberronOrdinal(msg); break; } weather(); calmenu(); break; case '!setmonth': switch(Number(state.Calendar.now.world)) { case 1: getFaerunOrdinal(msg); break; case 2: getGreyhawkOrdinal(msg); break; case 3: getModernOrdinal(msg); break; case 4: getEberronOrdinal(msg); break; } weather(); calmenu(); break; case '!setyear': state.Calendar.now.year=args[1]; calmenu(); break; case '!setordinal': state.Calendar.now.ordinal=args[1]; calmenu(); break; case '!settimetype': var type = args[1]; state.Calendar.now.timetype=type; if (type == 'OFF') { state.Calendar.now.time = 'OFF' }; calmenu(); break; case '!settime': var type = state.Calendar.now.timetype; if (type == 'General'){ state.Calendar.now.time = args[1]; } else if (type == '24 Hour') { state.Calendar.now.time = args[1]+args[2]; } calmenu(); break; case '!setdown': var down = Number(args[1]); state.Calendar.now.down = down; getdown(down); calmenu(); break; case '!setdiv': state.Calendar.now.divider=Number(args[1]); calmenu(); break; case '!addday': addday(args[1]); weather(); calmenu(); break; case '!addtime': addtime(args[1]); calmenu(); break; case '!weather': if(args[1]=='Roll}'){ weather(); }else{ var string = args[1]; for (var i = 2; i &lt; args.length; i++) { string = string + ", " + args[i]; } state.Calendar.now.weather = string; } calmenu(); break; case '!playercal': showcal(msg); break; } }else if(args[0]=='!cal'){ showcal(msg); } }, calmenu = function() { var colour = '#7E2D40'; var divstyle = 'style="width: 189px; border: 1px solid black; background-color: #ffffff; padding: 5px;"' var astyle1 = 'style="text-align:center; border: 1px solid black; margin: 1px; padding: 2px; background-color: ' + colour + '; border-radius: 4px; box-shadow: 1px 1px 1px #707070; width: 100px;'; var astyle2 = 'style="text-align:center; border: 1px solid black; margin: 1px; padding: 2px; background-color: ' + colour + '; border-radius: 4px; box-shadow: 1px 1px 1px #707070; width: 150px;'; var tablestyle = 'style="text-align:center;"'; var arrowstyle = 'style="border: none; border-top: 3px solid transparent; border-bottom: 3px solid transparent; border-left: 195px solid ' + colour + '; margin-bottom: 2px; margin-top: 2px;"'; var headstyle = 'style="color: ' + colour + '; font-size: 18px; text-align: left; font-variant: small-caps; font-family: Times, serif;"'; var substyle = 'style="font-size: 11px; line-height: 13px; margin-top: -3px; font-style: italic;"'; var world = getworld(); var down = Number(state.Calendar.now.down); down = getdown(down); var moMenu = getMoMenu(); var ordinal = state.Calendar.now.ordinal; var nowdate; switch(Number(state.Calendar.now.world)) { case 1: nowdate = getFaerunDate(ordinal).split(','); break; case 2: nowdate = getGreyhawkDate(ordinal).split(','); break; case 3: nowdate = getModernDate(ordinal).split(','); break; case 4: nowdate = getEberronDate(ordinal).split(','); break; } var month = nowdate[0]; var day = nowdate[1]; var moon; if (state.Calendar.now.world==1){ moon = getFaerunMoon(); }else if(state.Calendar.now.world==2){ moon = getGreyhawkMoon(); }else{ // MESSED WITH THIS TO GET MOON TO FUNCTION!!!!! was "moon = '';" moon = getFaerunMoon(); } var start = state.Calendar.now.startdate.split(','); var startdate = start[0]+getsuffix(start[0])+' '+start[1]+', '+start[2]; var timeselect = timemenu(); sendChat('Calendar', '/w gm &lt;div ' + divstyle + '&gt;' + //-- '&lt;div ' + headstyle + '&gt;Calendar&lt;/div&gt;' + //-- '&lt;div ' + substyle + '&gt;Menu (v.' + state.Calendar.now.version + ')&lt;/div&gt;' + //-- '&lt;div ' + arrowstyle + '&gt;&lt;/div&gt;' + //-- '&lt;table&gt;' + //-- '&lt;tr&gt;&lt;td&gt;World: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setworld,?{World?|Faerûn,1|Greyhawk,2|Modern,3|Eberron,4}"&gt;' + world + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Start Date: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!startdate,?{Day},?{Month},?{Year}"&gt;' + startdate + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Day: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setday,?{Day?|1},' + month +'"&gt;' + day + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Month: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setmonth,' + day + moMenu + month + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Year: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setyear,?{Year?|1486}"&gt;' + state.Calendar.now.year + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Ordinal: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setordinal,?{Ordinal?|1}"&gt;' + ordinal + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //- '&lt;tr&gt;&lt;td&gt;Time type: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!settimetype,?{Time?|OFF|24 Hour|General}"&gt;' + state.Calendar.now.timetype + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //- '&lt;tr&gt;&lt;td&gt;Time: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!settime,'+ timeselect + '"&gt;' + state.Calendar.now.time + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Down Days: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setdown,?{Down Days?|0}"&gt;' + down + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Down Day&lt;br&gt;Divider: &lt;/td&gt;&lt;td&gt;&lt;a ' + astyle1 + '" href="!setdiv,?{Down Day Divider?|1}"&gt;' + state.Calendar.now.divider + '&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;tr&gt;&lt;td&gt;Moon: &lt;/td&gt;&lt;td&gt;' + moon + '&lt;/td&gt;&lt;/tr&gt;' + //-- '&lt;/table&gt;' + //-- '&lt;br&gt;Weather: ' + state.Calendar.now.weather + //-- '&lt;br&gt;&lt;br&gt;&lt;div style="text-align:center;"&gt;&lt;a ' + astyle2 + '" href="!addday,?{Days to add?|1}"&gt;Advance the Date&lt;/a&gt;&lt;/div&gt;' + //-- '&lt;div style="text-align:center;"&gt;&lt;a ' + astyle2 + '" href="!addtime,?{Advance how many hours?|1}"&gt;Advance the Time&lt;/a&gt;&lt;/div&gt;' + //-- '&lt;div style="text-align:center;"&gt;&lt;a ' + astyle2 + '" href="!weather,?{Weather|Roll|Edit,?{Edit Weather}}"&gt;Change Weather&lt;/a&gt;&lt;/div&gt;' + //-- '&lt;div style="text-align:center;"&gt;&lt;a ' + astyle2 + '" href="!playercal"&gt;Show to Players&lt;/a&gt;&lt;/div&gt;' + //-- '&lt;/div&gt;' ); }, showcal = function(msg) { var nowdate; var ordinal = state.Calendar.now.ordinal; switch(Number(state.Calendar.now.world)) { case 1: nowdate = getFaerunDate(ordinal).split(','); break; case 2: nowdate = getGreyhawkDate(ordinal).split(','); break; case 3: nowdate = getModernDate(ordinal).split(','); break; case 4: nowdate = getEberronDate(ordinal).split(','); break; } var month = nowdate[0]; var day = nowdate[1]; var down = state.Calendar.now.down; down = getdown(down); var suffix = getsuffix(day); var world = getworld(); var colour = '#7E2D40'; var divstyle = 'style="width: 189px; border: 1px solid black; background-color: #ffffff; padding: 5px;"' var tablestyle = 'style="text-align:center;"'; var arrowstyle = 'style="border: none; border-top: 3px solid transparent; border-bottom: 3px solid transparent; border-left: 195px solid ' + colour + '; margin-bottom: 2px; margin-top: 2px;"'; var headstyle = 'style="color: ' + colour + '; font-size: 18px; text-align: left; font-variant: small-caps; font-family: Times, serif;"'; var substyle = 'style="font-size: 11px; line-height: 13px; margin-top: -3px; font-style: italic;"'; var moon; if (state.Calendar.now.world==1){ moon = getFaerunMoon(); }else if(state.Calendar.now.world==2){ moon = getGreyhawkMoon(); }else{ // MESSED WITH THIS TO GET MOON TO FUNCTION!!!!! was "moon = '';" moon = getFaerunMoon(); } var timestr; var downstr; if(state.Calendar.now.time!="OFF"){ timestr = '&lt;br&gt;The time is: '+state.Calendar.now.time; }else{ timestr = ''; } if(down!=0){ downstr = '&lt;br&gt;Players have ' + down + ' down days.'; }else{ downstr = ''; } sendChat(msg.who, '&lt;div ' + divstyle + '&gt;' + //-- '&lt;div ' + headstyle + '&gt;Calendar&lt;/div&gt;' + //-- '&lt;div ' + substyle + '&gt;' + world + '&lt;/div&gt;' + //-- '&lt;div ' + arrowstyle + '&gt;&lt;/div&gt;' + //-- day + suffix + ' ' + month + ', ' + state.Calendar.now.year + //-- timestr + '&lt;br&gt;' + //-- downstr + //-- 'Moon:&lt;br&gt;' + moon + '&lt;br&gt;' + //-- 'Today\'s weather:&lt;br&gt;' + state.Calendar.now.weather ); }, getworld = function() { var num = Number(state.Calendar.now.world); var world; switch(num) { case 1: world = 'Faerûn'; break; case 2: world = 'Greyhawk'; break; case 3: world = 'Ravenloft'; break; case 4: world = 'Eberron'; break; } return world; }, getdown = function(days) { var down = Number(days); var div = Number(state.Calendar.now.divider); if(div!=0){ down = down/div; } return down; }, getMoMenu = function() { var world = Number(state.Calendar.now.world); var leap = checkLeap(); var moMenu; switch(world){ case 1: if(leap==0){ moMenu = ',?{Month|Hammer|Midwinter|Alturiak|Ches|Tarsakh|Greengrass|Mirtul|Kythorn|Flamerule|Midsummer|Eleasias|Eleint|Highharvestide|Marpenoth|Uktar|Feast of the Moon|Nightal}"&gt;'; }else{ moMenu = ',?{Month|Hammer|Midwinter|Alturiak|Ches|Tarsakh|Greengrass|Mirtul|Kythorn|Flamerule|Midsummer|Sheildmeet|Eleasias|Eleint|Highharvestide|Marpenoth|Uktar|Feast of the Moon|Nightal}"&gt;'; } break; case 2: moMenu = ',?{Month|Needfest|Fire Seek|Readying|Coldeven|Growfest|Planting|Flocktime|Wealsun|Richfest|Reaping|Goodmonth|Harvester|Brewfest|Patchwall|Readyreat|Sunsebb}"&gt;'; break; case 3: moMenu = ',?{Month|1st Moon|2nd Moon|3rd Moon|4th Moon|5th Moon|6th Moon|7th Moon|8th Moon|9th Moon|10th Moon|11th Moon|12th Moon}"&gt;'; break; case 4: moMenu = ',?{Month|Zarantyr|Olarune|Therendor|Eyre|Dravago|Nymm|Lharvion|Barrakas|Rhaan|Sypheros|Aryth|Vult}"&gt;'; break; } return moMenu; }, checkLeap = function(){ var leap; var remainder; var world = Number(state.Calendar.now.world); var year = Number(state.Calendar.now.year); switch(world){ case 1: remainder = year % 4; if(remainder==0){ leap = 1; }else{ leap = 0; } break; case 2: leap = 0; break; case 3: if(year % 4 != 0){ leap = 0; }else if(year % 100 != 0){ leap = 1; }else if(year % 400 != 0){ leap = 0; }else{ leap = 1; } break; case 4: leap = 0; break; } return leap; }, getFaerunDate = function(options){ var day = Number(options); var date; var month; if(day&gt;0 &amp;&amp; day&lt;=30){ month="Hammer"; date=day; }else if(day==31){ month="Midwinter"; date='festival'; }else if(day&gt;31 &amp;&amp; day&lt;=61){ month="Alturiak"; date=day-31; }else if(day&gt;61 &amp;&amp; day&lt;=91){ month="Ches"; date=day-61; }else if(day&gt;91 &amp;&amp; day&lt;=121){ month="Tarsakh"; date=day-91; }else if(day==122){ month="Greengrass"; date='festival'; }else if(day&gt;122 &amp;&amp; day&lt;=152){ month="Mirtul"; date=day-122; }else if(day&gt;152 &amp;&amp; day&lt;=182){ month="Kythorn"; date=day-152; }else if(day&gt;182 &amp;&amp; day&lt;=212){ month="Flamerule"; date=day-182; }else if(day==213){ month="Midsummer"; date='festival'; }else if(day==214){ month="Sheildmeet"; date='festival'; }else if(day&gt;214 &amp;&amp; day&lt;=244){ month="Eleasias" date=day-214; }else if(day&gt;244 &amp;&amp; day&lt;=274){ month="Eleint"; date=day-244; }else if(day==275){ month="Highharvestide"; date='festival'; }else if(day&gt;275 &amp;&amp; day&lt;=305){ month="Marpenoth"; date=day-275; }else if(day&gt;305 &amp;&amp; day&lt;=335){ month="Uktar"; date=day-305; }else if(day==336){ month="Feast of the Moon"; date='festival'; }else if(day&gt;336 &amp;&amp; day&lt;=366){ month="Nightal"; date=day-336; }else{ month="Hammer"; date='1'; } var array=month+','+String(date); return array; }, getGreyhawkDate = function(options){ var day = Number(options); var date; var month; if(day&gt;0 &amp;&amp; day&lt;=7){ month="Needfest"; date=day; }else if(day&gt;7 &amp;&amp; day&lt;=35){ month="Fire Seek"; date=day-7; }else if(day&gt;35 &amp;&amp; day&lt;=63){ month="Readying"; date=day-35; }else if(day&gt;63 &amp;&amp; day&lt;=91){ month="Coldeven"; date=day-63; }else if(day&gt;91 &amp;&amp; day&lt;=98){ month="Growfest"; date=day-91; }else if(day&gt;98 &amp;&amp; day&lt;=126){ month="Planting"; date=day-98; }else if(day&gt;126 &amp;&amp; day&lt;=154){ month="Flocktime"; date=day-126; }else if(day&gt;154 &amp;&amp; day&lt;=182){ month="Wealsun"; date=day-154; }else if(day&gt;182 &amp;&amp; day&lt;=189){ month="Richfest"; date=day-182; }else if(day&gt;189 &amp;&amp; day&lt;=217){ month="Reaping"; date=day-189; }else if(day&gt;217 &amp;&amp; day&lt;=245){ month="Goodmonth" date=day-217; }else if(day&gt;245 &amp;&amp; day&lt;=273){ month="Harvester"; date=day-245; }else if(day&gt;273 &amp;&amp; day&lt;=280){ month="Brewfest"; date=day-273; }else if(day&gt;280 &amp;&amp; day&lt;=308){ month="Patchwall"; date=day-280; }else if(day&gt;308 &amp;&amp; day&lt;=336){ month="Readyreat"; date=day-308; }else if(day&gt;336 &amp;&amp; day&lt;=364){ month="Sunsebb"; date=day-336; }else{ month="Needfest"; date='1'; } var array=month+','+String(date); return array; }, getModernDate = function(options){ var day = Number(options); var date; var month; if(day&gt;0 &amp;&amp; day&lt;=31){ month="1st Moon"; date=day; }else if(day&gt;31 &amp;&amp; day&lt;=59){ month="2nd Moon"; date=day-31; }else if(day&gt;59 &amp;&amp; day&lt;=90){ month="3rd Moon"; date=day-59; }else if(day&gt;90 &amp;&amp; day&lt;=120){ month="4th Moon"; date=day-90; }else if(day&gt;120 &amp;&amp; day&lt;=151){ month="5th Moon"; date=day-120; }else if(day&gt;151 &amp;&amp; day&lt;=181){ month="6th Moon"; date=day-151; }else if(day&gt;181 &amp;&amp; day&lt;=212){ month="7th Moon"; date=day-181; }else if(day&gt;212 &amp;&amp; day&lt;=243){ month="8th Moon"; date=day-212; }else if(day&gt;243 &amp;&amp; day&lt;=273){ month="9th Moon"; date=day-243; }else if(day&gt;273 &amp;&amp; day&lt;=304){ month="10th Moon"; date=day-273; }else if(day&gt;304 &amp;&amp; day&lt;=334){ month="11th Moon" date=day-304; }else if(day&gt;334 &amp;&amp; day&lt;=365){ month="12th Moon"; date=day-334; }else{ month="Error"; date='1'; } var array=month+','+String(date); return array; }, getEberronDate = function(options){ var day = Number(options); var date; var month; if(day&lt;=28){ month = 'Zarantyr'; date = day; }else if(day&lt;=56){ month = 'Olarune'; date = day-28; }else if(day&lt;=84){ month = 'Therendor'; date = day-56; }else if(day&lt;=112){ month = 'Eyre'; date = day-84; }else if(day&lt;=140){ month = 'Dravago'; date = day-112; }else if(day&lt;=168){ month = 'Nymm'; date = day-140; }else if(day&lt;=196){ month = 'Lharvion'; date = day-168; }else if(day&lt;=224){ month = 'Rhaan'; date = day-196; }else if(day&lt;=252){ month = 'Sypheros'; date = day-224; }else if(day&lt;=280){ month = 'Aryth'; date = day-252; }else if(day&lt;=308){ month = 'Vult'; date = day-280; }else{ month = 'Zarantyr'; date = 1; } var array=month+','+String(date); return array; }, getFaerunOrdinal = function(options){ var args = options.content.split(","); var date = args[1]; var month = args[2]; var ordinal = state.Calendar.now.ordinal; if(date == 'festival'){ date = 1; }else{ date = Number(args[1]); } switch(month) { case 'Hammer': ordinal = date; break; case 'Midwinter': ordinal = 31; break; case 'Alturiak': ordinal = 31+date; break; case 'Ches': ordinal = 61+date; break; case 'Tarsakh': ordinal = 91+date; break; case 'Greengrass': ordinal = 122; break; case 'Mirtul': ordinal = 122+date; break; case 'Kythorn': ordinal = 152+date; break; case 'Flamerule': ordinal = 182+date; break; case 'Midsummer': ordinal = 213; break; case 'Sheildmeet': ordinal = 214; break; case 'Eleasias': ordinal = 214+date; break; case 'Eleint': ordinal = 244+date; break; case 'Highharvestide': ordinal = 275; break; case 'Marpenoth': ordinal = 275+date; break; case 'Uktar': ordinal = 305+date; break; case 'Feast of the Moon': ordinal = 335+date; break; case 'Nightal': ordinal = 336+date; break; } state.Calendar.now.ordinal = ordinal; }, getGreyhawkOrdinal = function(options){ var args = options.content.split(","); var date = args[1]; var month = args[2]; var ordinal = state.Calendar.now.ordinal; if(date == 'festival'){ date = 1; }else{ date = Number(args[1]); } switch(month) { case 'Needfest': ordinal = date; break; case 'Fire Seek': ordinal = 7+date; break; case 'Readying': ordinal = 35+date; break; case 'Coldeven': ordinal = 63+date; break; case 'Growfest': ordinal = 91+date; break; case 'Planting': ordinal = 98+date; break; case 'Flocktime': ordinal = 126+date; break; case 'Wealsun': ordinal = 154+date; break; case 'Richfest': ordinal = 182+date; break; case 'Reaping': ordinal = 189+date; break; case 'Goodmonth': ordinal = 217+date; break; case 'Harvester': ordinal = 245+date; break; case 'Brewfest': ordinal = 273+date; break; case 'Patchwall': ordinal = 280+date; break; case 'Readyreat': ordinal = 308+date; break; case 'Sunsebb': ordinal = 336+date; break; } state.Calendar.now.ordinal = ordinal; }, getModernOrdinal = function(options){ var args = options.content.split(","); var date = Number(args[1]); var month = args[2]; var ordinal = state.Calendar.now.ordinal; switch(month) { case '1st Moon': ordinal = date; break; case '2nd Moon': ordinal = 31+date; break; case '3rd Moon': ordinal = 60+date; break; case '4th Moon': ordinal = 91+date; break; case '5th Moon': ordinal = 121+date; break; case '6th Moon': ordinal = 152+date; break; case '7th Moon': ordinal = 182+date; break; case '8th Moon': ordinal = 213+date; break; case '9th Moon': ordinal = 244+date; break; case '10th Moon': ordinal = 274+date; break; case '11th Moon': ordinal = 305+date; break; case '12th Moon': ordinal = 366+date; break; } state.Calendar.now.ordinal = ordinal; }, getEberronOrdinal = function(options){ var args = options.content.split(","); var date = Number(args[1]); var month = args[2]; var ordinal = state.Calendar.now.ordinal; switch(month) { case 'Zarantyr': ordinal = date; break; case 'Olarune': ordinal = 28+date; break; case 'Therendor': ordinal = 56+date; break; case 'Eyre': ordinal = 84+date; break; case 'Dravago': ordinal = 112+date; break; case 'Nymm': ordinal = 140+date; break; case 'Lharvion': ordinal = 168+date; break; case 'Barrakas': ordinal = 196+date; break; case 'Rhaan': ordinal = 224+date; break; case 'Sypheros': ordinal = 252+date; break; case 'Aryth': ordinal = 280+date; break; case 'Vult': ordinal = 308+date; break; } state.Calendar.now.ordinal = ordinal; }, addday = function(no){ var leap = checkLeap(); var days = Number(no); var ordinal = Number(state.Calendar.now.ordinal); var world = Number(state.Calendar.now.world); var div = state.Calendar.now.divider; if(div!=0){ state.Calendar.now.down = Number(state.Calendar.now.down)+days; } var newordinal = ordinal+days; switch(world){ case 1: if(leap==0 &amp;&amp; ordinal &lt;= 214 &amp;&amp; newordinal &gt;= 214){ state.Calendar.now.ordinal = newordinal+1; }else{ state.Calendar.now.ordinal = newordinal; } if(newordinal&gt;366){ state.Calendar.now.ordinal=newordinal-366; state.Calendar.now.year = Number(state.Calendar.now.year)+1; } break; case 2: if(newordinal&gt;364){ state.Calendar.now.ordinal=newordinal-364; state.Calendar.now.year = Number(state.Calendar.now.year)+1; }else{ state.Calendar.now.ordinal = newordinal; } break; case 3: if(leap==0 &amp;&amp; ordinal &lt;= 60 &amp;&amp; newordinal &gt;= 60){ state.Calendar.now.ordinal = newordinal+1; }else{ state.Calendar.now.ordinal = newordinal; } if(newordinal&gt;366){ state.Calendar.now.ordinal=newordinal-366; state.Calendar.now.year = Number(state.Calendar.now.year)+1; } case 4: state.Calendar.now.ordinal = newordinal; break; } }, addtime = function(no){ var addhours = Number(no); var timecheck = state.Calendar.now.time; var currtime = state.Calendar.now.time.split(":"); var hour = currtime[0]; var newhour = Number(hour) + addhours; var day = 0; while (newhour &gt; 24) { newhour = newhour - 24; day ++; } if (day &gt; 0) { addday(day); weather(); } state.Calendar.now.time = newhour + ":" + currtime[1]; }, getsuffix = function(day) { var date = Number(day) var suffix if (date == 1 || date == 21 ){ suffix = 'st'; }else if (date == 2 || date == 22){ suffix = 'nd'; }else if (date == 3 || date == 23){ suffix = 'rd'; }else{ suffix = 'th'; } return suffix; }, weather = function() { var roll; var temperature; var wind; var precipitation; var season; var ordinal = state.Calendar.now.ordinal; if(ordinal &gt; 349 || ordinal &lt;= 75){ season = 'Winter' }else if(ordinal &lt;= 166){ season = 'Spring' }else if(ordinal &lt;=257 ){ season = 'Summer' }else if(ordinal &lt;=349 ){ season = 'Fall' } roll = Math.floor(Math.random()*(20-1+1)+1); if(roll&gt;=15 &amp;&amp; roll&lt;=17){ switch(season) { case 'Winter': temperature = 'It is a bitterly cold winter day. '; break; case 'Spring': temperature = 'It is a cold spring day. '; break; case 'Summer': temperature = 'It is a cool summer day. '; break; case 'Fall': temperature = 'It is a cold fall day. '; break; } }else if(roll&gt;=18 &amp;&amp; roll&lt;=20){ switch(season) { case 'Winter': temperature = 'It is a warm winter day. '; break; case 'Spring': temperature = 'It is a hot spring day. '; break; case 'Summer': temperature = 'It is a blisteringly hot summer day. '; break; case 'Fall': temperature = 'It is a hot fall day. '; break; } }else{ switch(season) { case 'Winter': temperature = 'It is a cold winter day. '; break; case 'Spring': temperature = 'It is a mild spring day. '; break; case 'Summer': temperature = 'It is a hot summer day. '; break; case 'Fall': temperature = 'It is a mild fall day. '; break; } } roll = Math.floor(Math.random()*(20-1+1)+1); if(roll&gt;=15 &amp;&amp; roll&lt;=17){ wind='There is a light breeze and '; }else if(roll&gt;=18 &amp;&amp; roll&lt;=20){ wind='There is a howling wind and '; }else{ wind='The air is still and '; } roll = Math.floor(Math.random()*(20-1+1)+1); if(roll&gt;=15 &amp;&amp; roll&lt;=17){ precipitation="Light rain or snow."; if(season=='Winter'){ precipitation = 'snow falls softly on the ground.'; }else{ precipitation = 'a light rain falls from the sky.'; } }else if(roll&gt;=18 &amp;&amp; roll&lt;=20){ if(season=='Winter'){ precipitation = 'snow falls thick and fast from the sky.'; }else{ precipitation = 'a torrential rain begins to fall.'; } }else{ roll = Math.floor(Math.random()*(2-1+1)+1); if(roll=1){ precipitation = 'the sky is overcast.'; }else{ precipitation = 'the sky is clear.'; } } var forecast=temperature+wind+precipitation; state.Calendar.now.weather = forecast; }, getFaerunMoon = function() { var year = state.Calendar.now.year; var ordinal = Number(state.Calendar.now.ordinal); var moonOrdinal; var moon; var remainder = year/4 - Math.floor(year/4); if(remainder==0.25) { moonOrdinal=ordinal; }else if (remainder==0.5) { moonOrdinal=ordinal+365; }else if (remainder==0.75) { moonOrdinal=ordinal+730; }else if (remainder==0) { moonOrdinal=ordinal+1095; } var today = ordinal/30.4375 - Math.floor(ordinal/30.4375); var tomorrow = (ordinal+1)/30.4375 - Math.floor((ordinal+1)/30.4375); var perc = today + ',' + tomorrow + ',' + moonOrdinal; moon = '&lt;img src="'+getMoon(perc)+'" style="width:30px;height:30px;"&gt;'; return moon; }, getGreyhawkMoon = function() { var ordinal = Number(state.Calendar.now.ordinal); var today; var tomorrow; var LunaOrd = ordinal + 10; var CeleneOrd = ordinal + 87; today = LunaOrd/28 - Math.floor(LunaOrd/28); tomorrow = (LunaOrd+1)/28 - Math.floor((LunaOrd+1)/28); var perc = today + ',' + tomorrow + ',' + 0; var Luna = getMoon(perc); today = CeleneOrd/91 - Math.floor(CeleneOrd/91); tomorrow = (CeleneOrd+1)/91 - Math.floor((CeleneOrd+1)/91); perc = today + ',' + tomorrow + ',' + 0; var Celene = getCelene(perc); //&lt;img src="'+moon+'" style="width:60px;height:60px;"&gt;' var moon = '&lt;img src="'+Luna+'" style="width:30px;height:30px;"&gt;&lt;img src="'+Celene+'" style="width:30px;height:30px;"&gt;'; return moon; }, getMoon = function(perc) { var args = perc.split(','); var today = args[0]; var tomorrow = args[1]; var moonOrdinal = args[2]; var moon; if(today==0 || tomorrow&lt;today || moonOrdinal==1){ // moon = 'Full Moon'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Twemoji_1f315.svg/512px-Twemoji_1f315.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Twemoji_1f315.svg/512px-Twemoji_1f315.svg.png</a>' }else if(today&lt;=0.25 &amp;&amp; tomorrow&gt;0.25){ // moon = 'Last Quarter'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Twemoji_1f317.svg/512px-Twemoji_1f317.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Twemoji_1f317.svg/512px-Twemoji_1f317.svg.png</a>'; }else if(today&lt;0.25){ // moon = 'Waning Gibbous'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Twemoji_1f316.svg/512px-Twemoji_1f316.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Twemoji_1f316.svg/512px-Twemoji_1f316.svg.png</a>'; }else if(today&lt;=0.5 &amp;&amp; tomorrow&gt;0.5){ // moon = 'New Moon'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Twemoji_1f311.svg/512px-Twemoji_1f311.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Twemoji_1f311.svg/512px-Twemoji_1f311.svg.png</a>'; }else if(today&lt;0.5){ // moon = 'Waning Crescent'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Twemoji_1f318.svg/512px-Twemoji_1f318.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Twemoji_1f318.svg/512px-Twemoji_1f318.svg.png</a>'; }else if(today&lt;=0.75 &amp;&amp; tomorrow&gt;0.75){ // moon = 'First Quarter'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Twemoji_1f313.svg/512px-Twemoji_1f313.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Twemoji_1f313.svg/512px-Twemoji_1f313.svg.png</a>'; }else if(today&lt;0.75){ // moon = 'Waxing Crescent'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Twemoji_1f312.svg/512px-Twemoji_1f312.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Twemoji_1f312.svg/512px-Twemoji_1f312.svg.png</a>'; }else{ // moon = 'Waxing Gibbous'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Twemoji_1f314.svg/512px-Twemoji_1f314.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Twemoji_1f314.svg/512px-Twemoji_1f314.svg.png</a>'; } return moon; }, getCelene = function(perc) { var args = perc.split(','); var today = args[0]; var tomorrow = args[1]; var moonOrdinal = args[2]; var moon; if(today==0 || tomorrow&lt;today || moonOrdinal==1){ // moon = 'Full Moon'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Emojione_1F315.svg/512px-Emojione_1F315.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Emojione_1F315.svg/512px-Emojione_1F315.svg.png</a>' }else if(today&lt;=0.25 &amp;&amp; tomorrow&gt;0.25){ // moon = 'Last Quarter'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Emojione_1F317.svg/512px-Emojione_1F317.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Emojione_1F317.svg/512px-Emojione_1F317.svg.png</a>'; }else if(today&lt;0.25){ // moon = 'Waning Gibbous'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Emojione_1F316.svg/512px-Emojione_1F316.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/d/d8/Emojione_1F316.svg/512px-Emojione_1F316.svg.png</a>'; }else if(today&lt;=0.5 &amp;&amp; tomorrow&gt;0.5){ // moon = 'New Moon'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Emojione_1F315.svg/512px-Emojione_1F315.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Emojione_1F315.svg/512px-Emojione_1F315.svg.png</a>'; }else if(today&lt;0.5){ // moon = 'Waning Crescent'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Emojione_1F318.svg/512px-Emojione_1F318.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Emojione_1F318.svg/512px-Emojione_1F318.svg.png</a>'; }else if(today&lt;=0.75 &amp;&amp; tomorrow&gt;0.75){ // moon = 'First Quarter'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Emojione_1F313.svg/512px-Emojione_1F313.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Emojione_1F313.svg/512px-Emojione_1F313.svg.png</a>'; }else if(today&lt;0.75){ // moon = 'Waxing Crescent'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Emojione_1F312.svg/512px-Emojione_1F312.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Emojione_1F312.svg/512px-Emojione_1F312.svg.png</a>'; }else{ // moon = 'Waxing Gibbous'; moon = '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Emojione_1F314.svg/512px-Emojione_1F314.svg.png" rel="nofollow">https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Emojione_1F314.svg/512px-Emojione_1F314.svg.png</a>'; } return moon; }, timemenu = function() { var timetype = state.Calendar.now.timetype; var timeselect = 'OFF'; switch(timetype) { case 'General': timeselect = '?{Time?|Morning (dawn)|Early Morning|Late Morning|Noon|Afternoon|Early Evening|Evening (dusk)|Late Evening|Midnight|After Midnight}'; break; case '24 Hour': timeselect = '?{Hour|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24},?{Minute|00,:00|15,:15|30,:30|45,:45}'; break; } return timeselect; }, checkInstall = function() { if(typeof state.Calendar == "undefined"){ setDefaults(); } if ( state.Calendar.now.version != version ){ checkDefaults(); } }, registerEventHandlers = function() { on('chat:message', handleInput); }; return { CheckInstall: checkInstall, RegisterEventHandlers: registerEventHandlers }; }()); on("ready",function(){ 'use strict'; Calendar.CheckInstall(); Calendar.RegisterEventHandlers(); });
1531791030
The Aaron
Pro
API Scripter
Try disabling those two and see if the multiline works.
everything else is exactly as I found it in one-click or github
1531791114
The Aaron
Pro
API Scripter
Neither of those posted scripts deals with playing , so probably not the culprit.
Negative. &nbsp;I'll try with Powercards and Roll20AM disabled also. &nbsp;brb
Same thing - no results
1531791573
The Aaron
Pro
API Scripter
Do you get the same error of: TypeError: Cannot set property 'playing' of undefined
I think Jakob, as annoying as it can be out of --silent, has a good idea with his API (CSA), in letting you have feedback as the script runs or throws errors. &nbsp;But the thing is - it's not actually throwing an error afaict, it tells me setup completed, which means it ran through the whole macro to get there. &nbsp;Although I've done that with CSA and noticed a bit of lag on callback, and got the setup complete message, then got his feedback message afterwards, so I digress ...
oh - lemme check
1531791716
The Aaron
Pro
API Scripter
Yeah.&nbsp; The crash is actually happening in Roll20's code because of a malformed object.&nbsp; If it were in TokenMod, it wouldn't crash and whisper you the error, callstack, and instructions on sending it to me. =D Want to PM me an invite and I'll come check it out?
This is all I have for that time: {"content":" {{title=Token Setup for TESTY }}{{... Setup Begun...}}","playerid":"-LGrD5x4_PCSWg_nzRyd","rolltemplate":"5e-shaped","target":"gm","target_name":"GM","type":"whisper","who":"Wolf Thunderspirit (GM)"} {"content":"!token-mod {{&lt;br/&gt;\n &nbsp;--on&lt;br/&gt;\n &nbsp; &nbsp;showname&lt;br/&gt;\n &nbsp; &nbsp;showplayers_name&lt;br/&gt;\n &nbsp; &nbsp;showplayers_bar1&lt;br/&gt;\n &nbsp; &nbsp;showplayers_aura1&lt;br/&gt;\n &nbsp; &nbsp;showplayers_aura2&lt;br/&gt;\n &nbsp; &nbsp;light_hassight&lt;br/&gt;\n &nbsp;--set&lt;br/&gt;\n &nbsp; &nbsp;represents|\"TESTY\"&lt;br/&gt;\n &nbsp; &nbsp;name|\"TESTY\"&lt;br/&gt;\n &nbsp; &nbsp;bar1_link|HP&lt;br/&gt;\n &nbsp; &nbsp;bar2_link|AC&lt;br/&gt;\n &nbsp; &nbsp;bar3_link|speed&lt;br/&gt;\n &nbsp; &nbsp;light_radius|5 &lt;br/&gt;\n &nbsp; &nbsp;light_dimradius|0&lt;br/&gt;\n &nbsp; &nbsp;light_angle|360&lt;br/&gt;\n &nbsp; &nbsp;light_losangle|360&lt;br/&gt;\n &nbsp; &nbsp;defaulttoken&lt;br/&gt;\n}}","playerid":"-LGrD5x4_PCSWg_nzRyd","selected":[{"_id":"-LGruZXWJlaNufSAG7fR","_type":"graphic"}],"type":"api","who":"Wolf Thunderspirit (GM)"} {"content":"{{title=Token Setup for TESTY }}{{... Setup Completed...}}","playerid":"-LGrD5x4_PCSWg_nzRyd","rolltemplate":"5e-shaped","target":"gm","target_name":"GM","type":"whisper","who":"Wolf Thunderspirit (GM)"}
absotively
done
I'm gonna be heading to bed soon Aaron, we may have to pick this up tomorrow. &nbsp; If you're able to assign yourself GM status, the global macros are: multiline "1Check", and single line (the one I can use) is "SetupTokenDefaults". &nbsp;If not, I'll PM you after work. &nbsp;(Around 5pm EST (NYC/Philly Time))
1531795893
The Aaron
Pro
API Scripter
Oh, I'll jump in real quick...