diff --git a/index.html b/index.html index 78e532c..e1fe8cc 100644 --- a/index.html +++ b/index.html @@ -15,12 +15,15 @@ - + + + diff --git a/script/engine.js b/script/engine.js index 189454b..ef0d725 100644 --- a/script/engine.js +++ b/script/engine.js @@ -59,8 +59,8 @@ var Engine = { options: { state: null, - debug: false, - log: false + debug: true, + log: true }, init: function(options) { @@ -112,6 +112,7 @@ var Engine = { swipeElement.on('swipeup', Engine.swipeUp); swipeElement.on('swipedown', Engine.swipeDown); + $SM.init(); Notifications.init(); Events.init(); Room.init(); @@ -122,7 +123,7 @@ var Engine = { if(Engine.getStore('compass') > 0) { Path.init(); } - if(State.ship) { + if($SM.get('features.location.spaceShip')) { Ship.init(); } @@ -165,8 +166,6 @@ var Engine = { } catch(e) { State = { version: 1.2, - stores: {}, - perks: {} }; Engine.event('progress', 'new game'); } @@ -324,10 +323,10 @@ var Engine = { }, addPerk: function(name) { - if(!State.perks) { - State.perks = {}; + if(!$SM.get('character.perks')) { + $SM.set('character.perks', {}); } - State.perks[name] = true; + $SM.set('character.perks[\''+name+'\']', true); Notifications.notify(null, Engine.Perks[name].notify); if(Engine.activeModule == Path) { Path.updatePerks(); @@ -335,47 +334,37 @@ var Engine = { }, hasPerk: function(name) { - return typeof State.perks == 'object' && State.perks[name] == true; + return typeof $SM.get('character.perks') == 'object' && $SM.get('character.perks[\''+name+'\']') == true; }, setStore: function(name, number) { - if(typeof State.stores == 'undefined') { - State.stores = {}; - } - if(number > Engine.MAX_STORE) number = Engine.MAX_STORE; - State.stores[name] = number; + $SM.set('stores[\''+name+'\']', number); Room.updateStoresView(); Room.updateBuildButtons(); - if(State.outside) { + if($SM.get('features.location.outside')) { Outside.updateVillage(); } Engine.saveGame(); }, setStores: function(list) { - if(typeof State.stores == 'undefined') { - State.stores = {}; - } for(k in list) { - State.stores[k] = list[k] > Engine.MAX_STORE ? Engine.MAX_STORE : list[k]; + $SM.set('stores[\''+k+'\']', list[k]); } Room.updateStoresView(); Room.updateBuildButtons(); - if(State.outside) { + if($SM.get('features.location.outside')) { Outside.updateVillage(); } Engine.saveGame(); }, addStore: function(name, number) { - if(typeof State.stores == 'undefined') { - State.stores = {}; - } - var num = State.stores[name]; + var num = $SM.get('stores[\''+name+'\']'); if(typeof num != 'number' || isNaN(num) || num < 0) num = 0; num += number; if(num > Engine.MAX_STORE) num = Engine.MAX_STORE; - State.stores[name] = num; + $SM.set('stores[\''+name+'\']', num); Room.updateStoresView(); Room.updateBuildButtons(); Outside.updateVillage(); @@ -386,14 +375,10 @@ var Engine = { }, addStores: function(list, ignoreCosts) { - if(typeof State.stores == 'undefined') { - State.stores = {}; - } - // Make sure any income costs can be paid if(!ignoreCosts) { for(k in list) { - var num = State.stores[k]; + var num = $SM.get('stores[\''+k+'\']'); if(typeof num != 'number' || isNaN(num) || num < 0) num = 0; if(num + list[k] < 0) { return false; @@ -403,12 +388,12 @@ var Engine = { // Actually do the update for(k in list) { - var num = State.stores[k]; + var num = $SM.get('stores[\''+k+'\']'); if(typeof num != 'number') num = 0; num += list[k]; num = num < 0 ? 0 : num; num = num > Engine.MAX_STORE ? Engine.MAX_STORE : num; - State.stores[k] = num; + $SM.set('stores[\''+k+'\']', num); } Room.updateStoresView(); Room.updateBuildButtons(); @@ -421,32 +406,26 @@ var Engine = { }, storeAvailable: function(name) { - return typeof State.stores[name] == 'number'; + return typeof $SM.get('stores[\''+name+'\']') == 'number'; }, getStore: function(name) { - if(typeof State.stores == 'undefined' || typeof State.stores[name] == 'undefined' ) { + if(typeof $SM.get('stores[\''+name+'\']') == 'undefined') { return 0; } - return State.stores[name]; + return $SM.get('stores[\''+name+'\']'); }, setIncome: function(source, options) { - if(typeof State.income == 'undefined') { - State.income = {}; - } - var existing = State.income[source]; + var existing = $SM.get('income[\''+source+'\']'); if(typeof existing != 'undefined') { options.timeLeft = existing.timeLeft; } - State.income[source] = options; + $SM.set('income[\''+source+'\']', options); }, getIncome: function(source) { - if(typeof State.income == 'undefined') { - State.income = {}; - } - var existing = State.income[source]; + var existing = $SM.get('income[\''+source+'\']'); if(typeof existing != 'undefined') { return existing; } @@ -454,17 +433,15 @@ var Engine = { }, removeIncome: function(source) { - if(State.income) { - delete State.income[source]; - } + $SM.remove('income[\''+source+'\']'); Room.updateIncomeView(); }, collectIncome: function() { - if(typeof State.income != 'undefined' && Engine.activeModule != Space) { + if(typeof $SM.get('income') != 'undefined' && Engine.activeModule != Space) { var changed = false; - for(var source in State.income) { - var income = State.income[source]; + for(var source in $SM.get('income')) { + var income = $SM.get('income[\''+source+'\']'); if(typeof income.timeLeft != 'number') { income.timeLeft = 0; @@ -501,15 +478,15 @@ var Engine = { }, addStolen: function(stores) { - if(!State.stolen) State.stolen = {}; + if(!$SM.get('game.stolen')) $SM.set('game.stolen', {}); for(var k in stores) { - if(!State.stolen[k]) State.stolen[k] = 0; - State.stolen[k] -= stores[k]; + if(!$SM.get('game.stolen[\''+k+'\']')) $SM.set('game.stolen[\''+k+'\']', 0); + $SM.add('game.stolen[\''+k+'\']', stores[k] * -1); } }, startThieves: function() { - State.thieves = 1; + $SM.set('game.thieves', 1); Engine.setIncome('thieves', { delay: 10, stores: { diff --git a/script/events.js b/script/events.js index 6fee7b0..1148c2e 100644 --- a/script/events.js +++ b/script/events.js @@ -243,13 +243,13 @@ var Events = { var weaponName = btn.attr('id').substring(7).replace('-', ' '); var weapon = World.Weapons[weaponName]; if(weapon.type == 'unarmed') { - if(!State.punches) State.punches = 0; - State.punches++; - if(State.punches == 50 && !Engine.hasPerk('boxer')) { + if(!$SM.get('character.punches')) $SM.set('character.punches', 0); + $SM.add('character.punches', 1); + if($SM.get('character.punches') == 50 && !Engine.hasPerk('boxer')) { Engine.addPerk('boxer'); - } else if(State.punches == 150 && !Engine.hasPerk('martial artist')) { + } else if($SM.get('character.punches') == 150 && !Engine.hasPerk('martial artist')) { Engine.addPerk('martial artist'); - } else if(State.punches == 300 && !Engine.hasPerk('unarmed master')) { + } else if($SM.get('character.punches') == 300 && !Engine.hasPerk('unarmed master')) { Engine.addPerk('unarmed master'); } diff --git a/script/events/global.js b/script/events/global.js index 64f4021..7c623b0 100644 --- a/script/events/global.js +++ b/script/events/global.js @@ -5,7 +5,7 @@ Events.Global = [ { /* The Thief */ title: 'The Thief', isAvailable: function() { - return (Engine.activeModule == Room || Engine.activeModule == Outside) && State.thieves == 1; + return (Engine.activeModule == Room || Engine.activeModule == Outside) && $SM.get('game.thieves') == 1; }, scenes: { 'start': { @@ -32,9 +32,9 @@ Events.Global = [ 'the point is made. in the next few days, the missing supplies are returned.' ], onLoad: function() { - State.thieves = 2; + $SM.set('game.thieves', 2); Engine.removeIncome('thieves'); - Engine.addStores(State.stolen); + Engine.addStores($SM.get('game.stolen')); }, buttons: { 'leave': { @@ -49,7 +49,7 @@ Events.Global = [ "shares what he knows about sneaking before he goes." ], onLoad: function() { - State.thieves = 2; + $SM.set('game.thieves', 2); Engine.removeIncome('thieves'); Engine.addPerk('stealthy'); }, diff --git a/script/events/outside.js b/script/events/outside.js index aa1b7c7..109eb49 100644 --- a/script/events/outside.js +++ b/script/events/outside.js @@ -211,7 +211,7 @@ Events.Outside = [ { /* Soldier attack */ title: 'A Military Raid', isAvailable: function() { - return Engine.activeModule == Outside && Outside.getPopulation() > 0 && State.cityCleared; + return Engine.activeModule == Outside && Outside.getPopulation() > 0 && $SM.get('game.cityCleared');; }, scenes: { 'start': { diff --git a/script/events/room.js b/script/events/room.js index 246ff06..0350053 100644 --- a/script/events/room.js +++ b/script/events/room.js @@ -397,7 +397,7 @@ Events.Room = [ { /* The Scout -- Map Merchant */ title: 'The Scout', isAvailable: function() { - return Engine.activeModule == Room && typeof State.world == 'object'; + return Engine.activeModule == Room && $SM.get('features.location.world'); }, scenes: { 'start': { @@ -435,7 +435,7 @@ Events.Room = [ { /* The Wandering Master */ title: 'The Master', isAvailable: function() { - return Engine.activeModule == Room && typeof State.world == 'object'; + return Engine.activeModule == Room && $SM.get('features.location.world'); }, scenes: { 'start': { @@ -507,7 +507,7 @@ Events.Room = [ { /* The Sick Man */ title: 'The Sick Man', isAvailable: function() { - return Engine.activeModule == Room && typeof State.world == 'object'; + return Engine.activeModule == Room && $SM.get('features.location.world'); }, scenes: { 'start': { diff --git a/script/events/setpieces.js b/script/events/setpieces.js index 41cff66..9e00e9f 100644 --- a/script/events/setpieces.js +++ b/script/events/setpieces.js @@ -2244,7 +2244,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { bullets: { @@ -2278,7 +2278,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { torch: { @@ -2308,7 +2308,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { rifle: { @@ -2354,7 +2354,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { rifle: { @@ -2389,7 +2389,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { rifle: { @@ -2429,7 +2429,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'laser rifle': { @@ -2464,7 +2464,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'steel sword': { @@ -2499,7 +2499,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'steel sword': { @@ -2534,7 +2534,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'rifle': { @@ -2574,7 +2574,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'energy cell': { @@ -2613,7 +2613,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'energy cell': { @@ -2646,7 +2646,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'energy cell': { @@ -2695,7 +2695,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'steel sword': { @@ -2739,7 +2739,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'energy cell': { @@ -2782,7 +2782,7 @@ Events.Setpieces = { ], onLoad: function() { World.clearDungeon(); - State.cityCleared = true; + $SM.set('game.cityCleared', true); }, loot: { 'alien alloy': { diff --git a/script/outside.js b/script/outside.js index 23daebd..c86c002 100644 --- a/script/outside.js +++ b/script/outside.js @@ -135,12 +135,13 @@ var Outside = { .addClass('location') .appendTo('div#locationSlider'); - if(typeof State.outside == 'undefined') { - State.outside = { + if(typeof $SM.get('features.location.outside') == 'undefined') { + $SM.set('features.location.outside', true); + $SM.setM('game.outside', { buildings: {}, population: 0, workers: {} - } + }); } this.updateVillage(); @@ -159,27 +160,27 @@ var Outside = { }, numBuilding: function(bName) { - return State.outside && - State.outside.buildings && - State.outside.buildings[bName] ? State.outside.buildings[bName] : 0; + return $SM.get('features.location.outside') && + $SM.get('game.outside.buildings') && + $SM.get('game.outside.buildings[\''+bName+'\']', true); }, addBuilding: function(bName, num) { - var cur = State.outside.buildings[bName]; + var cur = $SM.get('game.outside.buildings[\''+bName+'\']'); if(typeof cur != 'number') cur = 0; cur += num; if(cur < 0) cur = 0; - State.outside.buildings[bName] = cur; + $SM.set('game.outside.buildings[\''+bName+'\']', cur); this.updateVillage(); Engine.saveGame(); }, addBuildings: function(list) { for(k in list) { - var num = State.outside.buildings[k]; + var num = $SM.get('game.outside.buildings[\''+k+'\']'); if(typeof num != 'number') num = 0; num += list[k]; - State.outside.buildings[k] = num; + $SM.set('game.outside.buildings[\''+k+'\']', num); } this.updateVillage(); Engine.saveGame(); @@ -190,14 +191,14 @@ var Outside = { }, getPopulation: function() { - if(State.outside && State.outside.population) { - return State.outside.population; + if($SM.get('features.location.outside') && $SM.get('game.outside.population')) { + return $SM.get('game.outside.population'); } return 0; }, increasePopulation: function() { - var space = Outside.getMaxPopulation() - State.outside.population; + var space = Outside.getMaxPopulation() - $SM.get('game.outside.population'); if(space > 0) { var num = Math.floor(Math.random()*(space/2) + space/2); if(num == 0) num = 1; @@ -213,7 +214,7 @@ var Outside = { Notifications.notify(null, "the town's booming. word does get around."); } Engine.log('population increased by ' + num); - State.outside.population += num; + $SM.add('game.outside.population', num); Outside.updateVillage(); Outside.updateWorkersView(); Outside.updateVillageIncome(); @@ -222,20 +223,20 @@ var Outside = { }, killVillagers: function(num) { - State.outside.population -= num; - if(State.outside.population < 0) { - State.outside.population = 0; + $SM.add('game.outside.population', num * -1); + if($SM.get('game.outside.population') < 0) { + $SM.set('game.outside.population', 0); } var remaining = Outside.getNumGatherers(); if(remaining < 0) { var gap = -remaining; - for(var k in State.outside.workers) { - var num = State.outside.workers[k]; + for(var k in $SM.get('game.outside.workers')) { + var num = $SM.get('game.outside.workers[\''+k+'\']'); if(num < gap) { gap -= num; - State.outside.workers[k] = 0; + $SM.set('game.outside.workers[\''+k+'\']', 0); } else { - State.outside.workers[k] -= gap; + $SM.add('game.outside.workers[\''+k+'\']', gap * -1); break; } } @@ -256,7 +257,7 @@ var Outside = { // If our population is 0 and we don't already have a workers view, // there's nothing to do here. - if(!workers.length && State.outside.population == 0) return; + if(!workers.length && $SM.get('game.outside.population') == 0) return; var needsAppend = false; if(workers.length == 0) { @@ -264,13 +265,13 @@ var Outside = { workers = $('
').attr('id', 'workers').css('opacity', 0); } - var numGatherers = State.outside.population; + var numGatherers = $SM.get('game.outside.population'); var gatherer = $('div#workers_row_gatherer', workers); - for(var k in State.outside.workers) { + for(var k in $SM.get('game.outside.workers')) { var row = $('div#workers_row_' + k.replace(' ', '-'), workers); if(row.length == 0) { - row = Outside.makeWorkerRow(k, State.outside.workers[k]); + row = Outside.makeWorkerRow(k, $SM.get('game.outside.workers[\''+k+'\']')); var curPrev = null; workers.children().each(function(i) { @@ -295,10 +296,10 @@ var Outside = { } } else { - $('div#' + row.attr('id') + ' > div.row_val > span', workers).text(State.outside.workers[k]); + $('div#' + row.attr('id') + ' > div.row_val > span', workers).text($SM.get('game.outside.workers[\''+k+'\']')); } - numGatherers -= State.outside.workers[k]; - if(State.outside.workers[k] == 0) { + numGatherers -= $SM.get('game.outside.workers[\''+k+'\']'); + if($SM.get('game.outside.workers[\''+k+'\']') == 0) { $('.dnBtn', row).addClass('disabled'); $('.dnManyBtn', row).addClass('disabled'); } else { @@ -329,9 +330,9 @@ var Outside = { }, getNumGatherers: function() { - var num = State.outside.population; - for(var k in State.outside.workers) { - num -= State.outside.workers[k]; + var num = $SM.get('game.outside.population'); + for(var k in $SM.get('game.outside.workers')) { + num -= $SM.get('game.outside.workers[\''+k+'\']'); } return num; }, @@ -371,7 +372,7 @@ var Outside = { if(Outside.getNumGatherers() > 0) { var increaseAmt = Math.min(Outside.getNumGatherers(), btn.data); Engine.log('increasing ' + worker + ' by ' + increaseAmt); - State.outside.workers[worker] += increaseAmt; + $SM.add('game.outside.workers[\''+worker+'\']', increaseAmt); Outside.updateVillageIncome(); Outside.updateWorkersView(); } @@ -379,10 +380,10 @@ var Outside = { decreaseWorker: function(btn) { var worker = $(this).closest('.workerRow').children('.row_key').text(); - if(State.outside.workers[worker] > 0) { - var decreaseAmt = Math.min(State.outside.workers[worker] || 0, btn.data); + if($SM.get('game.outside.workers[\''+worker+'\']') > 0) { + var decreaseAmt = Math.min($SM.get('game.outside.workers[\''+worker+'\']') || 0, btn.data); Engine.log('decreasing ' + worker + ' by ' + decreaseAmt); - State.outside.workers[worker] -= decreaseAmt; + $SM.add('game.outside.workers[\''+worker+'\']', decreaseAmt * -1); Outside.updateVillageIncome(); Outside.updateWorkersView(); } @@ -428,9 +429,9 @@ var Outside = { population = $('
').attr('id', 'population').appendTo(village); } - for(var k in State.outside.buildings) { + for(var k in $SM.get('game.outside.buildings')) { if(k == 'trap') { - var numTraps = State.outside.buildings[k]; + var numTraps = $SM.get('game.outside.buildings[\''+k+'\']'); var numBait = Engine.getStore('bait'); var traps = numTraps - numBait; traps = traps < 0 ? 0 : traps; @@ -440,11 +441,11 @@ var Outside = { if(Outside.checkWorker(k)) { Outside.updateWorkersView(); } - Outside.updateVillageRow(k, State.outside.buildings[k], village); + Outside.updateVillageRow(k, $SM.get('game.outside.buildings[\''+k+'\']'), village); } } - population.text('pop ' + State.outside.population + '/' + this.getMaxPopulation()); + population.text('pop ' + $SM.get('game.outside.population') + '/' + this.getMaxPopulation()); var hasPeeps; if(Outside.numBuilding('hut') == 0) { @@ -488,10 +489,10 @@ var Outside = { if(typeof jobs == 'object') { for(var i = 0, len = jobs.length; i < len; i++) { var job = jobs[i]; - if(typeof State.outside.buildings[name] == 'number' && - typeof State.outside.workers[job] != 'number') { + if(typeof $SM.get('game.outside.buildings[\''+name+'\']') == 'number' && + typeof $SM.get('game.outside.workers[\''+job+'\']') != 'number') { Engine.log('adding ' + job + ' to the workers list') - State.outside.workers[job] = 0; + $SM.set('game.outside.workers[\''+job+'\']', 0); added = true; } } @@ -502,7 +503,7 @@ var Outside = { updateVillageIncome: function() { for(var worker in Outside._INCOME) { var income = Outside._INCOME[worker]; - var num = worker == 'gatherer' ? Outside.getNumGatherers() : State.outside.workers[worker]; + var num = worker == 'gatherer' ? Outside.getNumGatherers() : $SM.get('game.outside.workers[\''+worker+'\']'); if(typeof num == 'number') { var stores = {}; if(num < 0) num = 0; @@ -575,9 +576,9 @@ var Outside = { onArrival: function(transition_diff) { Outside.setTitle(); - if(!State.seenForest) { + if(!$SM.get('game.outside.seenForest')) { Notifications.notify(Outside, "the sky is grey and the wind blows relentlessly"); - State.seenForest = true; + $SM.set('game.outside.seenForest', true); } Outside.updateTrapButton(); Outside.updateVillage(); diff --git a/script/path.js b/script/path.js index 17abf0b..d880eb2 100644 --- a/script/path.js +++ b/script/path.js @@ -85,17 +85,17 @@ var Path = { }, updatePerks: function() { - if(State.perks) { + if($SM.get('character.perks')) { var perks = $('#perks'); var needsAppend = false; if(perks.length == 0) { needsAppend = true; perks = $('
').attr('id', 'perks'); } - for(var k in State.perks) { + for(var k in $SM.get('character.perks')) { var id = 'perk_' + k.replace(' ', '-'); var r = $('#' + id); - if(State.perks[k] && r.length == 0) { + if($SM.get('character.perks[\''+k+'\']') && r.length == 0) { r = $('
').attr('id', id).addClass('perkRow').appendTo(perks); $('
').addClass('row_key').text(k).appendTo(r); $('
').addClass('tooltip bottom right').text(Engine.Perks[k].desc).appendTo(r); @@ -166,7 +166,7 @@ var Path = { for(var k in carryable) { var store = carryable[k]; - var have = State.stores[k]; + var have = $SM.get('stores[\''+k+'\']'); var num = Path.outfit[k]; num = typeof num == 'number' ? num : 0; var numAvailable = Engine.getStore(k); diff --git a/script/room.js b/script/room.js index aff291d..3131269 100644 --- a/script/room.js +++ b/script/room.js @@ -437,19 +437,20 @@ var Room = { ); if(Engine._debug) { - this._ROOM_WARM_DELAY = 1; - this._BUILDER_STATE_DELAY = 1; + this._ROOM_WARM_DELAY = 5000; + this._BUILDER_STATE_DELAY = 5000; this._STOKE_COOLDOWN = 0; - this._NEED_WOOD_DELAY = 1; + this._NEED_WOOD_DELAY = 5000; } - if(typeof State.room == 'undefined') { - State.room = { + if(typeof $SM.get('features.location.room') == 'undefined') { + $SM.set('features.location.room', true); + $SM.set('game.room', { temperature: this.TempEnum.Cold, fire: this.FireEnum.Dead, buttons: {}, builder: -1 - }; + }); } // Create the room tab @@ -502,16 +503,16 @@ var Room = { * 3 - Sleeping * 4 - Helping */ - if(State.room.builder >= 0 && State.room.builder < 3) { + if($SM.get('game.room.builder') >= 0 && $SM.get('game.room.builder') < 3) { Room._builderTimer = setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY); } - if(State.room.builder == 1 && Engine.getStore('wood') < 0) { + if($SM.get('game.room.builder') == 1 && Engine.getStore('wood') < 0) { setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY); } setTimeout(Engine.collectIncome, 1000); - Notifications.notify(Room, "the room is " + State.room.temperature.text); - Notifications.notify(Room, "the fire is " + State.room.fire.text); + Notifications.notify(Room, "the room is " + $SM.get('game.room.temperature.text')); + Notifications.notify(Room, "the fire is " + $SM.get('game.room.fire.text')); }, options: {}, // Nothing for now @@ -519,12 +520,12 @@ var Room = { onArrival: function(transition_diff) { Room.setTitle(); if(Room.changed) { - Notifications.notify(Room, "the fire is " + State.room.fire.text); - Notifications.notify(Room, "the room is " + State.room.temperature.text); + Notifications.notify(Room, "the fire is " + $SM.get('game.room.fire.text')); + Notifications.notify(Room, "the room is " + $SM.get('game.room.temperature.text')); Room.changed = false; } - if(State.room.builder == 3) { - State.room.builder++; + if($SM.get('game.room.builder') == 3) { + $SM.add('game.room.builder', 1); Engine.setIncome('builder', { delay: 10, stores: {'wood' : 2 } @@ -569,7 +570,7 @@ var Room = { }, setTitle: function() { - var title = State.room.fire.value < 2 ? "A Dark Room" : "A Firelit Room"; + var title = $SM.get('game.room.fire.value') < 2 ? "A Dark Room" : "A Firelit Room"; if(Engine.activeModule == this) { document.title = title; } @@ -579,7 +580,7 @@ var Room = { updateButton: function() { var light = $('#lightButton.button'); var stoke = $('#stokeButton.button'); - if(State.room.fire.value == Room.FireEnum.Dead.value && stoke.css('display') != 'none') { + if($SM.get('game.room.fire.value') == Room.FireEnum.Dead.value && stoke.css('display') != 'none') { stoke.hide(); light.show(); if(stoke.hasClass('disabled')) { @@ -613,7 +614,7 @@ var Room = { } else if(wood > 4) { Engine.setStore('wood', wood - 5); } - State.room.fire = Room.FireEnum.Burning; + $SM.set('game.room.fire', Room.FireEnum.Burning); Room.onFireChange(); }, @@ -627,8 +628,8 @@ var Room = { if(wood > 0) { Engine.setStore('wood', wood - 1); } - if(State.room.fire.value < 4) { - State.room.fire = Room.FireEnum.fromInt(State.room.fire.value + 1); + if($SM.get('game.room.fire.value') < 4) { + $SM.set('game.room.fire', Room.FireEnum.fromInt($SM.get('game.room.fire.value') + 1)); } Room.onFireChange(); }, @@ -637,9 +638,9 @@ var Room = { if(Engine.activeModule != Room) { Room.changed = true; } - Notifications.notify(Room, "the fire is " + State.room.fire.text, true); - if(State.room.fire.value > 1 && State.room.builder < 0) { - State.room.builder = 0; + Notifications.notify(Room, "the fire is " + $SM.get('game.room.fire.text'), true); + if($SM.get('game.room.fire.value') > 1 && $SM.get('game.room.builder') < 0) { + $SM.set('game.room.builder', 0); Notifications.notify(Room, "the light from the fire spills from the windows, out into the dark"); setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY); } @@ -650,30 +651,30 @@ var Room = { }, coolFire: function() { - if(State.room.fire.value <= Room.FireEnum.Flickering.value && - State.room.builder > 3 && Engine.getStore('wood') > 0) { + if($SM.get('game.room.fire.value') <= Room.FireEnum.Flickering.value && + $SM.get('game.room.builder') > 3 && Engine.getStore('wood') > 0) { Notifications.notify(Room, "builder stokes the fire", true); Engine.setStore('wood', Engine.getStore('wood') - 1); - State.room.fire = Room.FireEnum.fromInt(State.room.fire.value + 1); + $SM.set('game.room.fire', Room.FireEnum.fromInt($SM.get('game.room.fire.value') + 1)); } - if(State.room.fire.value > 0) { - State.room.fire = Room.FireEnum.fromInt(State.room.fire.value - 1); + if($SM.get('game.room.fire.value') > 0) { + $SM.set('game.room.fire', Room.FireEnum.fromInt($SM.get('game.room.fire.value') - 1)); Room._fireTimer = setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY); Room.onFireChange(); } }, adjustTemp: function() { - var old = State.room.temperature.value; - if(State.room.temperature.value > 0 && State.room.temperature.value > State.room.fire.value) { - State.room.temperature = Room.TempEnum.fromInt(State.room.temperature.value - 1); - Notifications.notify(Room, "the room is " + State.room.temperature.text, true); + var old = $SM.get('game.room.temperature.value'); + if($SM.get('game.room.temperature.value') > 0 && $SM.get('game.room.temperature.value') > $SM.get('game.room.fire.value')) { + $SM.set('game.room.temperature', Room.TempEnum.fromInt($SM.get('game.room.temperature.value') - 1)); + Notifications.notify(Room, "the room is " + $SM.get('game.room.temperature.text'), true); } - if(State.room.temperature.value < 4 && State.room.temperature.value < State.room.fire.value) { - State.room.temperature = Room.TempEnum.fromInt(State.room.temperature.value + 1); - Notifications.notify(Room, "the room is " + State.room.temperature.text, true); + if($SM.get('game.room.temperature.value') < 4 && $SM.get('game.room.temperature.value') < $SM.get('game.room.fire.value')) { + $SM.set('game.room.temperature', Room.TempEnum.fromInt($SM.get('game.room.temperature.value') + 1)); + Notifications.notify(Room, "the room is " + $SM.get('game.room.temperature.text'), true); } - if(State.room.temperature.value != old) { + if($SM.get('game.room.temperature.value') != old) { Room.changed = true; } Room._tempTimer = setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY); @@ -690,14 +691,14 @@ var Room = { }, updateBuilderState: function() { - if(State.room.builder == 0) { + if($SM.get('game.room.builder') == 0) { Notifications.notify(Room, "a ragged stranger stumbles through the door and collapses in the corner"); - State.room.builder = 1; + $SM.set('game.room.builder', 1); setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY); } - else if(State.room.builder < 3 && State.room.temperature.value >= Room.TempEnum.Warm.value) { + else if($SM.get('game.room.builder') < 3 && $SM.get('game.room.temperature.value') >= Room.TempEnum.Warm.value) { var msg; - switch(State.room.builder) { + switch($SM.get('game.room.builder')) { case 1: msg = "the stranger shivers, and mumbles quietly. her words are unintelligible."; break; @@ -706,11 +707,11 @@ var Room = { break; } Notifications.notify(Room, msg); - if(State.room.builder < 3) { - State.room.builder++; + if($SM.get('game.room.builder') < 3) { + $SM.add('game.room.builder', 1); } } - if(State.room.builder < 3) { + if($SM.get('game.room.builder') < 3) { setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY); } Engine.saveGame(); @@ -732,7 +733,7 @@ var Room = { }).css('opacity', 0); wNeedsAppend = true; } - for(var k in State.stores) { + for(var k in $SM.get('stores')) { var type = null; if(Room.Craftables[k]) { @@ -758,17 +759,18 @@ var Room = { var id = "row_" + k.replace(' ', '-'); var row = $('div#' + id, location); - var num = State.stores[k]; + var num = $SM.get('stores[\''+k+'\']'); if(typeof num != 'number' || isNaN(num)) { // No idea how counts get corrupted, but I have reason to believe that they occassionally do. // Build a little fence around it! - num = State.stores[k] = 0; + num = 0; + $SM.set('stores[\''+k+'\']', 0); } // thieves? - if(typeof State.thieves == 'undefined' && num > 5000 && State.world) { + if(typeof $SM.get('game.thieves') == 'undefined' && num > 5000 && $SM.get('features.location.world')) { Engine.startThieves(); } @@ -819,14 +821,14 @@ var Room = { updateIncomeView: function() { var stores = $('div#stores'); - if(stores.length == 0 || typeof State.income == 'undefined') return; + if(stores.length == 0 || typeof $SM.get('income') == 'undefined') return; $('div.storeRow', stores).each(function(index, el) { el = $(el); $('div.tooltip', el).remove(); var tt = $('
').addClass('tooltip bottom right'); var storeName = el.attr('id').substring(4).replace('-', ' '); - for(var incomeSource in State.income) { - var income = State.income[incomeSource]; + for(var incomeSource in $SM.get('income')) { + var income = $SM.get('income[\''+incomeSource+'\']'); for(var store in income.stores) { if(store == storeName && income.stores[store] != 0) { $('
').addClass('row_key').text(incomeSource).appendTo(tt); @@ -878,7 +880,7 @@ var Room = { build: function(buildBtn) { var thing = $(buildBtn).attr('buildThing'); - if(State.room.temperature.value <= Room.TempEnum.Cold.value) { + if($SM.get('game.room.temperature.value') <= Room.TempEnum.Cold.value) { Notifications.notify(Room, "builder just shivers"); return false; } @@ -938,12 +940,12 @@ var Room = { }, craftUnlocked: function(thing) { - if(typeof State.room != 'undefined' && - typeof State.room.buttons != 'undefined' && - State.room.buttons[thing]) { + if(typeof $SM.get('features.location.room') != 'undefined' && + typeof $SM.get('game.room.buttons') != 'undefined' && + $SM.get('game.room.buttons[\''+thing+'\']')) { return true; } - if(State.room.builder < 4) return false; + if($SM.get('game.room.builder') < 4) return false; var craftable = Room.Craftables[thing]; if(Room.needsWorkshop(craftable.type) && Outside.numBuilding('workshop') == 0) return false; var cost = craftable.cost(); @@ -958,15 +960,15 @@ var Room = { } } - State.room.buttons[thing] = true; + $SM.set('game.room.buttons[\''+thing+'\']', true); Notifications.notify(Room, craftable.availableMsg); return true; }, buyUnlocked: function(thing) { - if(typeof State.room != 'undefined' && - typeof State.room.buttons != 'undefined' && - State.room.buttons[thing]) { + if(typeof $SM.get('features.location.room') != 'undefined' && + typeof $SM.get('game.room.buttons') != 'undefined' && + $SM.get('game.room.buttons[\''+thing+'\']')) { return true; } else if(Outside.numBuilding('trading post') > 0) { if(thing == 'compass' || Engine.storeAvailable(thing)) { diff --git a/script/ship.js b/script/ship.js index 0fad202..64dce98 100644 --- a/script/ship.js +++ b/script/ship.js @@ -15,11 +15,12 @@ var Ship = { options ); - if(!State.ship) { - State.ship = { + if(!$SM.get('features.location.spaceShip')) { + $SM.set('features.location.spaceShip', true); + $SM.setM('game.spaceShip', { hull: Ship.BASE_HULL, thrusters: Ship.BASE_THRUSTERS - } + }); } // Create the Ship tab @@ -35,13 +36,13 @@ var Ship = { // Draw the hull label var hullRow = $('
').attr('id', 'hullRow').appendTo('div#shipPanel'); $('
').addClass('row_key').text('hull:').appendTo(hullRow); - $('
').addClass('row_val').text(State.ship.hull).appendTo(hullRow); + $('
').addClass('row_val').text($SM.get('game.spaceShip.hull')).appendTo(hullRow); $('
').addClass('clear').appendTo(hullRow); // Draw the thrusters label var engineRow = $('
').attr('id', 'engineRow').appendTo('div#shipPanel'); $('
').addClass('row_key').text('engine:').appendTo(engineRow); - $('
').addClass('row_val').text(State.ship.thrusters).appendTo(engineRow); + $('
').addClass('row_val').text($SM.get('game.spaceShip.thrusters')).appendTo(engineRow); $('
').addClass('clear').appendTo(engineRow); // Draw the reinforce button @@ -71,7 +72,7 @@ var Ship = { cooldown: Ship.LIFTOFF_COOLDOWN }).appendTo('div#shipPanel'); - if(State.ship.hull <= 0) { + if($SM.get('game.spaceShip.hull') <= 0) { Button.setDisabled(b, true); } @@ -83,9 +84,9 @@ var Ship = { onArrival: function(transition_diff) { Ship.setTitle(); - if(!State.seenShip) { + if(!$SM.get('game.spaceShip.seenShip')) { Notifications.notify(Ship, 'somewhere above the debris cloud, the wanderer fleet hovers. been on this rock too long.'); - State.seenShip = true; + $SM.set('game.spaceShip.seenShip', true); Engine.saveGame(); } @@ -104,11 +105,11 @@ var Ship = { return false; } Engine.addStore('alien alloy', -Ship.ALLOY_PER_HULL); - State.ship.hull++; - if(State.ship.hull > 0) { + $SM.add('game.spaceShip.hull', 1); + if($SM.get('game.spaceShip.hull') > 0) { Button.setDisabled($('#liftoffButton', Ship.panel), false); } - $('#hullRow .row_val', Ship.panel).text(State.ship.hull); + $('#hullRow .row_val', Ship.panel).text($SM.get('game.spaceShip.hull')); }, upgradeEngine: function() { @@ -117,16 +118,16 @@ var Ship = { return false; } Engine.addStore('alien alloy', -Ship.ALLOY_PER_THRUSTER); - State.ship.thrusters++; - $('#engineRow .row_val', Ship.panel).text(State.ship.thrusters); + $SM.add('game.spaceShip.thrusters', 1) + $('#engineRow .row_val', Ship.panel).text($SM.get('game.spaceShip.thrusters')); }, getMaxHull: function() { - return State.ship.hull; + return $SM.get('game.spaceShip.hull'); }, checkLiftOff: function() { - if(!State.ship.seenWarning) { + if(!$SM.get('game.spaceShip.seenWarning')) { Events.startEvent({ title: 'Ready to Leave?', scenes: { @@ -138,7 +139,7 @@ var Ship = { 'fly': { text: 'lift off', onChoose: function() { - State.ship.seenWarning = true; + $SM.set('game.spaceShip.seenWarning', true); Ship.liftOff(); }, nextScene: 'end' diff --git a/script/space.js b/script/space.js index 488de1c..16b8c64 100644 --- a/script/space.js +++ b/script/space.js @@ -87,7 +87,7 @@ var Space = { }, getSpeed: function() { - return Space.SHIP_SPEED + State.ship.thrusters; + return Space.SHIP_SPEED + $SM.get('game.spaceShip.thrusters'); }, updateHull: function() { diff --git a/script/state_manager.js b/script/state_manager.js new file mode 100644 index 0000000..5615bda --- /dev/null +++ b/script/state_manager.js @@ -0,0 +1,212 @@ +/* + * 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 + 'income', + 'timers', + 'game', //mostly location related: fire temp, workers, population, world map, etc + 'playStats', //anything play related: play time, loads, etc + ]; + + for(var which in cats) { + if(!$SM.get(cats[which])) $SM.set(cats[which], {}); + }; + }, + + //create the parent of a given state, recursive as needed + createParent: function(stateName) { + var err = 0; + + //parse path to find last child + var lastDot = stateName.lastIndexOf('.'); //if ends with a dot, there is a coding bug, not like ending in a bracket, so don't account for it + if(lastDot == stateName.length) { + Engine.log('ERROR: '+stateName+' is invalid. Cannot end in a dot.'); + return; + } + var lastOB = stateName.lastIndexOf('['); + //make sure last bracket isn't just end of the line + var lastCB = stateName.substr(0, stateName.length -1).lastIndexOf(']'); + //find last child or return if no more children + var cutoff = Math.max(lastDot, lastOB, lastCB); + if(cutoff <= 0) return; + + var parentPath = $SM.buildPath(stateName.substr(0,cutoff)); + + //try creating the parent + try { + eval('('+parentPath+') = {}'); + } catch (e) { + //need to go up another level and make parent of whichParent + $SM.createParent(stateName.substr(0,cutoff)); + //then it will definitely work if not, something is fubar + eval('('+parentPath+') = {}'); + } + }, + + //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.createParent(stateName); + //now it will definitely work. if not, something is broken + eval('('+fullPath+') = 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) { + var whichParent = $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; + //0 if undefined, null (but not {}) should allow adding to new objects, helps avoid existence checks and NaN for stores + //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 + var old = $SM.get(stateName, true); + + if(typeof old != 'number' || typeof value != 'number'){ + Engine.log('WARNING: Can not do math with state:'+stateName+' or value:'+value+' because at least one is not a number.'); + err = 1 + } 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, name); + + //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; + }, + + remove: function(stateName) { + var whichState = $SM.buildPath(whichState); + try{ + delete eval(whichState); + } catch (e) { + //it didn't exist in the first place + Engine.log('WARNING: Tried to remove non-existant state \''+stateName+'\'.'); + } + Engine.saveGame(); + $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){ + if(stateName == undefined) stateName = 'all'; //best if this doesn't happen as it will trigger more stuff + $.event.trigger({ + 'type': 'stateUpdate', + 'stateName': stateName, + }); + if(save) Engine.saveGame(); + }, + + handleStateUpdates: function(e){ + + }, +}; + +//alias +var $SM = StateManager; + +//listener for StateManager update events +$(StateManager).on('stateUpdate', $SM.handleStateUpdates); \ No newline at end of file diff --git a/script/world.js b/script/world.js index d20f6b6..c608aab 100644 --- a/script/world.js +++ b/script/world.js @@ -128,11 +128,12 @@ var World = { World.LANDMARKS[World.TILE.BATTLEFIELD] = {num: 5, minRadius: 18, maxRadius: World.RADIUS * 1.5, scene: 'battlefield', label: 'A Battlefield'}; World.LANDMARKS[World.TILE.SWAMP] = {num: 1, minRadius: 15, maxRadius: World.RADIUS * 1.5, scene: 'swamp', label: 'A Murky Swamp'}; - if(typeof State.world == 'undefined') { - State.world = { + if(typeof $SM.get('features.location.world') == 'undefined') { + $SM.set('features.location.world', true); + $SM.setM('game.world', { map: World.generateMap(), mask: World.newMask() - }; + }); } // Create the World panel @@ -440,9 +441,9 @@ var World = { Notifications.notify(World, 'starvation sets in') World.starvation = true; } else { - State.starved = State.starved ? State.starved : 0; - State.starved++; - if(State.starved >= 10 && !Engine.hasPerk('slow metabolism')) { + $SM.set('character.starved', $SM.get('character.starved', true)); + $SM.add('character.starved', 1); + if($SM.get('character.starved') >= 10 && !Engine.hasPerk('slow metabolism')) { Engine.addPerk('slow metabolism'); } World.die(); @@ -469,9 +470,9 @@ var World = { Notifications.notify(World, 'the thirst becomes unbearable'); World.thirst = true; } else { - State.dehydrated = State.dehydrated ? State.dehydrated : 0; - State.dehydrated++; - if(State.dehydrated >= 10 && !Engine.hasPerk('desert rat')) { + $SM.set('character.dehydrated', $SM.get('character.dehydrated', true)); + $SM.add('character.dehydrated', 1); + if($SM.get('character.dehydrated') >= 10 && !Engine.hasPerk('desert rat')) { Engine.addPerk('desert rat'); } World.die(); @@ -604,7 +605,7 @@ var World = { applyMap: function() { var x = Math.floor(Math.random() * (World.RADIUS * 2) + 1); var y = Math.floor(Math.random() * (World.RADIUS * 2) + 1); - World.uncoverMap(x, y, 5, State.world.mask); + World.uncoverMap(x, y, 5, $SM.get('game.world.mask')); }, generateMap: function() { @@ -822,7 +823,7 @@ var World = { goHome: function() { // Home safe! Commit the changes. - State.world = World.state; + $SM.setM('game.world', World.state); if(World.state.sulphurmine && Outside.numBuilding('sulphur mine') == 0) { Outside.addBuilding('sulphur mine', 1); Engine.event('progress', 'sulphur mine'); @@ -835,7 +836,7 @@ var World = { Outside.addBuilding('coal mine', 1); Engine.event('progress', 'coal mine'); } - if(World.state.ship && !State.ship) { + if(World.state.ship && !$SM.get('features.location.spaceShip')) { Ship.init(); Engine.event('progress', 'ship'); } @@ -904,7 +905,7 @@ var World = { Notifications.notify(null, 'water replenished'); World.setWater(World.getMaxWater()); // Save progress at outposts - State.world = World.state; + $SM.setM('game.world', World.state); // Mark this outpost as used World.usedOutposts[World.curPos[0] + ',' + World.curPos[1]] = true; }, @@ -912,7 +913,7 @@ var World = { onArrival: function() { Engine.keyLock = false; // Explore in a temporary world-state. We'll commit the changes if you return home safe. - World.state = $.extend(true, {}, State.world); + World.state = $.extend(true, {}, $SM.get('game.world')); World.setWater(World.getMaxWater()); World.setHp(World.getMaxHealth()); World.foodMove = 0;