From 8320156f42679b47734a80fd51ce65c0f08d8a3e Mon Sep 17 00:00:00 2001 From: nicholas_pellizer Date: Thu, 23 Apr 2015 11:33:44 +0200 Subject: [PATCH] Hyper mode and LightsOff is now stored in the State --- script/engine.js | 155 ++++++++++++++++++++++------------------ script/state_manager.js | 131 ++++++++++++++++----------------- 2 files changed, 151 insertions(+), 135 deletions(-) diff --git a/script/engine.js b/script/engine.js index 1766704..3c1c776 100644 --- a/script/engine.js +++ b/script/engine.js @@ -1,15 +1,15 @@ (function() { var Engine = window.Engine = { - + SITE_URL: encodeURIComponent("http://adarkroom.doublespeakgames.com"), VERSION: 1.3, MAX_STORE: 99999999999999, SAVE_DISPLAY: 30 * 1000, GAME_OVER: false, - + //object event types topics: {}, - + Perks: { 'boxer': { name: _('boxer'), @@ -69,7 +69,7 @@ notify: _('learned to make the most of food') } }, - + options: { state: null, debug: false, @@ -77,7 +77,7 @@ dropbox: false, doubleTime: false }, - + init: function(options) { this.options = $.extend( this.options, @@ -85,31 +85,31 @@ ); this._debug = this.options.debug; this._log = this.options.log; - + // Check for HTML5 support if(!Engine.browserValid()) { window.location = 'browserWarning.html'; } - + // Check for mobile if(Engine.isMobile()) { window.location = 'mobileWarning.html'; } - + Engine.disableSelection(); - + if(this.options.state != null) { window.State = this.options.state; } else { Engine.loadGame(); } - + $('
').attr('id', 'locationSlider').appendTo('#main'); var menu = $('
') .addClass('menu') .appendTo('body'); - + if(typeof langs != 'undefined'){ var customSelect = $('') .addClass('customSelect') @@ -123,7 +123,7 @@ $('
  • ') .text("language.") .appendTo(optionsList); - + $.each(langs, function(name,display){ $('
  • ') .text(display) @@ -140,15 +140,9 @@ .appendTo(menu); $('') - .addClass('menuBtn') + .addClass('hyper menuBtn') .text(_('hyper.')) - .click(function(){ - Engine.options.doubleTime = !Engine.options.doubleTime; - if(Engine.options.doubleTime) - $(this).text(_('classic.')); - else - $(this).text(_('hyper.')); - }) + .click(Engine.triggerHyperMode) .appendTo(menu); $('') @@ -156,7 +150,7 @@ .text(_('restart.')) .click(Engine.confirmDelete) .appendTo(menu); - + $('') .addClass('menuBtn') .text(_('share.')) @@ -178,7 +172,7 @@ .click(Engine.Dropbox.startDropbox) .appendTo(menu); } - + $('') .addClass('menuBtn') .text(_('app store.')) @@ -190,7 +184,7 @@ .text(_('github.')) .click(function() { window.open('https://github.com/doublespeakgames/adarkroom'); }) .appendTo(menu); - + // Register keypress handlers $('body').off('keydown').keydown(Engine.keyDown); $('body').off('keyup').keyup(Engine.keyUp); @@ -201,7 +195,7 @@ swipeElement.on('swiperight', Engine.swipeRight); swipeElement.on('swipeup', Engine.swipeUp); swipeElement.on('swipedown', Engine.swipeDown); - + // subscribe to stateUpdates $.Dispatch('stateUpdate').subscribe(Engine.handleStateUpdates); @@ -209,7 +203,7 @@ Notifications.init(); Events.init(); Room.init(); - + if(typeof $SM.get('stores.wood') != 'undefined') { Outside.init(); } @@ -219,20 +213,28 @@ if($SM.get('features.location.spaceShip')) { Ship.init(); } - + + if($SM.get('config.lightsOff', true)){ + Engine.turnLightsOff(); + } + + if($SM.get('config.hyperMode', true)){ + Engine.triggerHyperMode(); + } + Engine.saveLanguage(); Engine.travelTo(Room); - + }, - + browserValid: function() { return ( location.search.indexOf( 'ignorebrowser=true' ) >= 0 || ( typeof Storage != 'undefined' && !oldIE ) ); }, - + isMobile: function() { return ( location.search.indexOf( 'ignorebrowser=true' ) < 0 && /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test( navigator.userAgent ) ); }, - + saveGame: function() { if(typeof Storage != 'undefined' && localStorage) { if(Engine._saveTimer != null) { @@ -245,7 +247,7 @@ localStorage.gameState = JSON.stringify(State); } }, - + loadGame: function() { try { var savedState = JSON.parse(localStorage.gameState); @@ -260,7 +262,7 @@ Engine.event('progress', 'new game'); } }, - + exportImport: function() { Events.startEvent({ title: _('Export / Import'), @@ -370,7 +372,7 @@ ga('send', 'event', cat, act); } }, - + confirmDelete: function() { Events.startEvent({ title: _('Restart?'), @@ -392,7 +394,7 @@ } }); }, - + deleteSave: function(noReload) { if(typeof Storage != 'undefined' && localStorage) { var prestige = Prestige.get(); @@ -404,7 +406,7 @@ location.reload(); } }, - + share: function() { Events.startEvent({ title: _('Share'), @@ -470,22 +472,35 @@ } return false; }, - + turnLightsOff: function() { var darkCss = Engine.findStylesheet('darkenLights'); if (darkCss == null) { $('head').append(''); $('.lightsOff').text(_('lights on.')); + $SM.set('config.lightsOff', true, true); } else if (darkCss.disabled) { darkCss.disabled = false; $('.lightsOff').text(_('lights on.')); + $SM.set('config.lightsOff', true,true); } else { $("#darkenLights").attr("disabled", "disabled"); darkCss.disabled = true; $('.lightsOff').text(_('lights off.')); + $SM.set('config.lightsOff', false, true); } }, - + + triggerHyperMode: function(){ + Engine.options.doubleTime = !Engine.options.doubleTime; + if(Engine.options.doubleTime) + $('.hyper').text(_('classic.')); + else + $('.hyper').text(_('hyper.')); + + $SM.set('config.hyperMode', Engine.options.doubleTime, false); + }, + // Gets a guid getGuid: function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { @@ -493,9 +508,9 @@ return v.toString(16); }); }, - + activeModule: null, - + travelTo: function(module) { if(Engine.activeModule != module) { var currentIndex = Engine.activeModule ? $('.location').index(Engine.activeModule.panel) : 1; @@ -512,7 +527,7 @@ // FIXME Why does this work if there's an animation queue...? stores.animate({right: -(panelIndex * 700) + 'px'}, 300 * diff); } - + Engine.activeModule = module; module.onArrival(diff); @@ -530,7 +545,7 @@ } Notifications.printQueue(module); - + } }, @@ -557,33 +572,33 @@ top: top_container.height() + 26 + 'px' }, { - queue: false, + queue: false, duration: 300 * transition_diff }); } }, - + log: function(msg) { if(this._log) { console.log(msg); } }, - + updateSlider: function() { var slider = $('#locationSlider'); slider.width((slider.children().length * 700) + 'px'); }, - + updateOuterSlider: function() { var slider = $('#outerSlider'); slider.width((slider.children().length * 700) + 'px'); }, - + getIncomeMsg: function(num, delay) { return _("{0} per {1}s", (num > 0 ? "+" : "") + num, delay); //return (num > 0 ? "+" : "") + num + " per " + delay + "s"; }, - + keyDown: function(e) { e = e || window.event; if(!Engine.keyPressed && !Engine.keyLock) { @@ -594,7 +609,7 @@ } return jQuery.inArray(e.keycode, [37,38,39,40]) < 0; }, - + keyUp: function(e) { Engine.pressed = false; if(Engine.activeModule.keyUp) { @@ -645,7 +660,7 @@ break; } } - + return false; }, @@ -682,15 +697,15 @@ document.onselectstart = eventPassthrough; document.onmousedown = eventPassthrough; }, - + autoSelect: function(selector) { $(selector).focus().select(); }, - + handleStateUpdates: function(e){ - + }, - + switchLanguage: function(dom){ var lang = $(dom).data("language"); if(document.location.href.search(/[\?\&]lang=[a-z_]+/) != -1){ @@ -699,9 +714,9 @@ document.location.href = document.location.href + ( (document.location.href.search(/\?/) != -1 )?"&":"?") + "lang="+lang; } }, - + saveLanguage: function(){ - var lang = decodeURIComponent((new RegExp('[?|&]lang=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null; + var lang = decodeURIComponent((new RegExp('[?|&]lang=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null; if(lang && typeof Storage != 'undefined' && localStorage) { localStorage.lang = lang; } @@ -732,32 +747,32 @@ function inView(dir, elem){ - var scTop = $('#main').offset().top; - var scBot = scTop + $('#main').height(); + var scTop = $('#main').offset().top; + var scBot = scTop + $('#main').height(); - var elTop = elem.offset().top; - var elBot = elTop + elem.height(); + var elTop = elem.offset().top; + var elBot = elTop + elem.height(); - if( dir == 'up' ){ - // STOP MOVING IF BOTTOM OF ELEMENT IS VISIBLE IN SCREEN - return ( elBot < scBot ); - }else if( dir == 'down' ){ - return ( elTop > scTop ); - }else{ - return ( ( elBot <= scBot ) && ( elTop >= scTop ) ); - } + if( dir == 'up' ){ + // STOP MOVING IF BOTTOM OF ELEMENT IS VISIBLE IN SCREEN + return ( elBot < scBot ); + }else if( dir == 'down' ){ + return ( elTop > scTop ); + }else{ + return ( ( elBot <= scBot ) && ( elTop >= scTop ) ); + } } function scrollByX(elem, x){ - var elTop = parseInt( elem.css('top'), 10 ); - elem.css( 'top', ( elTop + x ) + "px" ); + var elTop = parseInt( elem.css('top'), 10 ); + elem.css( 'top', ( elTop + x ) + "px" ); } -//create jQuery Callbacks() to handle object events +//create jQuery Callbacks() to handle object events $.Dispatch = function( id ) { var callbacks, topic = id && Engine.topics[ id ]; if ( !topic ) { diff --git a/script/state_manager.js b/script/state_manager.js index ad807ed..c42b5c5 100644 --- a/script/state_manager.js +++ b/script/state_manager.js @@ -1,52 +1,53 @@ /* * Module for handling States - * + * * All states should be get and set through the StateManager ($SM). - * + * * The manager is intended to handle all needed checks and error catching. * This includes creating the parents of layered/deep states so undefined states * do not need to be tested for and created beforehand. - * + * * When a state is changed, an update event is sent out containing the name of the state * changed or in the case of multiple changes (.setM, .addM) the parent class changed. * Event: type: 'stateUpdate', stateName: - * + * * Original file created by: Michael Galusha */ var StateManager = { - + MAX_STORE: 99999999999999, - + options: {}, - + init: function(options) { this.options = $.extend( this.options, options ); - + //create categories var cats = [ - 'features', //big features like buildings, location availability, unlocks, etc - 'stores', //little stuff, items, weapons, etc - 'character', //this is for player's character stats such as perks + 'features', //big features like buildings, location availability, unlocks, etc + 'stores', //little stuff, items, weapons, etc + 'character', //this is for player's character stats such as perks 'income', 'timers', - 'game', //mostly location related: fire temp, workers, population, world map, etc - 'playStats', //anything play related: play time, loads, etc - 'previous', // prestige, score, trophies (in future), achievements (again, not yet), etc - 'outfit' // used to temporarily store the items to be taken on the path + 'game', //mostly location related: fire temp, workers, population, world map, etc + 'playStats', //anything play related: play time, loads, etc + 'previous', // prestige, score, trophies (in future), achievements (again, not yet), etc + 'outfit', // used to temporarily store the items to be taken on the path + 'config' ]; - + for(var which in cats) { - if(!$SM.get(cats[which])) $SM.set(cats[which], {}); + if(!$SM.get(cats[which])) $SM.set(cats[which], {}); } - + //subscribe to stateUpdates $.Dispatch('stateUpdate').subscribe($SM.handleStateUpdates); }, - + //create all parents and then set state createState: function(stateName, value) { var words = stateName.split(/[.\[\]'"]+/); @@ -67,51 +68,51 @@ var StateManager = { obj[words[i]] = value; return obj; }, - + //set single state //if noEvent is true, the update event won't trigger, useful for setting multiple states first set: function(stateName, value, noEvent) { var fullPath = $SM.buildPath(stateName); - + //make sure the value isn't over the engine maximum if(typeof value == 'number' && value > $SM.MAX_STORE) value = $SM.MAX_STORE; - + try{ eval('('+fullPath+') = value'); } catch (e) { //parent doesn't exist, so make parent $SM.createState(stateName, value); } - + //stores values can not be negative if(stateName.indexOf('stores') === 0 && $SM.get(stateName, true) < 0) { eval('('+fullPath+') = 0'); Engine.log('WARNING: state:' + stateName + ' can not be a negative value. Set to 0 instead.'); } - + if(!noEvent) { Engine.saveGame(); $SM.fireUpdate(stateName); - } + } }, - + //sets a list of states setM: function(parentName, list, noEvent) { $SM.buildPath(parentName); - + //make sure the state exists to avoid errors, if($SM.get(parentName) === undefined) $SM.set(parentName, {}, true); - + for(var k in list){ $SM.set(parentName+'["'+k+'"]', list[k], true); } - + if(!noEvent) { Engine.saveGame(); $SM.fireUpdate(parentName); } }, - + //shortcut for altering number values, return 1 if state wasn't a number add: function(stateName, value, noEvent) { var err = 0; @@ -119,7 +120,7 @@ var StateManager = { //could also add in a true = 1 thing, to have something go from existing (true) //to be a count, but that might be unwanted behavior (add with loose eval probably will happen anyways) var old = $SM.get(stateName, true); - + //check for NaN (old != old) and non number values if(old != old){ Engine.log('WARNING: '+stateName+' was corrupted (NaN). Resetting to 0.'); @@ -131,52 +132,52 @@ var StateManager = { } else { $SM.set(stateName, old + value, noEvent); //setState handles event and save } - + return err; }, - + //alters multiple number values, return number of fails addM: function(parentName, list, noEvent) { var err = 0; - + //make sure the parent exists to avoid errors if($SM.get(parentName) === undefined) $SM.set(parentName, {}, true); - + for(var k in list){ if($SM.add(parentName+'["'+k+'"]', list[k], true)) err++; } - + if(!noEvent) { Engine.saveGame(); $SM.fireUpdate(parentName); } return err; }, - + //return state, undefined or 0 get: function(stateName, requestZero) { var whichState = null; var fullPath = $SM.buildPath(stateName); - + //catch errors if parent of state doesn't exist try{ eval('whichState = ('+fullPath+')'); } catch (e) { whichState = undefined; } - + //prevents repeated if undefined, null, false or {}, then x = 0 situations if((!whichState || whichState == {}) && requestZero) return 0; else return whichState; }, - + //mainly for local copy use, add(M) can fail so we can't shortcut them //since set does not fail, we know state exists and can simply return the object setget: function(stateName, value, noEvent){ $SM.set(stateName, value, noEvent); return eval('('+$SM.buildPath(stateName)+')'); }, - + remove: function(stateName, noEvent) { var whichState = $SM.buildPath(stateName); try{ @@ -190,21 +191,21 @@ var StateManager = { $SM.fireUpdate(stateName); } }, - + //creates full reference from input //hopefully this won't ever need to be more complicated buildPath: function(input){ var dot = (input.charAt(0) == '[')? '' : '.'; //if it starts with [foo] no dot to join return 'State' + dot + input; }, - + fireUpdate: function(stateName, save){ var category = $SM.getCategory(stateName); if(stateName == undefined) stateName = category = 'all'; //best if this doesn't happen as it will trigger more stuff $.Dispatch('stateUpdate').publish({'category': category, 'stateName':stateName}); if(save) Engine.saveGame(); }, - + getCategory: function(stateName){ var firstOB = stateName.indexOf('['); var firstDot = stateName.indexOf('.'); @@ -220,7 +221,7 @@ var StateManager = { return stateName.substr(0,cutoff); } }, - + //Use this function to make old save games compatible with new version updateOldState: function(){ var version = $SM.get('version'); @@ -299,7 +300,7 @@ var StateManager = { $SM.set('version', 1.3); } }, - + /****************************************************************** * Start of specific state functions ******************************************************************/ @@ -308,11 +309,11 @@ var StateManager = { $SM.set('character.perks["'+name+'"]', true); Notifications.notify(null, Engine.Perks[name].notify); }, - + hasPerk: function(name) { return $SM.get('character.perks["'+name+'"]'); }, - + //INCOME setIncome: function(source, options) { var existing = $SM.get('income["'+source+'"]'); @@ -321,7 +322,7 @@ var StateManager = { } $SM.set('income["'+source+'"]', options); }, - + getIncome: function(source) { var existing = $SM.get('income["'+source+'"]'); if(typeof existing != 'undefined') { @@ -329,7 +330,7 @@ var StateManager = { } return {}; }, - + collectIncome: function() { var changed = false; if(typeof $SM.get('income') != 'undefined' && Engine.activeModule != Space) { @@ -340,21 +341,21 @@ var StateManager = { income.timeLeft = 0; } income.timeLeft--; - + if(income.timeLeft <= 0) { Engine.log('collection income from ' + source); - if(source == 'thieves') $SM.addStolen(income.stores); + if(source == 'thieves') $SM.addStolen(income.stores); var cost = income.stores; var ok = true; if (source != 'thieves') { - for (var k in cost) { - var have = $SM.get('stores["' + k + '"]', true); - if (have + cost[k] < 0) { - ok = false; - break; - } - } + for (var k in cost) { + var have = $SM.get('stores["' + k + '"]', true); + if (have + cost[k] < 0) { + ok = false; + break; + } + } } if(ok){ @@ -372,7 +373,7 @@ var StateManager = { } Engine._incomeTimeout = setTimeout($SM.collectIncome, 1000); }, - + //Thieves addStolen: function(stores) { for(var k in stores) { @@ -386,7 +387,7 @@ var StateManager = { } } }, - + startThieves: function() { $SM.set('game.thieves', 1); $SM.setIncome('thieves', { @@ -398,7 +399,7 @@ var StateManager = { } }); }, - + //Misc num: function(name, craftable) { switch(craftable.type) { @@ -411,10 +412,10 @@ var StateManager = { return $SM.get('game.buildings["'+name+'"]', true); } }, - + handleStateUpdates: function(e){ - - } + + } }; //alias