As I continue down the path of trying to create a real-time, event-driven story in SugarCube, I find myself encountering some interesting challenges. The latest of which is getting object prototypes and anonymous functions to play nicely with story variables.
I think I've fixed the problem by following advice given by @TheMadExile in the thread Keeping complex JS objects in variables?, but I'm not sure I've fixed it "correctly".
If any of you have experience with JSON serialisation, could you please take a look over the following and let me know if there's a better way?
Events:
Creates a future-dated event, to be fired when $game_clock >= Event.time
Event Logs:
Creates a log, a historical record of past events for the user to see.
Example Usage:
This creates a hidden Event that will be not be displayed in the 'Upcoming Events' section of the UI. When the event fires, it will immediately stop any time acceleration, and add this event's EventLog to the list of historical logs.
It will also display a SugarCube dialog displaying the same log information. When the user closes this dialog, they will be taken to the passage 'Event Intro Alarm'.
I think I've fixed the problem by following advice given by @TheMadExile in the thread Keeping complex JS objects in variables?, but I'm not sure I've fixed it "correctly".
If any of you have experience with JSON serialisation, could you please take a look over the following and let me know if there's a better way?
Events:
Creates a future-dated event, to be fired when $game_clock >= Event.time
/* setup.Event(time, [title[, passage[, openFn[, closeFn[, bHidden[, bPopUp[, log]]]]]]]) time: When the event will occur, the only mandatory field. title: Name of event to be displayed on UI. passage: Passage to be displayed if user clicks on the event's title in UI (title will only be a link if passage is not undefined). openFn: Function to be fired immediately after the event is fired. closeFn: Function to be fired after the user closes the pop-up dialog, only works if bPopUp is true and log is not undefined. bHidden: Whether or not the event should be displayed on the UI. bPopUp: Whether or the event's log should pop-up on screen as a SugarCube dialog, only works if log is not undefined. log: Historical log entry to be created after the event is fired. */ setup.Event = function(time, title, passage, openFn, closeFn, bHidden, bPopUp, log) { if (!(time instanceof Date)) { time = new Date(time); } if (openFn instanceof Array) { openFn = eval(openFn[1]); } if (closeFn instanceof Array) { closeFn = eval(closeFn[1]); } if (log instanceof Array) { log = eval(log[1][0]); } this.time = time; this.title = title; this.passage = passage; this.openFn = openFn; this.closeFn = closeFn; this.bHidden = bHidden; this.bPopUp = bPopUp; this.log = log; }; setup.Event.prototype = { toJSON: function () { var logStr, returnFn; if (this.log) { /* log is an instance of setup.EventLog, see below */ logStr = this.log.toJSON(); } returnFn = 'new setup.Event('; returnFn += JSON.stringify(this.time.getTime()) +','; returnFn += JSON.stringify(this.title) +','; returnFn += JSON.stringify(this.passage) +','; returnFn += JSON.stringify(this.openFn) +','; returnFn += JSON.stringify(this.closeFn) +','; returnFn += JSON.stringify(this.bHidden) +','; returnFn += JSON.stringify(this.bPopUp) +','; returnFn += JSON.stringify(logStr) +')'; return JSON.reviveWrapper(returnFn); } };
Event Logs:
Creates a log, a historical record of past events for the user to see.
/* setup.EventLog(time, logSev, logType, logMessage[, learnid[, learnmsg[, read]]]) time: When the event occured. logSev: Log's severity, for filtering purposes. logType: Log's type, for filtering purposes. logMessage: Main body text of the log message. learnid: What $player_knowledge is unlocked the first time the user reads this log. learnmsg: Additional text to display the first time this $player_knowledge is found. read: A boolean to track if the user has read this log. */ setup.EventLog = function(time, logSev, logType, logMessage, learnid, learnmsg, read) { if (!(time instanceof Date)) { time = new Date(time); } this.time = time; this.severity = logSev; this.type = logType; this.message = logMessage; this.learnid = learnid; this.learnmsg = learnmsg; this.read = (read || false); }; setup.EventLog.prototype = { /* Prints the number of days since epoch */ getDays: function () { /* snip */ }, /* Prints the current time (24H). */ getTime: function () { /* snip */ }, /* creates a summary of this log for use in a <jQuery>.wiki() call */ format: function() { /* snip */ }, /* display a SugarCube dialog containing this log's information */ showDialog: function(closeFn) { /* snip */ }, toJSON: function () { var returnFn = 'new setup.EventLog('; returnFn += JSON.stringify(this.time.getTime()) +','; returnFn += JSON.stringify(this.severity) +','; returnFn += JSON.stringify(this.type) +','; returnFn += JSON.stringify(this.message) +','; returnFn += JSON.stringify(this.learnid) +','; returnFn += JSON.stringify(this.learnmsg) +','; returnFn += JSON.stringify(this.read) +')'; return JSON.reviveWrapper(returnFn); } };
Example Usage:
This creates a hidden Event that will be not be displayed in the 'Upcoming Events' section of the UI. When the event fires, it will immediately stop any time acceleration, and add this event's EventLog to the list of historical logs.
It will also display a SugarCube dialog displaying the same log information. When the user closes this dialog, they will be taken to the passage 'Event Intro Alarm'.
setup.cannedEvents = { /* snip */ introCollisionWarning: function() { var time = new Date('1901-04-07T07:20:00Z'); var event = new setup.Event( time, //time 'introCollisionWarning', //title null, //passage setup.timeSystem.clearTimeGoal, //openFn function() { Engine.play("Event Intro Alarm"); }, //closeFn true, //bHidden true //bPopUp ); var log = new setup.EventLog( time, //time 'High', //logSev 'Collision Warning', //logType "Sensor event SE-4562 has now been upgraded to a high severity, anomaly appears to be mass-bearing. Due to possibility of kinetic impact, ship status has been upgraded to high alert status.<br/><br/>''Warning:'' Current trajectory suggests ESSD Cetacea will now encounter anomaly in ''T-1 hour.'' Brace for severe warp turbulence." //logMessage ); setup.eventSystem.addEvent(event, log); }, /* snip */ }