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

[Script] Event Tracking for The Aaron's Mystara Calendar Script

1447731370

Edited 1455995297
UPDATE 02/20/2016 -- v1.3 --Split the AddEvent command into AddEvent and AddEventGM to simplify input and resolve issues with GM events not showing properly ( per the recommendation of Jose P. ) UPDATE 11/18/2015 -- v1.2 ---Fixed the bug where the events added on the last day of the month did not display properly. ---Fixed the bug where Public events were not added as Public when added using option 3 (add by days) Thank you again to Gozer for catching them! UPDATE 11/18/2015 -- v1.1 --Added functionality to be able to add events by days forward or back in addition to by a specific date. --Fixed the bug where names with spaces caused part of the name to be included in confirmation message whispers (Thanks to&nbsp; Gozer the Gozeran for the catch!). **All changes are reflected in the instructions below where appropriate** ORIGINAL POST ( with updated documentation for features) I took a stab at some additions to Aaron's Mystara Calendar script ( original script thread ) for one of my upcoming campaigns and I thought I would share it. Basically I am too lazy to write things down so I went this route :). Below is documentation on the new functionality and a link to the code: GitHub link: <a href="https://github.com/Cephalopd/Roll20ScriptsMASTER/b" rel="nofollow">https://github.com/Cephalopd/Roll20ScriptsMASTER/b</a>... New Commands: !cal AddEvent target&nbsp;name --- This command adds a PUBLIC event to the calendar. example !cal AddEvent 11 12 1001 Harvest Festival --target - 3 options &nbsp; &nbsp; &nbsp;1) Today - adds event at on the current calendar day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; example: !cal AddEvent Today Harvest Festival &nbsp; &nbsp; &nbsp;2) Specific Date dd mm yyyy - adds an event at the specified date &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;example: !cal AddEvent 11 12 1001 Harvest Festival &nbsp; &nbsp; 3) A single numeric value which will add an event that number if days in the future (if positive) or past (if negative) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;example: !cal AddEvent 10 Harvest Festival --name - The name of the event. All text after the target and/or gm flag will be entered as the name of the event !cal AddEventGM target name --- This command adds a GM event to the calendar. The functionality of this command is the same as above except it adds an event visible only to the GM. !cal RemoveEvent name --- This command removes the first event it encounters with a matching name. example !cal RemoveEvent Harvest Festival --name - The name of the event to be removed. It is NOT case sensitive but must match exactly in other respects !cal GetEvents tense range -- This command makes the script whisper a table of the events to the player who sent the command. It will only show Public events to players and all events to GMs example !cal GetEvents Past 100 --tense - 3 Options &nbsp; &nbsp; &nbsp;1) Past - Events from the current day backwards to the first event or range limit set &nbsp; &nbsp; &nbsp;2) Present - Events for the current day only &nbsp; &nbsp; &nbsp;3) Future - Events from the current day forward to the last event or range limit set --range - An optional numeric value to limit the number of days in the future or past for which events will be listed !cal DisplayEvents tense range -- This functions as !cal GetEvents except it sends a table into chat containing only public events specified Changes to Existing Commands: !cal today - Below the date text this command now also sends an event table into chat containing only public events. If there are GM only events it whispers a second table to the GM only. !cal next - Same functionality as !cal today for the new date the calendar is set to ! cal prev - Same functionality as !cal today for the new date the calendar is set to KNOWN ISSUES: Currently if you have two events with the same name, only the first one will be shown if both are in the range you Get or Display. I am working on a work around or fix for this issue. For now, make sure your events are all uniquely named or that events with the same name won't be called up in the same table. My apologies for the invconvinience. Caveats: I absolutely built this script with my own needs and requirements in mind. I tried to make things a little more general use but if it is useful to some of you and there is additional functionality you could use please let me know and I will take a stab at it. Additionally my formatting skills are still Level 1 so there isn't a great visual match with Aaron's original designs. I realize the roll templates are a bit jarring but its the best I could muster with my current skill set :) I've done a fair bit of unit testing and think I have hammered out most of the bugs, but I inevitably missed some. When you find them let me know and I will be happy to try and fix them! Please feel free to critique the script or let me know if there are things I can do to make it more useful for any of you!
This is a great idea!&nbsp; I'm using his calendar (with month and day names tweaked) in my own campaign, and I've been thinking I'd like something to have notifications come up as time passes. Will all of the original !cal commands work as usual?
Thanks Gozer! All the original !cal commands will work as they did before (with the exception of the ones listed in my original post). If you are going to use this in a campaign that is already running the script you will need to make sure the Version value on line 3 is different than the one you are currently using (The script will have to install the variable where the events are stored). And of course make sure the other settings are the same as your current campaign so it doesn't change those (Months, year, ect). If you run into any problems or aren't sure about something let me know and I'm more than happy to help out!
Seems to be working, except for the prev &nbsp;command. &nbsp;When I use it, the script crashes and throws the following error:
Bummer. Sorry about the error Gozer. It seems to be working on my end which makes me think the additions to the state.Calendar variable might not have been setup correctly in your campaign with the existing calendar when you added the script. Would you mind putting the script below in your campaign and then running the !test command and sending me what shows up in the log? That will give me more to work with. on("chat:message", function(msg) { var cmdName = "!test"; var msgTxt = msg.content; var cmdNamePortion = msgTxt.slice (0, cmdName.length); if (msg.type !== 'api') return; if (cmdNamePortion !== cmdName) return; //TEST CODE HERE log (state.Calendar) });
Spinning up new sandbox... "-=&gt; Torch v0.8.4 &lt;=- [Sun Aug 23 2015 16:08:06 GMT-0500 (CDT)]" "-=&gt; TokenNameNumber v0.5.4 &lt;=- [Tue Sep 22 2015 17:04:58 GMT-0500 (CDT)]" "-=&gt; TurnMarker v1.3.1 &lt;=- [Tue Oct 13 2015 08:17:46 GMT-0500 (CDT)]" "-=&gt; GroupInitiative v0.9.12 &lt;=- [Tue Oct 13 2015 08:17:50 GMT-0500 (CDT)]" "-=&gt; Ammo v0.3.0 &lt;=- [Sat Mar 28 2015 23:19:58 GMT-0500 (CDT)]" "-=&gt; TokenMod v0.8.14 &lt;=- [Mon Sep 14 2015 08:02:23 GMT-0500 (CDT)]" "-=&gt; NoteLog v0.1.0 &lt;=- [Mon Jun 15 2015 23:25:11 GMT-0500 (CDT)]" {"version":1.4,"now":{"year":576,"month":11,"day":12},"setting":{"daysOfTheWeek":["Moonday","Godsday","Waterday","Earthday","Freeday","Starday","Sunday"],"weeksOfTheMonth":[1,2,3,4],"monthsOfTheYear":["Fireseek","Readying","Coldeven","Planting","FLocktime","Wealsun","Reaping","Goodmonth","Willowind","Patchwall","Readyreat","Sunsebb"],"yearPrefix":"CY "}}
Okay, it looks like the events variable did not get added to state for some reason... Running the script below with the !test command once should clear the problem up for you: on("chat:message", function(msg) { var cmdName = "!test"; var msgTxt = msg.content; var cmdNamePortion = msgTxt.slice (0, cmdName.length); if (msg.type !== 'api') return; if (cmdNamePortion !== cmdName) return; //TEST CODE HERE state.Calendar.events = [] }); I'll have to do some poking around this evening to see if I can figure out why it didn't install properly with your existing campaign script.
That seems to have cleared it up - I'll let you know if anything else crops up. &nbsp;Thanks!
A little cosmetic thing perhaps, but it's printing out part of my name, but not the whole thing. &nbsp;Think it has something to do with a name w/spaces: EDIT: If you're taking requests, it would be nice to be able to add an event for a certain number of days in the future (in addition to being able to set events on a target date). I mainly want to use this for reminders of things that will come up in play - "Oh, I'll have that armor ready for you in two weeks." Then, rather than having to know today's date, I could just do something like: !cal AddEvent Future 14 Armor Ready
1447780484

Edited 1447780598
Glad that seems to fix the first error! The second is because my code is assuming a name without spaces. Oversight on my part :/. I'll put that on my to fix list and post back when&nbsp;I get it taken care of. EDIT: Just saw your edit. That was something I was playing around with but never actually finished. But I can get that worked in without too much trouble. I'll post back with that addition too, though it may take me a few days :)
1447796413
The Aaron
Pro
API Scripter
Sweet additions! &nbsp;I'd always meant to add events to it. &nbsp;I have a newer version I've been working on (but somewhat delayed by life and other things) where I intend to support events (holidays, battles, anniversaries of events, meetings, etc, etc.), and Player/GM notes. &nbsp;Looks like you've done a load of the thinking about it already. =D
Gozer the Gozerian said: EDIT: If you're taking requests, it would be nice to be able to add an event for a certain number of days in the future (in addition to being able to set events on a target date). I mainly want to use this for reminders of things that will come up in play - "Oh, I'll have that armor ready for you in two weeks." Then, rather than having to know today's date, I could just do something like: !cal AddEvent Future 14 Armor Ready Would really like this option if at all possible.
The Aaron said: Sweet additions! &nbsp;I'd always meant to add events to it. &nbsp;I have a newer version I've been working on (but somewhat delayed by life and other things) where I intend to support events (holidays, battles, anniversaries of events, meetings, etc, etc.), and Player/GM notes. &nbsp;Looks like you've done a load of the thinking about it already. =D Thanks Aaron! I appreciate the compliments! It took a while to get it all worked out but I'm pretty happy with where it is at. Arthur B. said: Gozer the Gozerian said: EDIT: If you're taking requests, it would be nice to be able to add an event for a certain number of days in the future (in addition to being able to set events on a target date). I mainly want to use this for reminders of things that will come up in play - "Oh, I'll have that armor ready for you in two weeks." Then, rather than having to know today's date, I could just do something like: !cal AddEvent Future 14 Armor Ready Would really like this option if at all possible. The code on GitHub has been updated with this feature as well as a fix for the name spacing issue Gozer reported. See the OP for the syntax of the new functionality. Let me know if you all run into any issues or think of anything else!
EDIT: I see now what you're doing - the public part says "no events," and the event is then whispered to the GM. &nbsp;Sorry for doubting you! EDIT, again: However, there does seem to be something breaking down. &nbsp;When the event is added, the feedback you get from the script says "your PUBLIC event..." whether it's a Public or GM event. &nbsp;I think that's what confused me at first, then I paid attention to the yellow background. The GM portion of AddEvent doesn't seem to be working. &nbsp;It adds it as a Public event: I copied the syntax from the OP, Then got this result:
Found another one! &nbsp;It looks like something funny's going on at the end of the month: The calendar script is interpreting the date correctly, but for some reason the event is showing as "Vatermont 0th" Just trying to keep you on your toes! &nbsp;(It's much easier to find problems than fix them. &nbsp;:)
No worries! I appreciate you testing it so thoroughly! It's so easy to get myopic when its your own work. I've found the problem on the first issue after a quick glance... It was a dumb copy/paste error. I'll get that uploaded tonight.&nbsp; I'll have to do some more digging this evening on the end of the month one, though as I'm writing this I think I may know what I did that is messing things up... Thanks again Gozer, I appreciate the help!
Got them both Gozer. Thank you again for catching them and letting me know about them! I did find a known issue. Since I am using roll templates to format the output, events with the same name will only show the first one. I'm playing around with a work around but the real answer is doing real formatting so this one may be a ways out. I added a note in the OP.
Ok, actually, GM events now still give the notification that a Public event was set, but then shows it as public as well (i.e., it doesn't whisper the event to the GM). EDIT:&nbsp; In addition, moving the calendar to the event date after setting an event crashes the script.&nbsp; Then with a reset, it works.&nbsp; The error message it returns is below. Just to clarify, here's how I'm testing.&nbsp; I add the event with: !cal AddEvent 2 GM Test Event Then I input the command to advance the calendar: !cal next 2 Then, the script crashes.&nbsp; I restart, hit !cal next 2 and the calendar advances 2 days, and shows the event - but it shows it not as a GM event, but a Public event.
Hmm, I'll take another look at it tonight. Thanks for the bug reports yet again and sorry for all the issues... I thought I had it working better than this :/&nbsp;
Is there any way that someone could add a 2nd moon cycle and have it show up when you pull up the current day?
1449014738
The Aaron
Pro
API Scripter
On what interval?
About 1.25 times faster than the 1st.
1449015599
The Aaron
Pro
API Scripter
So, 22 days? :)
Yeah, that's good.
1449034135

Edited 1449034288
The Aaron
Pro
API Scripter
Second Moon, 22 day cycle (Which means it repeats every 11 years in that calendar): var Calendar = Calendar || { &nbsp; &nbsp; //Modified with event tracking code &nbsp; &nbsp; version: 1.4, &nbsp; &nbsp; lunarPhaseSize: 15, &nbsp; &nbsp; lunarPhasesImage: '<a href="https://s3.amazonaws.com/files.d20.io/images/4277527/CJJWBbiHx3jHglPdccPx3A/max.png?1401939451" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277527/CJJWBbiHx3jHglPdccPx3A/max.png?1401939451</a>', &nbsp; &nbsp; clearImage: '<a href="https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/max.png?1401938659" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/max.png?1401938659</a>', &nbsp; &nbsp; _Ordinal: function(num) { &nbsp; &nbsp; &nbsp; &nbsp; var ones=(num%10); &nbsp; &nbsp; &nbsp; &nbsp; var tens=((num%100)-ones); &nbsp; &nbsp; &nbsp; &nbsp; switch(ones) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 1: return ((10 == tens) ? 'th' : 'st'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 2: return ((10 == tens) ? 'th' : 'nd'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 3: return ((10 == tens) ? 'th' : 'rd'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: return 'th'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetOptionsFromTokens: function (tokens) { &nbsp; &nbsp; &nbsp; &nbsp; var options={}; &nbsp; &nbsp; &nbsp; &nbsp; var switches=_.filter(tokens, function(tok){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null != tok.match(/^--/); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; _.each(switches,function(s){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(s) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '--lunar': options.showLunarPhases=true; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '--nolunar': options.showLunarPhases=false; break; &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;return options; &nbsp; &nbsp; }, &nbsp; &nbsp; CheckInstall: function() { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( ! state.hasOwnProperty('Calendar') || state.Calendar.version != Calendar.version) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Default Settings stored in the state. */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; version: Calendar.version, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; now: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; year: 1001, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; month: 12, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; day: 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setting: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; daysOfTheWeek: [ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Lunadain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Gromdain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Tserdain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Moldain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Nytdain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Loshdain', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Soladain'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeksOfTheMonth: [1,2,3,4], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; monthsOfTheYear: [ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Nuwmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Vatermont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Thaumont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Flaurmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Yarthmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Klarmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Felmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Fyrmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Ambyrmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Sviftmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Eirmont', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Kaldmont'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yearPrefix: 'AC ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; events: [] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; AdvanceDays: function(days){ &nbsp; &nbsp; &nbsp; &nbsp; var y=Math.floor(days/336); &nbsp; &nbsp; &nbsp; &nbsp; days-=(y*336); &nbsp; &nbsp; &nbsp; &nbsp; var m = Math.floor(days/28); &nbsp; &nbsp; &nbsp; &nbsp; days-=(m*28); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n = state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.day+=days; &nbsp; &nbsp; &nbsp; &nbsp; var _m=Math.floor((n.day-1)/28); &nbsp; &nbsp; &nbsp; &nbsp; n.day-=(_m*28); &nbsp; &nbsp; &nbsp; &nbsp; m+=_m; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.month+=m; &nbsp; &nbsp; &nbsp; &nbsp; var _y=Math.floor((n.month-1)/12); &nbsp; &nbsp; &nbsp; &nbsp; n.month-=(_y*12); &nbsp; &nbsp; &nbsp; &nbsp; y+=_y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.year+=y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.now=n; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; RemoveDays: function(days){ &nbsp; &nbsp; &nbsp; &nbsp; var y=Math.floor(days/336); &nbsp; &nbsp; &nbsp; &nbsp; days-=(y*336); &nbsp; &nbsp; &nbsp; &nbsp; var m = Math.floor(days/28); &nbsp; &nbsp; &nbsp; &nbsp; days-=(m*28); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n = state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.day-=days; &nbsp; &nbsp; &nbsp; &nbsp; var _m=((n.day&gt;0)?(0):(1)); &nbsp; &nbsp; &nbsp; &nbsp; n.day+=(_m*28); &nbsp; &nbsp; &nbsp; &nbsp; m+=_m; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.month-=m; &nbsp; &nbsp; &nbsp; &nbsp; var _y=((n.month&gt;0)?(0):(1)); &nbsp; &nbsp; &nbsp; &nbsp; n.month+=(_y*12); &nbsp; &nbsp; &nbsp; &nbsp; y+=_y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.year-=y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.now=n; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetPhaseForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: true &nbsp; &nbsp; &nbsp; &nbsp; }), &nbsp; &nbsp; &nbsp; &nbsp; moon1={ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row: ((d.day-1)%7), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; col: Math.floor((d.day-1)/7) &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; m2day=parseInt(((((d.month-1)*28+((d.year%11)*336)+d.day)%22)/21)*28), &nbsp; &nbsp; &nbsp; &nbsp; moon2={ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row: ((m2day-1)%7), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; col: Math.floor((m2day-1)/7) &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ((opt.showLunarPhases)?( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '&lt;img src="' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.clearImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'" style="width: '+Calendar.lunarPhaseSize+'px; height: '+Calendar.lunarPhaseSize+'px; background:url(' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.lunarPhasesImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +') -'+moon1.row*Calendar.lunarPhaseSize+'px -'+moon1.col*Calendar.lunarPhaseSize+'px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;img src="' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.clearImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'" style="width: '+(Calendar.lunarPhaseSize)+'px; height: '+(Calendar.lunarPhaseSize)+'px; background:url(' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.lunarPhasesImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +') -'+moon2.row*Calendar.lunarPhaseSize+'px -'+moon2.col*Calendar.lunarPhaseSize+'px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ):(''));&nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetDayForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n=state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp; var img = Calendar._GetPhaseForDate(d,opt) &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(d.year == n.year && d.month == n.month && d.day == n.day) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight: bold; color: #990000;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else if( (d.year &lt; n.year)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || ( (d.year &lt;= n.year) && (d.month&lt;n.month))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || ( (d.year &lt;= n.year) && (d.month&lt;=n.month) && (d.day&lt;n.day)) ) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;strike style="color:red; font-weight: bold;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight:bold; color:#999999;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/strike&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight: bold; color: #000099;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetMonthForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showMonthNumber: false &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; var daysHeader=''; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.daysOfTheWeek,function(d){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; daysHeader+='&lt;th&gt;&lt;div style="width: 40px;margin: 0px auto;"&gt;'+d.substring(0,2)+'&lt;/div&gt;&lt;/th&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var mday=_.clone(d); &nbsp; &nbsp; &nbsp; &nbsp; var weeks=''; &nbsp; &nbsp; &nbsp; &nbsp; mday.day=1; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.weeksOfTheMonth,function(w){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;tr&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.daysOfTheWeek,function(d){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;td style="vertical-align: middle; text-align:right;"&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+=Calendar._GetDayForDate(mday,opt); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;/td&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mday.day++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;/tr&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;table style="border:1px solid black;background-color:#eeffee;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;tr&gt;&lt;th colspan="'+s.daysOfTheWeek.length+'"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +((opt.showMonthNumber)?('&lt;div style="float:right; padding: 0px 3px;"&gt;'+d.month+'&lt;/div&gt;'):('')) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +s.monthsOfTheYear[d.month-1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +((opt.showYear)?(' '+d.year):('')) &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/th&gt;&lt;/tr&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;tr style="border-bottom: 1px solid #aaaaaa;"&gt;'+daysHeader+'&lt;/tr&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +weeks &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/table&gt;'; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetYearForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showMonthNumber: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; var yday=_.clone(d); &nbsp; &nbsp; &nbsp; &nbsp; yday.day=1; &nbsp; &nbsp; &nbsp; &nbsp; yday.month=1; &nbsp; &nbsp; &nbsp; &nbsp; var months=''; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3,4],function(r){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3],function(c){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;div style="float:left;padding: 2px 2px;"&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+=Calendar._GetMonthForDate(yday,opt); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yday.month++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="background-color: #DEB887; border: 3px solid #8B4513; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border-bottom: 2px solid #8B0000;margin: 3px 3px;font-weight: bold; font-size: 130%; text-align: center;"&gt;'+s.yearPrefix+d.year+'&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +months &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;/div&gt;'; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetDateAsString: function(date){ &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; return s.monthsOfTheYear[date.month-1]+' '+date.day+Calendar._Ordinal(date.day)+', '+s.yearPrefix +date.year; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowDate: function(d,options) { &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style=\'' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'color: white;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'padding: 5px 5px;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'background-color: #000033;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'font-weight: bold;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'font-family: Baskerville, "Baskerville Old Face", "Goudy Old Style", Garamond, "Times New Roman", serif;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'border: 3px solid #999999;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'text-align: center;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'\'&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar._GetDateAsString(d,opt) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar._GetPhaseForDate(d,opt) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowMonth: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct '+Calendar._GetMonthForDate(d,opt)); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowYear: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: false &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct '+Calendar._GetYearForDate(d,opt)); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; playerGM: 0, &nbsp; &nbsp; senderID: '', &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; calcDateIndex: function (day,month,year) { &nbsp; &nbsp; &nbsp; &nbsp; return ((year*336) + ((month-1)*28) + day); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; calcIndexToDate: function (index) { &nbsp; &nbsp; &nbsp; &nbsp; var year = Math.floor(index / 336) &nbsp; &nbsp; &nbsp; &nbsp; var month = Math.floor((index % 336) / 28) + 1 &nbsp; &nbsp; &nbsp; &nbsp; var day = Math.floor((index % 336) % 28) if (day === 0) { day = 28 month = month - 1 } &nbsp; &nbsp; &nbsp; &nbsp; var dateArray = [day,month,year] &nbsp; &nbsp; &nbsp; &nbsp; return dateArray; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; spliceEventIn: function (location,name,index,gm){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var allEvents = state.Calendar.events &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allEvents.splice(location,0,[name,index,gm]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.events = allEvents &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; addCalendarEvent: function (name,day,month,year,gm) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var firstEvent = state.Calendar.events[0] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var endEvents = state.Calendar.events.length - 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastEvent = state.Calendar.events[endEvents] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newEventIndex = Calendar.calcDateIndex (day,month,year) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (state.Calendar.events[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newEventIndex &lt; firstEvent[1]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (0,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (newEventIndex &gt; lastEvent[1]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (state.Calendar.events.length,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newEventIndex &lt;= thisEventIndex) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (i,name,newEventIndex,gm); &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; &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; Calendar.spliceEventIn (0,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; removeCalendarEvent: function (name) { &nbsp; &nbsp; &nbsp; &nbsp; if (state.Calendar.events[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (name.toUpperCase() == thisEvent[0].toUpperCase()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.events.splice(i,1) &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; getEvents: function (direction,limit) { &nbsp; &nbsp; &nbsp; &nbsp; var currentIndex = Calendar.calcDateIndex (state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year) &nbsp; &nbsp; &nbsp; &nbsp; var findEdgeIndex = function (direction,limit,start) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return start - limit; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (direction == 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return start + limit; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var allRecordedEvents = [] &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var returnEvents = function (start,end) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (thisEventIndex &gt;= start && thisEventIndex &lt;= end ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allRecordedEvents.splice(state.Calendar.events.length,0,thisEvent) &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; var removeGMEvents = function (array) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var events = array &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; array.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEvent = events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (thisEvent[2] === null){ &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; if (thisEvent[2].toUpperCase() == "GM") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; events.splice(i,1); &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; return events; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == 0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex,currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; } else if (limit) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex - limit, currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex, currentIndex + limit); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (0,currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsLength = state.Calendar.events.length &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastEvent = state.Calendar.events[eventsLength - 1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex, lastEvent[1]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (playerGM == false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allRecordedEvents = removeGMEvents (allRecordedEvents) &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //DO NOTHING &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return allRecordedEvents &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; convertDateArrayToObject: function (array) { &nbsp; &nbsp; var newDateObject = {} &nbsp; &nbsp; newDateObject.day = array[0] &nbsp; &nbsp; newDateObject.month = array[1] &nbsp; &nbsp; newDateObject.year = array[2] &nbsp; &nbsp; return newDateObject; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; buildEventTable: function (direction,title,limit) { &nbsp; &nbsp; &nbsp; &nbsp; var targetEvents = Calendar.getEvents (direction,limit); &nbsp; &nbsp; &nbsp; &nbsp; if (targetEvents[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventTable = "&{template:default} {{name=" + title + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; targetEvents.length; i++){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = targetEvents[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var dateArray = Calendar.calcIndexToDate (thisEventIndex) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventString = Calendar._GetDateAsString (Calendar.convertDateArrayToObject (dateArray)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newTableEntry = "{{" + thisEvent[0] + "=" + thisEventString + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventTable = eventTable + newTableEntry &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventTable; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "NO EVENTS FOUND FOR SPECIFIED RANGE"; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; HandleInput: function(tokens){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var options = Calendar._GetOptionsFromTokens(tokens); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tokens=_.filter(tokens, function(tok){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null == tok.match(/^--/); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; var cmd = tokens[0] || 'month'; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var concatenateEventName = function (start) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var fullEventName = '' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastWord = tokens.length-1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = start; i &lt; tokens.length - 1; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newNamePortion = tokens[i] + " " &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName + newNamePortion &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName + tokens[lastWord] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return fullEventName; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sendMsg = function (message) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", "/w " + senderID[0] + " " + message) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsToday = function () { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var events = Calendar.buildEventTable (0,"Today's Events") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (events === "NO EVENTS FOUND FOR SPECIFIED RANGE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "No Events Today"; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return events; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var returnEventRange = function (direction, title) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[2]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = Calendar.buildEventTable(direction, title + " (" + tokens[2] + " days)",parseInt(tokens[2])) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventsMessage; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = Calendar.buildEventTable(direction,"All " +title) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventsMessage; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (cmd) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'month':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowMonth(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'year': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowYear(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'today': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; &nbsp; case 'next': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var days=tokens[1] || 1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.AdvanceDays(days); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; case 'prev': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var days=tokens[1] || 1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.RemoveDays(days); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; &nbsp; case 'AddEvent': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[1].toUpperCase() === "TODAY" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[2].toUpperCase() === "GM") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(3),state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year,"GM"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your GM event has been added TODAY"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(3),state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your PUBLIC event has been added TODAY"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (isNaN(parseInt(tokens[1])) === false && isNaN(parseInt(tokens[2])) === false && isNaN(parseInt(tokens[3])) === false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[4].toUpperCase() === "GM" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(4),parseInt(tokens[1]),parseInt(tokens[2]),parseInt(tokens[3]),"GM"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your GM event has been added at the SPECIFIED DATE") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(4),parseInt(tokens[1]),parseInt(tokens[2]),parseInt(tokens[3])); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your PUBLIC event has been added at the SPECIFIED DATE") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (isNaN(parseInt(tokens[1])) === false && isNaN(parseInt(tokens[2])) === true) { var currentIndex = Calendar.calcDateIndex (state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year); var newIndex = currentIndex + parseInt(tokens[1]) var newDate = Calendar.calcIndexToDate (newIndex) if (tokens[2].toUpperCase === "GM") { Calendar.addCalendarEvent(concatenateEventName(3),newDate[0],newDate[1],newDate[2],"GM"); sendMsg ("Your GM event has been added " + tokens[1] + " days from today"); } else { Calendar.addCalendarEvent(concatenateEventName(2),newDate[0],newDate[1],newDate[2]); sendMsg ("Your PUBLIC event has been added " + tokens[1] + " days from today"); }; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'RemoveEvent': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; targetName = concatenateEventName(1) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.removeCalendarEvent (targetName); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("You have removed the event named -- " + targetName) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'GetEvents': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var targetFrame = tokens[1].toUpperCase() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (targetFrame === "PAST" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + returnEventRange (-1,"Past Events")); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "PRESENT") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + eventsMessage); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "FUTURE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + returnEventRange (1,"Upcoming Events")); &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; case 'DisplayEvents': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var targetFrame = tokens[1].toUpperCase() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (targetFrame === "PAST" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", returnEventRange (-1,"Past Events")); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "PRESENT") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", eventsMessage); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "FUTURE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", returnEventRange (1,"Upcoming Events")); &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; &nbsp; &nbsp; RegisterEventHandlers: function() { &nbsp; &nbsp; &nbsp; &nbsp; on("chat:message", function (msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Exit if not an api command */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (msg.type != "api") return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* clean up message bits. */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.who = msg.who.replace(" (GM)", ""); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.content = msg.content.replace("(GM) ", ""); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var tokenized = msg.content.split(" "); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var command = tokenized[0]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sendingPlayerID = msg.playerid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; senderID = msg.who.split(" ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = playerIsGM(sendingPlayerID); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(command) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "!cal": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "!calendar": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.HandleInput(_.rest(tokenized)); &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; &nbsp; &nbsp; &nbsp; case "!s": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '/direct &lt;div style="border: 2px solid red;"&gt;&lt;b&gt;state.Calendar&lt;/b&gt;&lt;br&gt;&lt;pre&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +JSON.stringify(state.Calendar,undefined," &nbsp; ").replace(/\n/g,'&lt;br&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +"&lt;/pre&gt;&lt;/div&gt;" ); &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; }; on("ready",function(){ &nbsp; &nbsp; Calendar.CheckInstall();&nbsp; &nbsp; &nbsp; Calendar.RegisterEventHandlers(); }); That really is an old script. &nbsp;I should get around to finishing up the newer version...
So would I just add this to the current script or overwrite the current script?
1449042743
Silvyre
Forum Champion
The Aaron posted the script in its entirity with the modifications made.
If I copy and paste this script into original script, will it keep all the events that are in there? Or will I have to re-add the events?
1449097393
The Aaron
Pro
API Scripter
It will keep them. &nbsp;They are stored in the state object. &nbsp;I copied Brent's version for the modifications, so it will be as his version, but with an extra moon.
The Aaron said: It will keep them. &nbsp;They are stored in the state object. &nbsp;I copied Brent's version for the modifications, so it will be as his version, but with an extra moon. Thanks Aaron. I've said it before and will say it again, you guys are awesome.
1449111849
The Aaron
Pro
API Scripter
No problem!
1450549162
The Aaron
Pro
API Scripter
Hey Brent, I sent you a pull request with a few minor bugfixes: &nbsp; <a href="https://github.com/Cephalopd/Roll20ScriptsMASTER/p" rel="nofollow">https://github.com/Cephalopd/Roll20ScriptsMASTER/p</a>... In particular, it should allow current calendar users to switch over without having to lose their existing configuration. =D
Thanks Aaron. I just accepted it. Improving/fixing this has been hovering in the middle of my to-do list for a while but end of semester and wrapping up a major experiment have kept it pinned down :/ I do have Douglas Crockford's book ready for some light holiday reading though! :)
1450558408
The Aaron
Pro
API Scripter
Sweet! &nbsp;Ping me if you wanna chat about JS:tGP! &nbsp;=D
1451673356

Edited 1451680737
OK so... I did some fiddling, and for the most part it works... lol most... I've attempted to convert this to Forgotten Realms. Edit : I just found a great Calendar online that shows exactly how FR works.. Faerun Calendar Major Differences: 3 ten day weeks instead of 4 sevens (Referred to as a Ten-day) No day names Different month names There are other subtle differences (like a&nbsp;separate&nbsp;day for holidays,&nbsp;basically&nbsp;a 1 day month) that I didn't bother with adding because the complexity seemed silly. The part that i'm having issues with is the !cal year command, when i bring it up it only lists 9 months. Here is the script I have edited. var Calendar = Calendar || { &nbsp; &nbsp; //Modified with event tracking code &nbsp; &nbsp; version: 1.5, &nbsp; &nbsp; lunarPhaseSize: 15, &nbsp; &nbsp; lunarPhasesImage: '<a href="https://s3.amazonaws.com/files.d20.io/images/4277527/CJJWBbiHx3jHglPdccPx3A/max.png?1401939451" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277527/CJJWBbiHx3jHglPdccPx3A/max.png?1401939451</a>', &nbsp; &nbsp; clearImage: '<a href="https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/max.png?1401938659" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/max.png?1401938659</a>', &nbsp; &nbsp; _Ordinal: function(num) { &nbsp; &nbsp; &nbsp; &nbsp; var ones=(num%10); &nbsp; &nbsp; &nbsp; &nbsp; var tens=((num%100)-ones); &nbsp; &nbsp; &nbsp; &nbsp; switch(ones) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 1: return ((10 == tens) ? 'th' : 'st'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 2: return ((10 == tens) ? 'th' : 'nd'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 3: return ((10 == tens) ? 'th' : 'rd'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: return 'th'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetOptionsFromTokens: function (tokens) { &nbsp; &nbsp; &nbsp; &nbsp; var options={}; &nbsp; &nbsp; &nbsp; &nbsp; var switches=_.filter(tokens, function(tok){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null != tok.match(/^--/); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; _.each(switches,function(s){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(s) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '--lunar': options.showLunarPhases=true; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '--nolunar': options.showLunarPhases=false; break; &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;return options; &nbsp; &nbsp; }, &nbsp; &nbsp; CheckInstall: function() { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( ! state.hasOwnProperty('Calendar') || state.Calendar.version != Calendar.version) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Default Settings stored in the state. */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; version: Calendar.version, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; now: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; year: 1489, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; month: 5, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; day: 20 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setting: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; daysOfTheWeek: [ &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; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ''], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeksOfTheMonth: [1,2,3], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; monthsOfTheYear: [ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Hammer-Jan', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Alturiak-Feb', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Ches-Mar', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Tarsakh-Apr', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Mirtul-May', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Kythorn-Jun', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Flamerule-Jul', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Elesias-Aug', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Eleint-Sep', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Marpenoth-Oct', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Uktar-Nov', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Nightal-Dec'], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yearPrefix: 'DR ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; events: [] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if(!_.has(state.Calendar,'events')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log('-- Adding events[]'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.events = []; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; AdvanceDays: function(days){ &nbsp; &nbsp; &nbsp; &nbsp; var y=Math.floor(days/360); &nbsp; &nbsp; &nbsp; &nbsp; days-=(y*360); &nbsp; &nbsp; &nbsp; &nbsp; var m = Math.floor(days/30); &nbsp; &nbsp; &nbsp; &nbsp; days-=(m*30); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n = state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.day+=days; &nbsp; &nbsp; &nbsp; &nbsp; var _m=Math.floor((n.day-1)/30); &nbsp; &nbsp; &nbsp; &nbsp; n.day-=(_m*30); &nbsp; &nbsp; &nbsp; &nbsp; m+=_m; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.month+=m; &nbsp; &nbsp; &nbsp; &nbsp; var _y=Math.floor((n.month-1)/12); &nbsp; &nbsp; &nbsp; &nbsp; n.month-=(_y*12); &nbsp; &nbsp; &nbsp; &nbsp; y+=_y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.year+=y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.now=n; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; RemoveDays: function(days){ &nbsp; &nbsp; &nbsp; &nbsp; var y=Math.floor(days/360); &nbsp; &nbsp; &nbsp; &nbsp; days-=(y*360); &nbsp; &nbsp; &nbsp; &nbsp; var m = Math.floor(days/30); &nbsp; &nbsp; &nbsp; &nbsp; days-=(m*30); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n = state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.day-=days; &nbsp; &nbsp; &nbsp; &nbsp; var _m=((n.day&gt;0)?(0):(1)); &nbsp; &nbsp; &nbsp; &nbsp; n.day+=(_m*30); &nbsp; &nbsp; &nbsp; &nbsp; m+=_m; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.month-=m; &nbsp; &nbsp; &nbsp; &nbsp; var _y=((n.month&gt;0)?(0):(1)); &nbsp; &nbsp; &nbsp; &nbsp; n.month+=(_y*12); &nbsp; &nbsp; &nbsp; &nbsp; y+=_y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n.year-=y; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.now=n; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetPhaseForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; return ((opt.showLunarPhases)?( &nbsp; &nbsp; &nbsp; &nbsp; '&lt;img src="' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.clearImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'" style="width: '+Calendar.lunarPhaseSize+'px; height: '+Calendar.lunarPhaseSize+'px; background:url(' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar.lunarPhasesImage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +') -'+((d.day-1)%10)*Calendar.lunarPhaseSize+'px -'+Math.floor((d.day-1)/10)*Calendar.lunarPhaseSize+'px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ):(''));&nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetDayForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var n=state.Calendar.now; &nbsp; &nbsp; &nbsp; &nbsp; var img = Calendar._GetPhaseForDate(d,opt) &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(d.year == n.year && d.month == n.month && d.day == n.day) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight: bold; color: #990000;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else if( (d.year &lt; n.year)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || ( (d.year &lt;= n.year) && (d.month&lt;n.month))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || ( (d.year &lt;= n.year) && (d.month&lt;=n.month) && (d.day&lt;n.day)) ) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;strike style="color:red; font-weight: bold;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight:bold; color:#999999;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/strike&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="white-space: nowrap;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;span style="font-weight: bold; color: #000099;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +d.day &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +img &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetMonthForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showMonthNumber: false &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; var daysHeader=''; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.daysOfTheWeek,function(d){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; daysHeader+='&lt;th&gt;&lt;div style="width: 25px;margin: 0px auto;"&gt;'+d.substring(0,2)+'&lt;/div&gt;&lt;/th&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var mday=_.clone(d); &nbsp; &nbsp; &nbsp; &nbsp; var weeks=''; &nbsp; &nbsp; &nbsp; &nbsp; mday.day=1; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.weeksOfTheMonth,function(w){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;tr&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each(s.daysOfTheWeek,function(d){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;td style="vertical-align: middle; text-align:right;"&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+=Calendar._GetDayForDate(mday,opt); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;/td&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mday.day++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weeks+='&lt;/tr&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;table style="border:1px solid black;background-color:#eeffee;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;tr&gt;&lt;th colspan="'+s.daysOfTheWeek.length+'"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +((opt.showMonthNumber)?('&lt;div style="float:right; padding: 0px 3px;"&gt;'+d.month+'&lt;/div&gt;'):('')) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +s.monthsOfTheYear[d.month-1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +((opt.showYear)?(' '+d.year):('')) &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/th&gt;&lt;/tr&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;tr style="border-bottom: 1px solid #aaaaaa;"&gt;'+daysHeader+'&lt;/tr&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +weeks &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/table&gt;'; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetYearForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showMonthNumber: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; var yday=_.clone(d); &nbsp; &nbsp; &nbsp; &nbsp; yday.day=1; &nbsp; &nbsp; &nbsp; &nbsp; yday.month=1; &nbsp; &nbsp; &nbsp; &nbsp; var months=''; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3],function(r){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3],function(c){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;div style="float:left;padding: 2px 2px;"&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+=Calendar._GetMonthForDate(yday,opt); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yday.month++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="background-color: #DEB887; border: 3px solid #8B4513; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border-bottom: 2px solid #8B0000;margin: 3px 3px;font-weight: bold; font-size: 130%; text-align: center;"&gt;'+s.yearPrefix+d.year+'&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +months &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;/div&gt;'; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; _GetDateAsString: function(date){ &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; return s.monthsOfTheYear[date.month-1]+' '+date.day+Calendar._Ordinal(date.day)+', '+s.yearPrefix +date.year; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowDate: function(d,options) { &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style=\'' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'color: white;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'padding: 5px 5px;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'background-color: #000033;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'font-weight: bold;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'font-family: Baskerville, "Baskerville Old Face", "Goudy Old Style", Garamond, "Times New Roman", serif;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'border: 3px solid #999999;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'text-align: center;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'\'&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar._GetDateAsString(d,opt) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +' ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar._GetPhaseForDate(d,opt) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowMonth: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct '+Calendar._GetMonthForDate(d,opt)); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ShowYear: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: false &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; sendChat('','/direct '+Calendar._GetYearForDate(d,opt)); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; playerGM: 0, &nbsp; &nbsp; senderID: '', &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; calcDateIndex: function (day,month,year) { &nbsp; &nbsp; &nbsp; &nbsp; return ((year*360) + ((month-1)*30) + day); &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; calcIndexToDate: function (index) { &nbsp; &nbsp; &nbsp; &nbsp; var year = Math.floor(index / 360) &nbsp; &nbsp; &nbsp; &nbsp; var month = Math.floor((index % 360) / 30) + 1 &nbsp; &nbsp; &nbsp; &nbsp; var day = Math.floor((index % 360) % 30) if (day === 0) { day = 30 month = month - 1 } &nbsp; &nbsp; &nbsp; &nbsp; var dateArray = [day,month,year] &nbsp; &nbsp; &nbsp; &nbsp; return dateArray; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; spliceEventIn: function (location,name,index,gm){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var allEvents = state.Calendar.events &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allEvents.splice(location,0,[name,index,gm]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.events = allEvents &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; addCalendarEvent: function (name,day,month,year,gm) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var firstEvent = state.Calendar.events[0] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var endEvents = state.Calendar.events.length - 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastEvent = state.Calendar.events[endEvents] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newEventIndex = Calendar.calcDateIndex (day,month,year) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (state.Calendar.events[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newEventIndex &lt; firstEvent[1]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (0,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (newEventIndex &gt; lastEvent[1]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (state.Calendar.events.length,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newEventIndex &lt;= thisEventIndex) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.spliceEventIn (i,name,newEventIndex,gm); &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; &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; Calendar.spliceEventIn (0,name,newEventIndex,gm); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; removeCalendarEvent: function (name) { &nbsp; &nbsp; &nbsp; &nbsp; if (state.Calendar.events[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (name && name.toUpperCase() == thisEvent[0].toUpperCase()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state.Calendar.events.splice(i,1) &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; getEvents: function (direction,limit) { &nbsp; &nbsp; &nbsp; &nbsp; var currentIndex = Calendar.calcDateIndex (state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year) &nbsp; &nbsp; &nbsp; &nbsp; var findEdgeIndex = function (direction,limit,start) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return start - limit; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (direction == 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return start + limit; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var allRecordedEvents = [] &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var returnEvents = function (start,end) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; state.Calendar.events.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEvent = state.Calendar.events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (thisEventIndex &gt;= start && thisEventIndex &lt;= end ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allRecordedEvents.splice(state.Calendar.events.length,0,thisEvent) &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; var removeGMEvents = function (array) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var events = array &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; array.length; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thisEvent = events[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (thisEvent[2] === null){ &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; if (thisEvent[2] && thisEvent[2].toUpperCase() == "GM") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; events.splice(i,1); &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; return events; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == 0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex,currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; } else if (limit) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex - limit, currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex, currentIndex + limit); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (0,currentIndex); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsLength = state.Calendar.events.length &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastEvent = state.Calendar.events[eventsLength - 1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; returnEvents (currentIndex, lastEvent[1]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (playerGM == false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allRecordedEvents = removeGMEvents (allRecordedEvents) &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //DO NOTHING &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return allRecordedEvents &nbsp; &nbsp; }, &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; convertDateArrayToObject: function (array) { &nbsp; &nbsp; var newDateObject = {} &nbsp; &nbsp; newDateObject.day = array[0] &nbsp; &nbsp; newDateObject.month = array[1] &nbsp; &nbsp; newDateObject.year = array[2] &nbsp; &nbsp; return newDateObject; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; buildEventTable: function (direction,title,limit) { &nbsp; &nbsp; &nbsp; &nbsp; var targetEvents = Calendar.getEvents (direction,limit); &nbsp; &nbsp; &nbsp; &nbsp; if (targetEvents[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventTable = "&{template:default} {{name=" + title + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; targetEvents.length; i++){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = targetEvents[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var dateArray = Calendar.calcIndexToDate (thisEventIndex) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventString = Calendar._GetDateAsString (Calendar.convertDateArrayToObject (dateArray)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newTableEntry = "{{" + thisEvent[0] + "=" + thisEventString + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventTable = eventTable + newTableEntry &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventTable; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "NO EVENTS FOUND FOR SPECIFIED RANGE"; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; HandleInput: function(tokens){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var options = Calendar._GetOptionsFromTokens(tokens); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tokens=_.filter(tokens, function(tok){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null == tok.match(/^--/); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; var cmd = tokens[0] || 'month'; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var concatenateEventName = function (start) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var fullEventName = '' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lastWord = tokens.length-1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = start; i &lt; tokens.length - 1; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newNamePortion = tokens[i] + " " &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName + newNamePortion &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullEventName = fullEventName + tokens[lastWord] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return fullEventName; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sendMsg = function (message) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", "/w " + senderID[0] + " " + message) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsToday = function () { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var events = Calendar.buildEventTable (0,"Today's Events") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (events === "NO EVENTS FOUND FOR SPECIFIED RANGE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "No Events Today"; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return events; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var returnEventRange = function (direction, title) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[2]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = Calendar.buildEventTable(direction, title + " (" + tokens[2] + " days)",parseInt(tokens[2])) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventsMessage; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = Calendar.buildEventTable(direction,"All " +title) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventsMessage; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (cmd) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'month':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowMonth(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'year': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowYear(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'today': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; &nbsp; case 'next': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var days=tokens[1] || 1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.AdvanceDays(days); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; case 'prev': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var days=tokens[1] || 1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.RemoveDays(days); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.ShowDate(state.Calendar.now,options); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', eventsMessage) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var gmEventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (eventsMessage != gmEventsMessage) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ('', "/w gm " + gmEventsMessage) &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; &nbsp; case 'AddEvent': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[1] && tokens[1].toUpperCase() === "TODAY" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[2].toUpperCase() === "GM") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(3),state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year,"GM"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your GM event has been added TODAY"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(3),state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your PUBLIC event has been added TODAY"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (isNaN(parseInt(tokens[1])) === false && isNaN(parseInt(tokens[2])) === false && isNaN(parseInt(tokens[3])) === false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tokens[4] && tokens[4].toUpperCase() === "GM" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(4),parseInt(tokens[1]),parseInt(tokens[2]),parseInt(tokens[3]),"GM"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your GM event has been added at the SPECIFIED DATE") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.addCalendarEvent (concatenateEventName(4),parseInt(tokens[1]),parseInt(tokens[2]),parseInt(tokens[3])); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("Your PUBLIC event has been added at the SPECIFIED DATE") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (isNaN(parseInt(tokens[1])) === false && isNaN(parseInt(tokens[2])) === true) { var currentIndex = Calendar.calcDateIndex (state.Calendar.now.day,state.Calendar.now.month,state.Calendar.now.year); var newIndex = currentIndex + parseInt(tokens[1]) var newDate = Calendar.calcIndexToDate (newIndex) if (tokens[2].toUpperCase === "GM") { Calendar.addCalendarEvent(concatenateEventName(3),newDate[0],newDate[1],newDate[2],"GM"); sendMsg ("Your GM event has been added " + tokens[1] + " days from today"); } else { Calendar.addCalendarEvent(concatenateEventName(2),newDate[0],newDate[1],newDate[2]); sendMsg ("Your PUBLIC event has been added " + tokens[1] + " days from today"); }; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'RemoveEvent': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; targetName = concatenateEventName(1) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.removeCalendarEvent (targetName); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendMsg ("You have removed the event named -- " + targetName) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'GetEvents': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var targetFrame = tokens[1] && tokens[1].toUpperCase(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (targetFrame === "PAST" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + returnEventRange (-1,"Past Events")); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "PRESENT") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + eventsMessage); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "FUTURE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents","/w " + senderID[0] + returnEventRange (1,"Upcoming Events")); &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; case 'DisplayEvents': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var targetFrame = tokens[1].toUpperCase() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (targetFrame === "PAST" ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", returnEventRange (-1,"Past Events")); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "PRESENT") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventsMessage = eventsToday () &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", eventsMessage); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (targetFrame === "FUTURE") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat ("CalendarEvents", returnEventRange (1,"Upcoming Events")); &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; &nbsp; &nbsp; RegisterEventHandlers: function() { &nbsp; &nbsp; &nbsp; &nbsp; on("chat:message", function (msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Exit if not an api command */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (msg.type != "api") return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* clean up message bits. */ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.who = msg.who.replace(" (GM)", ""); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.content = msg.content.replace("(GM) ", ""); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var tokenized = msg.content.split(" "); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var command = tokenized[0]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sendingPlayerID = msg.playerid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; senderID = msg.who.split(" ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerGM = playerIsGM(sendingPlayerID); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(command) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "!cal": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "!calendar": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Calendar.HandleInput(_.rest(tokenized)); &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; &nbsp; &nbsp; &nbsp; case "!s": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '/direct &lt;div style="border: 2px solid red;"&gt;&lt;b&gt;state.Calendar&lt;/b&gt;&lt;br&gt;&lt;pre&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +JSON.stringify(state.Calendar,undefined," &nbsp; ").replace(/\n/g,'&lt;br&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +"&lt;/pre&gt;&lt;/div&gt;" ); &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; }; on("ready",function(){ &nbsp; &nbsp; Calendar.CheckInstall();&nbsp; &nbsp; &nbsp; Calendar.RegisterEventHandlers(); });
1451712383
The Aaron
Pro
API Scripter
It's because of this function: &nbsp; &nbsp; _GetYearForDate: function(d,options){ &nbsp; &nbsp; &nbsp; &nbsp; var opt=_.defaults((options||{}),{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showLunarPhases: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showYear: false, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showMonthNumber: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; var s=state.Calendar.setting; &nbsp; &nbsp; &nbsp; &nbsp; var yday=_.clone(d); &nbsp; &nbsp; &nbsp; &nbsp; yday.day=1; &nbsp; &nbsp; &nbsp; &nbsp; yday.month=1; &nbsp; &nbsp; &nbsp; &nbsp; var months=''; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3],function(r){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each([1,2,3],function(c){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;div style="float:left;padding: 2px 2px;"&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+=Calendar._GetMonthForDate(yday,opt); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yday.month++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;div style="background-color: #DEB887; border: 3px solid #8B4513; padding: 3px 3px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="border-bottom: 2px solid #8B0000;margin: 3px 3px;font-weight: bold; font-size: 130%; text-align: center;"&gt;'+s.yearPrefix+d.year+'&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; +months &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;/div&gt;'; &nbsp; &nbsp; }, You took the ,4 out. &nbsp;Honestly, you could simplify this considerably. &nbsp;This was the first Roll20 script I ever wrote, 2 years ago. &nbsp;It is before I'd read Javascript: The Good Parts by Douglas Crockford and is quite shamefully ugly in design and style. Try it like this: &nbsp; &nbsp; &nbsp; &nbsp; _.each(_.range(state.Calendar.setting.monthsOfTheYear.length),function(){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; months+='&lt;div style="float:left;padding: 2px 2px;"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +Calendar._GetMonthForDate(yday,opt) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/div&gt;'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yday.month++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});
Ugly or not it works beautifully :)&nbsp; If my defense I thought that 4 referred to the number of weeks in a month. lol I got a copy of Javascript: The Good Parts by Douglas Crockford , I'm sure your commission check should be arriving shortly ;)
1451757807
The Aaron
Pro
API Scripter
Bwahahahaha. It would be funny to know how many copies he's sold because of my mentioning it. :)
1451906383
Ziechael
Forum Champion
Sheet Author
API Scripter
Now if you could just add variable weather by season I'd be a happy man indeed... or i could get off my lazy behind and add events to the current calendar/weather script i use i suppose.... nah!
1452088143
Ziechael
Forum Champion
Sheet Author
API Scripter
Just playing around with this and I love the event additions, i've decided to take a different tack and add the weather from the other script to this one rather than the other way around (expect a message soon Aaron ;) ). One question, is there a way to add repeating events currently (My players have a stronghold which generates income every 10 day (week) and it would be handy to be able to set that as a recurring event with one command). Thanks for all the work you guys put into these scripts :)
1452088961
The Aaron
Pro
API Scripter
There isn't a repeating events method yet. &nbsp;I'd suggest creating a macro for setting repeating events and a Roll Query to prompt you for the date, then just run it and flesh out the next decade or so. &nbsp;=D
1452089177
Ziechael
Forum Champion
Sheet Author
API Scripter
That was going to be my workaround but since implementing my weather mashup will likely take a while (depending on your availability, patience and my ability to learn anything at all) i figured i'd put it out there in case some quick code would solve it ;)
1452188818

Edited 1452189027
Ziechael I actually use the Randomizer script for weather, works great just made a macro called day advance that runs this script and the randomizer Randomizer this is what I get when I use it...
1452245229
Ziechael
Forum Champion
Sheet Author
API Scripter
I ended up doing something similar, I stripped out all of the references to days, dates and new days in my calendar/weather script and made sure it was starting on the same day as this awesome event tracking version of Aaron's Calendar. Then I set up a macro that runs both the !cal next and !day commands from both scripts which gives me this for each new day: I also coaxed Aaron (under the pretence of trying to learn something) into helping me only show the event dates when running a range rather than showing them for 'todays' events since the date is already there: By changing one line in the table builder you too can get this wonderful effect (thanks Aaron!): buildEventTable: function (direction,title,limit) { &nbsp; &nbsp; &nbsp; &nbsp; var targetEvents = Calendar.getEvents (direction,limit); &nbsp; &nbsp; &nbsp; &nbsp; if (targetEvents[0]) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var eventTable = "&{template:default} {{name=" + title + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i &lt; targetEvents.length; i++){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEvent = targetEvents[i] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventIndex = thisEvent[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var dateArray = Calendar.calcIndexToDate (thisEventIndex) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var thisEventString = ( limit ? Calendar._GetDateAsString (Calendar.convertDateArrayToObject (dateArray)) : ''); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newTableEntry = "{{" + thisEvent[0] + "=" + thisEventString + "}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventTable = eventTable + newTableEntry &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return eventTable; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "NO EVENTS FOUND FOR SPECIFIED RANGE"; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, But still retain the dates in the range driven output:
1452466509

Edited 1452466788
Hello, I've been trying to get the GM events to work, but they always keep posting as public events. I notice someone mentioned it earlier. I'm actually using the Faerun calendar variant posted afterwards. What exactly was the fix needed to get it creating properly? I think using a separate function for adding GM events would be cleaner than having to parse it, who knows, the game might have a GM Day event within its calendar! Edit: Well, seems the only part that's not working its the X amount of days in the future version of the GM event. I can do specified date and today.
Big thanks to everyone involved. I'd been using The Aaron's calendar for a while, and adding events definitely moved it from a 9/10 script to an 11/10.
Hello and apologies for not responding to fixes to this script in such a long time, life has been hectic but I finally have some free time. I've posed an update to the script fixing the issue reported by Gozer and implementing the change recommended by Jose P. The OP has been updated to reflect these changes and code is in the GitHub link. These changes should work fine if you are running the old script. But if you have written macros to do the commands for you, you will need to update them. Post back if there are still issues or anything I can do to improve the script for any of you.
1455998366
The Aaron
Pro
API Scripter
Cool!
I'm trying to install this script, but I seem to be running into an issue. I didn't change anything but the month and day names, and didn't alter any of the special characters that aren't letters outside of those names. But it either gives me this error Spinning up new sandbox... Error downloading scripts (probably no scripts exist for campaign.) or this error Spinning up new sandbox... Unexpected token : And I'm not sure what to do.
1456168315
The Aaron
Pro
API Scripter
That first one looks like the API error that was happening over the weekend (I got it myself on sunday), see the Stickie at the top of the API forum. The second looks more like a code issue. &nbsp;You might want to disable your current copy and make sure the sandbox starts up, then copy it fresh from the github link and see if the issue goes away.