').attr('id', 'buttons').appendTo(Events.eventPanel());
+ Events.loadScene('start');
+ $('div#wrapper').append(Events.eventPanel());
+ Events.eventPanel().animate({opacity: 1}, Events._PANEL_FADE, 'linear');
+ var currentSceneInformation = Events.activeEvent().scenes[Events.activeScene];
+ if (currentSceneInformation.blink) {
+ Events.blinkTitle();
+ }
+ }
+ },
+
+ scheduleNextEvent: function(scale) {
+ var nextEvent = Math.floor(Math.random()*(Events._EVENT_TIME_RANGE[1] - Events._EVENT_TIME_RANGE[0])) + Events._EVENT_TIME_RANGE[0];
+ if(scale > 0) { nextEvent *= scale; }
+ Engine.log('next event scheduled in ' + nextEvent + ' minutes');
+ Events._eventTimeout = Engine.setTimeout(Events.triggerEvent, nextEvent * 60 * 1000);
+ },
+
+ endEvent: function() {
+ Events.eventPanel().animate({opacity:0}, Events._PANEL_FADE, 'linear', function() {
+ Events.eventPanel().remove();
+ Events.activeEvent().eventPanel = null;
+ Events.eventStack.shift();
+ Engine.log(Events.eventStack.length + ' events remaining');
+ Engine.keyLock = false;
+ if (Events.BLINK_INTERVAL) {
+ Events.stopTitleBlink();
+ }
+ // Force refocus on the body. I hate you, IE.
+ $('body').focus();
+ });
+ },
+
+ handleStateUpdates: function(e){
+ if((e.category == 'stores' || e.category == 'income') && Events.activeEvent() != null){
+ Events.updateButtons();
+ }
+ }
+};
diff --git a/script/events/outside.js b/script/events/outside.js
index 45a6099..a829103 100644
--- a/script/events/outside.js
+++ b/script/events/outside.js
@@ -1,282 +1,282 @@
-/**
- * Events that can occur when the Outside module is active
- **/
-Events.Outside = [
- { /* Ruined traps */
- title: _('A Ruined Trap'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.buildings["trap"]', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _('some of the traps have been torn apart.'),
- _('large prints lead away, into the forest.')
- ],
- onLoad: function() {
- var numWrecked = Math.floor(Math.random() * $SM.get('game.buildings["trap"]', true)) + 1;
- $SM.add('game.buildings["trap"]', -numWrecked);
- Outside.updateVillage();
- Outside.updateTrapButton();
- },
- notification: _('some traps have been destroyed'),
- blink: true,
- buttons: {
- 'track': {
- text: _('track them'),
- nextScene: {0.5: 'nothing', 1: 'catch'}
- },
- 'ignore': {
- text: _('ignore them'),
- nextScene: 'end'
- }
- }
- },
- 'nothing': {
- text: [
- _('the tracks disappear after just a few minutes.'),
- _('the forest is silent.')
- ],
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- },
- 'catch': {
- text: [
- _('not far from the village lies a large beast, its fur matted with blood.'),
- _('it puts up little resistance before the knife.')
- ],
- reward: {
- fur: 100,
- meat: 100,
- teeth: 10
- },
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- }
- }
- },
- {
- title: _('Fire'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.buildings["hut"]', true) > 0 && $SM.get('game.population', true) > 5;
- },
- scenes: {
- 'start': {
- text: [
- _('a fire rampages through one of the huts, destroying it.'),
- _('all residents in the hut perished in the fire.')
- ],
- notification: _('a fire has started'),
- blink: true,
- onLoad: function() {
- var population = $SM.get('game.population', true);
- var huts = $SM.get('game.buildings["hut"]', true);
- $SM.set('game.buildings["hut"]', (huts - 1));
- $SM.set('game.population', (population - 4));
- },
- buttons: {
- 'mourn': {
- text: _('mourn'),
- notification: _('some villagers have died'),
- nextScene: 'end'
- }
- }
- }
- }
- },
- { /* Sickness */
- title: _('Sickness'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.population', true) > 10 && $SM.get('game.population', true) < 50 && $SM.get('stores.medicine', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _('a sickness is spreading through the village.'),
- _('medicine is needed immediately.')
- ],
-
- blink: true,
- buttons: {
- 'heal': {
- text: _('1 medicine'),
- cost: { 'medicine' : 1 },
- nextScene: {1: 'healed'}
- },
- 'ignore': {
- text: _('ignore it'),
- nextScene: {1: 'death'}
- }
- }
- },
- 'healed': {
- text: [
- _('the sickness is cured in time.')
- ],
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- },
- 'death': {
- text: [
- _('the sickness spreads through the village.'),
- _('the days are spent with burials.'),
- _('the nights are rent with screams.')
- ],
- onLoad: function() {
- var numKilled = Math.floor(Math.random() * 20) + 1;
- Outside.killVillagers(numKilled);
- },
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* Plague */
- title: _('Plague'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.population', true) > 50 && $SM.get('stores.medicine', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _('a terrible plague is fast spreading through the village.'),
- _('medicine is needed immediately.')
- ],
- blink: true,
- buttons: {
- /* Because there is a serious need for medicine, the price is raised. */
- 'buyMedicine': {
- text: _('buy medicine'),
- cost: { 'scales': 70,
- 'teeth': 50 },
- reward: { 'medicine': 1 }
- },
- 'heal': {
- text: _('5 medicine'),
- cost: { 'medicine' : 5 },
- nextScene: {1: 'healed'}
- },
- 'ignore': {
- text: _('do nothing'),
- nextScene: {1: 'death'}
- }
- }
- },
- 'healed': {
- text: [
- _('the plague is kept from spreading.'),
- _('only a few die.'),
- _('the rest bury them.')
- ],
- onLoad: function() {
- var numKilled = Math.floor(Math.random() * 5) + 2;
- Outside.killVillagers(numKilled);
- },
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- },
- 'death': {
- text: [
- _('the plague rips through the village.'),
- _('the nights are rent with screams.'),
- _('the only hope is a quick death.')
- ],
- onLoad: function() {
- var numKilled = Math.floor(Math.random() * 80) + 10;
- Outside.killVillagers(numKilled);
- },
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* Beast attack */
- title: _('A Beast Attack'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.population', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _('a pack of snarling beasts pours out of the trees.'),
- _('the fight is short and bloody, but the beasts are repelled.'),
- _('the villagers retreat to mourn the dead.')
- ],
- onLoad: function() {
- var numKilled = Math.floor(Math.random() * 10) + 1;
- Outside.killVillagers(numKilled);
- },
- reward: {
- fur: 100,
- meat: 100,
- teeth: 10
- },
- blink: true,
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* Soldier attack */
- title: _('A Military Raid'),
- isAvailable: function() {
- return Engine.activeModule == Outside && $SM.get('game.population', true) > 0 && $SM.get('game.cityCleared');
- },
- scenes: {
- 'start': {
- text: [
- _('a gunshot rings through the trees.'),
- _('well armed men charge out of the forest, firing into the crowd.'),
- _('after a skirmish they are driven away, but not without losses.')
- ],
- onLoad: function() {
- var numKilled = Math.floor(Math.random() * 40) + 1;
- Outside.killVillagers(numKilled);
- },
- reward: {
- bullets: 10,
- 'cured meat': 50
- },
-
- blink: true,
- buttons: {
- 'end': {
- text: _('go home'),
- nextScene: 'end'
- }
- }
- }
- }
- }
-];
+/**
+ * Events that can occur when the Outside module is active
+ **/
+Events.Outside = [
+ { /* Ruined traps */
+ title: _('A Ruined Trap'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.buildings["trap"]', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('some of the traps have been torn apart.'),
+ _('large prints lead away, into the forest.')
+ ],
+ onLoad: function() {
+ var numWrecked = Math.floor(Math.random() * $SM.get('game.buildings["trap"]', true)) + 1;
+ $SM.add('game.buildings["trap"]', -numWrecked);
+ Outside.updateVillage();
+ Outside.updateTrapButton();
+ },
+ notification: _('some traps have been destroyed'),
+ blink: true,
+ buttons: {
+ 'track': {
+ text: _('track them'),
+ nextScene: {0.5: 'nothing', 1: 'catch'}
+ },
+ 'ignore': {
+ text: _('ignore them'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'nothing': {
+ text: [
+ _('the tracks disappear after just a few minutes.'),
+ _('the forest is silent.')
+ ],
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'catch': {
+ text: [
+ _('not far from the village lies a large beast, its fur matted with blood.'),
+ _('it puts up little resistance before the knife.')
+ ],
+ reward: {
+ fur: 100,
+ meat: 100,
+ teeth: 10
+ },
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+ {
+ title: _('Fire'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.buildings["hut"]', true) > 0 && $SM.get('game.population', true) > 5;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a fire rampages through one of the huts, destroying it.'),
+ _('all residents in the hut perished in the fire.')
+ ],
+ notification: _('a fire has started'),
+ blink: true,
+ onLoad: function() {
+ var population = $SM.get('game.population', true);
+ var huts = $SM.get('game.buildings["hut"]', true);
+ $SM.set('game.buildings["hut"]', (huts - 1));
+ $SM.set('game.population', (population - 4));
+ },
+ buttons: {
+ 'mourn': {
+ text: _('mourn'),
+ notification: _('some villagers have died'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+ { /* Sickness */
+ title: _('Sickness'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.population', true) > 10 && $SM.get('game.population', true) < 50 && $SM.get('stores.medicine', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a sickness is spreading through the village.'),
+ _('medicine is needed immediately.')
+ ],
+
+ blink: true,
+ buttons: {
+ 'heal': {
+ text: _('1 medicine'),
+ cost: { 'medicine' : 1 },
+ nextScene: {1: 'healed'}
+ },
+ 'ignore': {
+ text: _('ignore it'),
+ nextScene: {1: 'death'}
+ }
+ }
+ },
+ 'healed': {
+ text: [
+ _('the sickness is cured in time.')
+ ],
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'death': {
+ text: [
+ _('the sickness spreads through the village.'),
+ _('the days are spent with burials.'),
+ _('the nights are rent with screams.')
+ ],
+ onLoad: function() {
+ var numKilled = Math.floor(Math.random() * 20) + 1;
+ Outside.killVillagers(numKilled);
+ },
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* Plague */
+ title: _('Plague'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.population', true) > 50 && $SM.get('stores.medicine', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a terrible plague is fast spreading through the village.'),
+ _('medicine is needed immediately.')
+ ],
+ blink: true,
+ buttons: {
+ /* Because there is a serious need for medicine, the price is raised. */
+ 'buyMedicine': {
+ text: _('buy medicine'),
+ cost: { 'scales': 70,
+ 'teeth': 50 },
+ reward: { 'medicine': 1 }
+ },
+ 'heal': {
+ text: _('5 medicine'),
+ cost: { 'medicine' : 5 },
+ nextScene: {1: 'healed'}
+ },
+ 'ignore': {
+ text: _('do nothing'),
+ nextScene: {1: 'death'}
+ }
+ }
+ },
+ 'healed': {
+ text: [
+ _('the plague is kept from spreading.'),
+ _('only a few die.'),
+ _('the rest bury them.')
+ ],
+ onLoad: function() {
+ var numKilled = Math.floor(Math.random() * 5) + 2;
+ Outside.killVillagers(numKilled);
+ },
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'death': {
+ text: [
+ _('the plague rips through the village.'),
+ _('the nights are rent with screams.'),
+ _('the only hope is a quick death.')
+ ],
+ onLoad: function() {
+ var numKilled = Math.floor(Math.random() * 80) + 10;
+ Outside.killVillagers(numKilled);
+ },
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* Beast attack */
+ title: _('A Beast Attack'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.population', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a pack of snarling beasts pours out of the trees.'),
+ _('the fight is short and bloody, but the beasts are repelled.'),
+ _('the villagers retreat to mourn the dead.')
+ ],
+ onLoad: function() {
+ var numKilled = Math.floor(Math.random() * 10) + 1;
+ Outside.killVillagers(numKilled);
+ },
+ reward: {
+ fur: 100,
+ meat: 100,
+ teeth: 10
+ },
+ blink: true,
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* Soldier attack */
+ title: _('A Military Raid'),
+ isAvailable: function() {
+ return Engine.activeModule == Outside && $SM.get('game.population', true) > 0 && $SM.get('game.cityCleared');
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a gunshot rings through the trees.'),
+ _('well armed men charge out of the forest, firing into the crowd.'),
+ _('after a skirmish they are driven away, but not without losses.')
+ ],
+ onLoad: function() {
+ var numKilled = Math.floor(Math.random() * 40) + 1;
+ Outside.killVillagers(numKilled);
+ },
+ reward: {
+ bullets: 10,
+ 'cured meat': 50
+ },
+
+ blink: true,
+ buttons: {
+ 'end': {
+ text: _('go home'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ }
+];
diff --git a/script/events/room.js b/script/events/room.js
index 472e72a..a3d98ce 100644
--- a/script/events/room.js
+++ b/script/events/room.js
@@ -1,603 +1,603 @@
-/**
- * Events that can occur when the Room module is active
- **/
-Events.Room = [
- { /* The Nomad -- Merchant */
- title: _('The Nomad'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.fur', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _('a nomad shuffles into view, laden with makeshift bags bound with rough twine.'),
- _("won't say from where he came, but it's clear that he's not staying.")
- ],
- notification: _('a nomad arrives, looking to trade'),
- blink: true,
- buttons: {
- 'buyScales': {
- text: _('buy scales'),
- cost: { 'fur': 100 },
- reward: { 'scales': 1 }
- },
- 'buyTeeth': {
- text: _('buy teeth'),
- cost: { 'fur': 200 },
- reward: { 'teeth': 1 }
- },
- 'buyBait': {
- text: _('buy bait'),
- cost: { 'fur': 5 },
- reward: { 'bait': 1 },
- notification: _('traps are more effective with bait.')
- },
- 'buyCompass': {
- available: function() {
- return $SM.get('stores.compass', true) < 1;
- },
- text: _('buy compass'),
- cost: { fur: 300, scales: 15, teeth: 5 },
- reward: { 'compass': 1 },
- notification: _('the old compass is dented and dusty, but it looks to work.'),
- onChoose: Path.openPath
- },
- 'goodbye': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- },
- { /* Noises Outside -- gain wood/fur */
- title: _('Noises'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.wood');
- },
- scenes: {
- 'start': {
- text: [
- _('through the walls, shuffling noises can be heard.'),
- _("can't tell what they're up to.")
- ],
- notification: _('strange noises can be heard through the walls'),
- blink: true,
- buttons: {
- 'investigate': {
- text: _('investigate'),
- nextScene: { 0.3: 'stuff', 1: 'nothing' }
- },
- 'ignore': {
- text: _('ignore them'),
- nextScene: 'end'
- }
- }
- },
- 'nothing': {
- text: [
- _('vague shapes move, just out of sight.'),
- _('the sounds stop.')
- ],
- buttons: {
- 'backinside': {
- text: _('go back inside'),
- nextScene: 'end'
- }
- }
- },
- 'stuff': {
- reward: { wood: 100, fur: 10 },
- text: [
- _('a bundle of sticks lies just beyond the threshold, wrapped in coarse furs.'),
- _('the night is silent.')
- ],
- buttons: {
- 'backinside': {
- text: _('go back inside'),
- nextScene: 'end'
- }
- }
- }
- }
- },
- { /* Noises Inside -- trade wood for better good */
- title: _('Noises'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.wood');
- },
- scenes: {
- start: {
- text: [
- _('scratching noises can be heard from the store room.'),
- _('something\'s in there.')
- ],
- notification: _('something\'s in the store room'),
- blink: true,
- buttons: {
- 'investigate': {
- text: _('investigate'),
- nextScene: { 0.5: 'scales', 0.8: 'teeth', 1: 'cloth' }
- },
- 'ignore': {
- text: _('ignore them'),
- nextScene: 'end'
- }
- }
- },
- scales: {
- text: [
- _('some wood is missing.'),
- _('the ground is littered with small scales')
- ],
- onLoad: function() {
- var numWood = $SM.get('stores.wood', true);
- numWood = Math.floor(numWood * 0.1);
- if(numWood === 0) numWood = 1;
- var numScales = Math.floor(numWood / 5);
- if(numScales === 0) numScales = 1;
- $SM.addM('stores', {'wood': -numWood, 'scales': numScales});
- },
- buttons: {
- 'leave': {
- text: _('leave'),
- nextScene: 'end'
- }
- }
- },
- teeth: {
- text: [
- _('some wood is missing.'),
- _('the ground is littered with small teeth')
- ],
- onLoad: function() {
- var numWood = $SM.get('stores.wood', true);
- numWood = Math.floor(numWood * 0.1);
- if(numWood === 0) numWood = 1;
- var numTeeth = Math.floor(numWood / 5);
- if(numTeeth === 0) numTeeth = 1;
- $SM.addM('stores', {'wood': -numWood, 'teeth': numTeeth});
- },
- buttons: {
- 'leave': {
- text: _('leave'),
- nextScene: 'end'
- }
- }
- },
- cloth: {
- text: [
- _('some wood is missing.'),
- _('the ground is littered with scraps of cloth')
- ],
- onLoad: function() {
- var numWood = $SM.get('stores.wood', true);
- numWood = Math.floor(numWood * 0.1);
- if(numWood === 0) numWood = 1;
- var numCloth = Math.floor(numWood / 5);
- if(numCloth === 0) numCloth = 1;
- $SM.addM('stores', {'wood': -numWood, 'cloth': numCloth});
- },
- buttons: {
- 'leave': {
- text: _('leave'),
- nextScene: 'end'
- }
- }
- }
- }
- },
- { /* The Beggar -- trade fur for better good */
- title: _('The Beggar'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.fur');
- },
- scenes: {
- start: {
- text: [
- _('a beggar arrives.'),
- _('asks for any spare furs to keep him warm at night.')
- ],
- notification: _('a beggar arrives'),
- blink: true,
- buttons: {
- '50furs': {
- text: _('give 50'),
- cost: {fur: 50},
- nextScene: { 0.5: 'scales', 0.8: 'teeth', 1: 'cloth' }
- },
- '100furs': {
- text: _('give 100'),
- cost: {fur: 100},
- nextScene: { 0.5: 'teeth', 0.8: 'scales', 1: 'cloth' }
- },
- 'deny': {
- text: _('turn him away'),
- nextScene: 'end'
- }
- }
- },
- scales: {
- reward: { scales: 20 },
- text: [
- _('the beggar expresses his thanks.'),
- _('leaves a pile of small scales behind.')
- ],
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- teeth: {
- reward: { teeth: 20 },
- text: [
- _('the beggar expresses his thanks.'),
- _('leaves a pile of small teeth behind.')
- ],
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- cloth: {
- reward: { cloth: 20 },
- text: [
- _('the beggar expresses his thanks.'),
- _('leaves some scraps of cloth behind.')
- ],
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* Mysterious Wanderer -- wood gambling */
- title: _('The Mysterious Wanderer'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.wood');
- },
- scenes: {
- start: {
- text: [
- _('a wanderer arrives with an empty cart. says if he leaves with wood, he\'ll be back with more.'),
- _("builder's not sure he's to be trusted.")
- ],
- notification: _('a mysterious wanderer arrives'),
- blink: true,
- buttons: {
- '100wood': {
- text: _('give 100'),
- cost: {wood: 100},
- nextScene: { 1: '100wood'}
- },
- '500wood': {
- text: _('give 500'),
- cost: {wood: 500},
- nextScene: { 1: '500wood' }
- },
- 'deny': {
- text: _('turn him away'),
- nextScene: 'end'
- }
- }
- },
- '100wood': {
- text: [
- _('the wanderer leaves, cart loaded with wood')
- ],
- onLoad: function() {
- if(Math.random() < 0.5) {
- Engine.setTimeout(function() {
- $SM.add('stores.wood', 300);
- Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with wood.'));
- }, 60 * 1000);
- }
- },
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- '500wood': {
- text: [
- _('the wanderer leaves, cart loaded with wood')
- ],
- onLoad: function() {
- if(Math.random() < 0.3) {
- Engine.setTimeout(function() {
- $SM.add('stores.wood', 1500);
- Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with wood.'));
- }, 60 * 1000);
- }
- },
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* Mysterious Wanderer -- fur gambling */
- title: _('The Mysterious Wanderer'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.fur');
- },
- scenes: {
- start: {
- text: [
- _('a wanderer arrives with an empty cart. says if she leaves with furs, she\'ll be back with more.'),
- _("builder's not sure she's to be trusted.")
- ],
- notification: _('a mysterious wanderer arrives'),
- blink: true,
- buttons: {
- '100fur': {
- text: _('give 100'),
- cost: {fur: 100},
- nextScene: { 1: '100fur'}
- },
- '500fur': {
- text: _('give 500'),
- cost: {fur: 500},
- nextScene: { 1: '500fur' }
- },
- 'deny': {
- text: _('turn her away'),
- nextScene: 'end'
- }
- }
- },
- '100fur': {
- text: [
- _('the wanderer leaves, cart loaded with furs')
- ],
- onLoad: function() {
- if(Math.random() < 0.5) {
- Engine.setTimeout(function() {
- $SM.add('stores.fur', 300);
- Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with furs.'));
- }, 60 * 1000);
- }
- },
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- '500fur': {
- text: [
- _('the wanderer leaves, cart loaded with furs')
- ],
- onLoad: function() {
- if(Math.random() < 0.3) {
- Engine.setTimeout(function() {
- $SM.add('stores.fur', 1500);
- Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with furs.'));
- }, 60 * 1000);
- }
- },
- buttons: {
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* The Scout -- Map Merchant */
- title: _('The Scout'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('features.location.world');
- },
- scenes: {
- 'start': {
- text: [
- _("the scout says she's been all over."),
- _("willing to talk about it, for a price.")
- ],
- notification: _('a scout stops for the night'),
- blink: true,
- buttons: {
- 'buyMap': {
- text: _('buy map'),
- cost: { 'fur': 200, 'scales': 10 },
- notification: _('the map uncovers a bit of the world'),
- onChoose: World.applyMap
- },
- 'learn': {
- text: _('learn scouting'),
- cost: { 'fur': 1000, 'scales': 50, 'teeth': 20 },
- available: function() {
- return !$SM.hasPerk('scout');
- },
- onChoose: function() {
- $SM.addPerk('scout');
- }
- },
- 'leave': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* The Wandering Master */
- title: _('The Master'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('features.location.world');
- },
- scenes: {
- 'start': {
- text: [
- _('an old wanderer arrives.'),
- _('he smiles warmly and asks for lodgings for the night.')
- ],
- notification: _('an old wanderer arrives'),
- blink: true,
- buttons: {
- 'agree': {
- text: _('agree'),
- cost: {
- 'cured meat': 100,
- 'fur': 100,
- 'torch': 1
- },
- nextScene: {1: 'agree'}
- },
- 'deny': {
- text: _('turn him away'),
- nextScene: 'end'
- }
- }
- },
- 'agree': {
- text: [
- _('in exchange, the wanderer offers his wisdom.')
- ],
- buttons: {
- 'evasion': {
- text: _('evasion'),
- available: function() {
- return !$SM.hasPerk('evasive');
- },
- onChoose: function() {
- $SM.addPerk('evasive');
- },
- nextScene: 'end'
- },
- 'precision': {
- text: _('precision'),
- available: function() {
- return !$SM.hasPerk('precise');
- },
- onChoose: function() {
- $SM.addPerk('precise');
- },
- nextScene: 'end'
- },
- 'force': {
- text: _('force'),
- available: function() {
- return !$SM.hasPerk('barbarian');
- },
- onChoose: function() {
- $SM.addPerk('barbarian');
- },
- nextScene: 'end'
- },
- 'nothing': {
- text: _('nothing'),
- nextScene: 'end'
- }
- }
- }
- }
- },
-
- { /* The Sick Man */
- title: _('The Sick Man'),
- isAvailable: function() {
- return Engine.activeModule == Room && $SM.get('stores.medicine', true) > 0;
- },
- scenes: {
- 'start': {
- text: [
- _("a man hobbles up, coughing."),
- _("he begs for medicine.")
- ],
- notification: _('a sick man hobbles up'),
- blink: true,
- buttons: {
- 'help': {
- text: _('give 1 medicine'),
- cost: { 'medicine': 1 },
- notification: _('the man swallows the medicine eagerly'),
- nextScene: { 0.1: 'alloy', 0.3: 'cells', 0.5: 'scales', 1.0: 'nothing' }
- },
- 'ignore': {
- text: _('tell him to leave'),
- nextScene: 'end'
- }
- }
- },
- 'alloy': {
- text: [
- _("the man is thankful."),
- _('he leaves a reward.'),
- _('some weird metal he picked up on his travels.')
- ],
- onLoad: function() {
- $SM.add('stores["alien alloy"]', 1);
- },
- buttons: {
- 'bye': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- 'cells': {
- text: [
- _("the man is thankful."),
- _('he leaves a reward.'),
- _('some weird glowing boxes he picked up on his travels.')
- ],
- onLoad: function() {
- $SM.add('stores["energy cell"]', 3);
- },
- buttons: {
- 'bye': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- 'scales': {
- text: [
- _("the man is thankful."),
- _('he leaves a reward.'),
- _('all he has are some scales.')
- ],
- onLoad: function() {
- $SM.add('stores.scales', 5);
- },
- buttons: {
- 'bye': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- },
- 'nothing': {
- text: [
- _("the man expresses his thanks and hobbles off.")
- ],
- buttons: {
- 'bye': {
- text: _('say goodbye'),
- nextScene: 'end'
- }
- }
- }
- }
- }
-];
+/**
+ * Events that can occur when the Room module is active
+ **/
+Events.Room = [
+ { /* The Nomad -- Merchant */
+ title: _('The Nomad'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.fur', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('a nomad shuffles into view, laden with makeshift bags bound with rough twine.'),
+ _("won't say from where he came, but it's clear that he's not staying.")
+ ],
+ notification: _('a nomad arrives, looking to trade'),
+ blink: true,
+ buttons: {
+ 'buyScales': {
+ text: _('buy scales'),
+ cost: { 'fur': 100 },
+ reward: { 'scales': 1 }
+ },
+ 'buyTeeth': {
+ text: _('buy teeth'),
+ cost: { 'fur': 200 },
+ reward: { 'teeth': 1 }
+ },
+ 'buyBait': {
+ text: _('buy bait'),
+ cost: { 'fur': 5 },
+ reward: { 'bait': 1 },
+ notification: _('traps are more effective with bait.')
+ },
+ 'buyCompass': {
+ available: function() {
+ return $SM.get('stores.compass', true) < 1;
+ },
+ text: _('buy compass'),
+ cost: { fur: 300, scales: 15, teeth: 5 },
+ reward: { 'compass': 1 },
+ notification: _('the old compass is dented and dusty, but it looks to work.'),
+ onChoose: Path.openPath
+ },
+ 'goodbye': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+ { /* Noises Outside -- gain wood/fur */
+ title: _('Noises'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.wood');
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('through the walls, shuffling noises can be heard.'),
+ _("can't tell what they're up to.")
+ ],
+ notification: _('strange noises can be heard through the walls'),
+ blink: true,
+ buttons: {
+ 'investigate': {
+ text: _('investigate'),
+ nextScene: { 0.3: 'stuff', 1: 'nothing' }
+ },
+ 'ignore': {
+ text: _('ignore them'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'nothing': {
+ text: [
+ _('vague shapes move, just out of sight.'),
+ _('the sounds stop.')
+ ],
+ buttons: {
+ 'backinside': {
+ text: _('go back inside'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'stuff': {
+ reward: { wood: 100, fur: 10 },
+ text: [
+ _('a bundle of sticks lies just beyond the threshold, wrapped in coarse furs.'),
+ _('the night is silent.')
+ ],
+ buttons: {
+ 'backinside': {
+ text: _('go back inside'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+ { /* Noises Inside -- trade wood for better good */
+ title: _('Noises'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.wood');
+ },
+ scenes: {
+ start: {
+ text: [
+ _('scratching noises can be heard from the store room.'),
+ _('something\'s in there.')
+ ],
+ notification: _('something\'s in the store room'),
+ blink: true,
+ buttons: {
+ 'investigate': {
+ text: _('investigate'),
+ nextScene: { 0.5: 'scales', 0.8: 'teeth', 1: 'cloth' }
+ },
+ 'ignore': {
+ text: _('ignore them'),
+ nextScene: 'end'
+ }
+ }
+ },
+ scales: {
+ text: [
+ _('some wood is missing.'),
+ _('the ground is littered with small scales')
+ ],
+ onLoad: function() {
+ var numWood = $SM.get('stores.wood', true);
+ numWood = Math.floor(numWood * 0.1);
+ if(numWood === 0) numWood = 1;
+ var numScales = Math.floor(numWood / 5);
+ if(numScales === 0) numScales = 1;
+ $SM.addM('stores', {'wood': -numWood, 'scales': numScales});
+ },
+ buttons: {
+ 'leave': {
+ text: _('leave'),
+ nextScene: 'end'
+ }
+ }
+ },
+ teeth: {
+ text: [
+ _('some wood is missing.'),
+ _('the ground is littered with small teeth')
+ ],
+ onLoad: function() {
+ var numWood = $SM.get('stores.wood', true);
+ numWood = Math.floor(numWood * 0.1);
+ if(numWood === 0) numWood = 1;
+ var numTeeth = Math.floor(numWood / 5);
+ if(numTeeth === 0) numTeeth = 1;
+ $SM.addM('stores', {'wood': -numWood, 'teeth': numTeeth});
+ },
+ buttons: {
+ 'leave': {
+ text: _('leave'),
+ nextScene: 'end'
+ }
+ }
+ },
+ cloth: {
+ text: [
+ _('some wood is missing.'),
+ _('the ground is littered with scraps of cloth')
+ ],
+ onLoad: function() {
+ var numWood = $SM.get('stores.wood', true);
+ numWood = Math.floor(numWood * 0.1);
+ if(numWood === 0) numWood = 1;
+ var numCloth = Math.floor(numWood / 5);
+ if(numCloth === 0) numCloth = 1;
+ $SM.addM('stores', {'wood': -numWood, 'cloth': numCloth});
+ },
+ buttons: {
+ 'leave': {
+ text: _('leave'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+ { /* The Beggar -- trade fur for better good */
+ title: _('The Beggar'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.fur');
+ },
+ scenes: {
+ start: {
+ text: [
+ _('a beggar arrives.'),
+ _('asks for any spare furs to keep him warm at night.')
+ ],
+ notification: _('a beggar arrives'),
+ blink: true,
+ buttons: {
+ '50furs': {
+ text: _('give 50'),
+ cost: {fur: 50},
+ nextScene: { 0.5: 'scales', 0.8: 'teeth', 1: 'cloth' }
+ },
+ '100furs': {
+ text: _('give 100'),
+ cost: {fur: 100},
+ nextScene: { 0.5: 'teeth', 0.8: 'scales', 1: 'cloth' }
+ },
+ 'deny': {
+ text: _('turn him away'),
+ nextScene: 'end'
+ }
+ }
+ },
+ scales: {
+ reward: { scales: 20 },
+ text: [
+ _('the beggar expresses his thanks.'),
+ _('leaves a pile of small scales behind.')
+ ],
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ teeth: {
+ reward: { teeth: 20 },
+ text: [
+ _('the beggar expresses his thanks.'),
+ _('leaves a pile of small teeth behind.')
+ ],
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ cloth: {
+ reward: { cloth: 20 },
+ text: [
+ _('the beggar expresses his thanks.'),
+ _('leaves some scraps of cloth behind.')
+ ],
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* Mysterious Wanderer -- wood gambling */
+ title: _('The Mysterious Wanderer'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.wood');
+ },
+ scenes: {
+ start: {
+ text: [
+ _('a wanderer arrives with an empty cart. says if he leaves with wood, he\'ll be back with more.'),
+ _("builder's not sure he's to be trusted.")
+ ],
+ notification: _('a mysterious wanderer arrives'),
+ blink: true,
+ buttons: {
+ '100wood': {
+ text: _('give 100'),
+ cost: {wood: 100},
+ nextScene: { 1: '100wood'}
+ },
+ '500wood': {
+ text: _('give 500'),
+ cost: {wood: 500},
+ nextScene: { 1: '500wood' }
+ },
+ 'deny': {
+ text: _('turn him away'),
+ nextScene: 'end'
+ }
+ }
+ },
+ '100wood': {
+ text: [
+ _('the wanderer leaves, cart loaded with wood')
+ ],
+ onLoad: function() {
+ if(Math.random() < 0.5) {
+ Engine.setTimeout(function() {
+ $SM.add('stores.wood', 300);
+ Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with wood.'));
+ }, 60 * 1000);
+ }
+ },
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ '500wood': {
+ text: [
+ _('the wanderer leaves, cart loaded with wood')
+ ],
+ onLoad: function() {
+ if(Math.random() < 0.3) {
+ Engine.setTimeout(function() {
+ $SM.add('stores.wood', 1500);
+ Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with wood.'));
+ }, 60 * 1000);
+ }
+ },
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* Mysterious Wanderer -- fur gambling */
+ title: _('The Mysterious Wanderer'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.fur');
+ },
+ scenes: {
+ start: {
+ text: [
+ _('a wanderer arrives with an empty cart. says if she leaves with furs, she\'ll be back with more.'),
+ _("builder's not sure she's to be trusted.")
+ ],
+ notification: _('a mysterious wanderer arrives'),
+ blink: true,
+ buttons: {
+ '100fur': {
+ text: _('give 100'),
+ cost: {fur: 100},
+ nextScene: { 1: '100fur'}
+ },
+ '500fur': {
+ text: _('give 500'),
+ cost: {fur: 500},
+ nextScene: { 1: '500fur' }
+ },
+ 'deny': {
+ text: _('turn her away'),
+ nextScene: 'end'
+ }
+ }
+ },
+ '100fur': {
+ text: [
+ _('the wanderer leaves, cart loaded with furs')
+ ],
+ onLoad: function() {
+ if(Math.random() < 0.5) {
+ Engine.setTimeout(function() {
+ $SM.add('stores.fur', 300);
+ Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with furs.'));
+ }, 60 * 1000);
+ }
+ },
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ '500fur': {
+ text: [
+ _('the wanderer leaves, cart loaded with furs')
+ ],
+ onLoad: function() {
+ if(Math.random() < 0.3) {
+ Engine.setTimeout(function() {
+ $SM.add('stores.fur', 1500);
+ Notifications.notify(Room, _('the mysterious wanderer returns, cart piled high with furs.'));
+ }, 60 * 1000);
+ }
+ },
+ buttons: {
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* The Scout -- Map Merchant */
+ title: _('The Scout'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('features.location.world');
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _("the scout says she's been all over."),
+ _("willing to talk about it, for a price.")
+ ],
+ notification: _('a scout stops for the night'),
+ blink: true,
+ buttons: {
+ 'buyMap': {
+ text: _('buy map'),
+ cost: { 'fur': 200, 'scales': 10 },
+ notification: _('the map uncovers a bit of the world'),
+ onChoose: World.applyMap
+ },
+ 'learn': {
+ text: _('learn scouting'),
+ cost: { 'fur': 1000, 'scales': 50, 'teeth': 20 },
+ available: function() {
+ return !$SM.hasPerk('scout');
+ },
+ onChoose: function() {
+ $SM.addPerk('scout');
+ }
+ },
+ 'leave': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* The Wandering Master */
+ title: _('The Master'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('features.location.world');
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _('an old wanderer arrives.'),
+ _('he smiles warmly and asks for lodgings for the night.')
+ ],
+ notification: _('an old wanderer arrives'),
+ blink: true,
+ buttons: {
+ 'agree': {
+ text: _('agree'),
+ cost: {
+ 'cured meat': 100,
+ 'fur': 100,
+ 'torch': 1
+ },
+ nextScene: {1: 'agree'}
+ },
+ 'deny': {
+ text: _('turn him away'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'agree': {
+ text: [
+ _('in exchange, the wanderer offers his wisdom.')
+ ],
+ buttons: {
+ 'evasion': {
+ text: _('evasion'),
+ available: function() {
+ return !$SM.hasPerk('evasive');
+ },
+ onChoose: function() {
+ $SM.addPerk('evasive');
+ },
+ nextScene: 'end'
+ },
+ 'precision': {
+ text: _('precision'),
+ available: function() {
+ return !$SM.hasPerk('precise');
+ },
+ onChoose: function() {
+ $SM.addPerk('precise');
+ },
+ nextScene: 'end'
+ },
+ 'force': {
+ text: _('force'),
+ available: function() {
+ return !$SM.hasPerk('barbarian');
+ },
+ onChoose: function() {
+ $SM.addPerk('barbarian');
+ },
+ nextScene: 'end'
+ },
+ 'nothing': {
+ text: _('nothing'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ },
+
+ { /* The Sick Man */
+ title: _('The Sick Man'),
+ isAvailable: function() {
+ return Engine.activeModule == Room && $SM.get('stores.medicine', true) > 0;
+ },
+ scenes: {
+ 'start': {
+ text: [
+ _("a man hobbles up, coughing."),
+ _("he begs for medicine.")
+ ],
+ notification: _('a sick man hobbles up'),
+ blink: true,
+ buttons: {
+ 'help': {
+ text: _('give 1 medicine'),
+ cost: { 'medicine': 1 },
+ notification: _('the man swallows the medicine eagerly'),
+ nextScene: { 0.1: 'alloy', 0.3: 'cells', 0.5: 'scales', 1.0: 'nothing' }
+ },
+ 'ignore': {
+ text: _('tell him to leave'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'alloy': {
+ text: [
+ _("the man is thankful."),
+ _('he leaves a reward.'),
+ _('some weird metal he picked up on his travels.')
+ ],
+ onLoad: function() {
+ $SM.add('stores["alien alloy"]', 1);
+ },
+ buttons: {
+ 'bye': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'cells': {
+ text: [
+ _("the man is thankful."),
+ _('he leaves a reward.'),
+ _('some weird glowing boxes he picked up on his travels.')
+ ],
+ onLoad: function() {
+ $SM.add('stores["energy cell"]', 3);
+ },
+ buttons: {
+ 'bye': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'scales': {
+ text: [
+ _("the man is thankful."),
+ _('he leaves a reward.'),
+ _('all he has are some scales.')
+ ],
+ onLoad: function() {
+ $SM.add('stores.scales', 5);
+ },
+ buttons: {
+ 'bye': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ },
+ 'nothing': {
+ text: [
+ _("the man expresses his thanks and hobbles off.")
+ ],
+ buttons: {
+ 'bye': {
+ text: _('say goodbye'),
+ nextScene: 'end'
+ }
+ }
+ }
+ }
+ }
+];
diff --git a/script/notifications.js b/script/notifications.js
index 68780a2..777c6b3 100644
--- a/script/notifications.js
+++ b/script/notifications.js
@@ -1,78 +1,78 @@
-/**
- * Module that registers the notification box and handles messages
- */
-var Notifications = {
-
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- // Create the notifications box
- elem = $('
').attr({
- id: 'notifications',
- className: 'notifications'
- });
- // Create the transparency gradient
- $('
').attr('id', 'notifyGradient').appendTo(elem);
-
- elem.appendTo('div#wrapper');
- },
-
- options: {}, // Nothing for now
-
- elem: null,
-
- notifyQueue: {},
-
- // Allow notification to the player
- notify: function(module, text, noQueue) {
- if(typeof text == 'undefined') return;
- if(text.slice(-1) != ".") text += ".";
- if(module != null && Engine.activeModule != module) {
- if(!noQueue) {
- if(typeof this.notifyQueue[module] == 'undefined') {
- this.notifyQueue[module] = [];
- }
- this.notifyQueue[module].push(text);
- }
- } else {
- Notifications.printMessage(text);
- }
- Engine.saveGame();
- },
-
- clearHidden: function() {
-
- // To fix some memory usage issues, we clear notifications that have been hidden.
-
- // We use position().top here, because we know that the parent will be the same, so the position will be the same.
- var bottom = $('#notifyGradient').position().top + $('#notifyGradient').outerHeight(true);
-
- $('.notification').each(function() {
-
- if($(this).position().top > bottom){
- $(this).remove();
- }
-
- });
-
- },
-
- printMessage: function(t) {
- var text = $('
').addClass('notification').css('opacity', '0').text(t).prependTo('div#notifications');
- text.animate({opacity: 1}, 500, 'linear', function() {
- // Do this every time we add a new message, this way we never have a large backlog to iterate through. Keeps things faster.
- Notifications.clearHidden();
- });
- },
-
- printQueue: function(module) {
- if(typeof this.notifyQueue[module] != 'undefined') {
- while(this.notifyQueue[module].length > 0) {
- Notifications.printMessage(this.notifyQueue[module].shift());
- }
- }
- }
-};
+/**
+ * Module that registers the notification box and handles messages
+ */
+var Notifications = {
+
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ // Create the notifications box
+ elem = $('
').attr({
+ id: 'notifications',
+ className: 'notifications'
+ });
+ // Create the transparency gradient
+ $('
').attr('id', 'notifyGradient').appendTo(elem);
+
+ elem.appendTo('div#wrapper');
+ },
+
+ options: {}, // Nothing for now
+
+ elem: null,
+
+ notifyQueue: {},
+
+ // Allow notification to the player
+ notify: function(module, text, noQueue) {
+ if(typeof text == 'undefined') return;
+ if(text.slice(-1) != ".") text += ".";
+ if(module != null && Engine.activeModule != module) {
+ if(!noQueue) {
+ if(typeof this.notifyQueue[module] == 'undefined') {
+ this.notifyQueue[module] = [];
+ }
+ this.notifyQueue[module].push(text);
+ }
+ } else {
+ Notifications.printMessage(text);
+ }
+ Engine.saveGame();
+ },
+
+ clearHidden: function() {
+
+ // To fix some memory usage issues, we clear notifications that have been hidden.
+
+ // We use position().top here, because we know that the parent will be the same, so the position will be the same.
+ var bottom = $('#notifyGradient').position().top + $('#notifyGradient').outerHeight(true);
+
+ $('.notification').each(function() {
+
+ if($(this).position().top > bottom){
+ $(this).remove();
+ }
+
+ });
+
+ },
+
+ printMessage: function(t) {
+ var text = $('
').addClass('notification').css('opacity', '0').text(t).prependTo('div#notifications');
+ text.animate({opacity: 1}, 500, 'linear', function() {
+ // Do this every time we add a new message, this way we never have a large backlog to iterate through. Keeps things faster.
+ Notifications.clearHidden();
+ });
+ },
+
+ printQueue: function(module) {
+ if(typeof this.notifyQueue[module] != 'undefined') {
+ while(this.notifyQueue[module].length > 0) {
+ Notifications.printMessage(this.notifyQueue[module].shift());
+ }
+ }
+ }
+};
diff --git a/script/outside.js b/script/outside.js
index f9f4690..0ee3425 100644
--- a/script/outside.js
+++ b/script/outside.js
@@ -1,615 +1,615 @@
-/**
- * Module that registers the outdoors functionality
- */
-var Outside = {
- name: _("Outside"),
-
- _GATHER_DELAY: 60,
- _TRAPS_DELAY: 90,
- _POP_DELAY: [0.5, 3],
-
- _INCOME: {
- 'gatherer': {
- name: _('gatherer'),
- delay: 10,
- stores: {
- 'wood': 1
- }
- },
- 'hunter': {
- name: _('hunter'),
- delay: 10,
- stores: {
- 'fur': 0.5,
- 'meat': 0.5
- }
- },
- 'trapper': {
- name: _('trapper'),
- delay: 10,
- stores: {
- 'meat': -1,
- 'bait': 1
- }
- },
- 'tanner': {
- name: _('tanner'),
- delay: 10,
- stores: {
- 'fur': -5,
- 'leather': 1
- }
- },
- 'charcutier': {
- name: _('charcutier'),
- delay: 10,
- stores: {
- 'meat': -5,
- 'wood': -5,
- 'cured meat': 1
- }
- },
- 'iron miner': {
- name: _('iron miner'),
- delay: 10,
- stores: {
- 'cured meat': -1,
- 'iron': 1
- }
- },
- 'coal miner': {
- name: _('coal miner'),
- delay: 10,
- stores: {
- 'cured meat': -1,
- 'coal': 1
- }
- },
- 'sulphur miner': {
- name: _('sulphur miner'),
- delay: 10,
- stores: {
- 'cured meat': -1,
- 'sulphur': 1
- }
- },
- 'steelworker': {
- name: _('steelworker'),
- delay: 10,
- stores: {
- 'iron': -1,
- 'coal': -1,
- 'steel': 1
- }
- },
- 'armourer': {
- name: _('armourer'),
- delay: 10,
- stores: {
- 'steel': -1,
- 'sulphur': -1,
- 'bullets': 1
- }
- }
- },
-
- TrapDrops: [
- {
- rollUnder: 0.5,
- name: 'fur',
- message: _('scraps of fur')
- },
- {
- rollUnder: 0.75,
- name: 'meat',
- message: _('bits of meat')
- },
- {
- rollUnder: 0.85,
- name: 'scales',
- message: _('strange scales')
- },
- {
- rollUnder: 0.93,
- name: 'teeth',
- message: _('scattered teeth')
- },
- {
- rollUnder: 0.995,
- name: 'cloth',
- message: _('tattered cloth')
- },
- {
- rollUnder: 1.0,
- name: 'charm',
- message: _('a crudely made charm')
- }
- ],
-
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- if(Engine._debug) {
- this._GATHER_DELAY = 0;
- this._TRAPS_DELAY = 0;
- }
-
- // Create the outside tab
- this.tab = Header.addLocation(_("A Silent Forest"), "outside", Outside);
-
- // Create the Outside panel
- this.panel = $('
').attr('id', "outsidePanel")
- .addClass('location')
- .appendTo('div#locationSlider');
-
- //subscribe to stateUpdates
- $.Dispatch('stateUpdate').subscribe(Outside.handleStateUpdates);
-
- if(typeof $SM.get('features.location.outside') == 'undefined') {
- $SM.set('features.location.outside', true);
- if(!$SM.get('game.buildings')) $SM.set('game.buildings', {});
- if(!$SM.get('game.population')) $SM.set('game.population', 0);
- if(!$SM.get('game.workers')) $SM.set('game.workers', {});
- }
-
- this.updateVillage();
- Outside.updateWorkersView();
-
- Engine.updateSlider();
-
- // Create the gather button
- new Button.Button({
- id: 'gatherButton',
- text: _("gather wood"),
- click: Outside.gatherWood,
- cooldown: Outside._GATHER_DELAY,
- width: '80px'
- }).appendTo('div#outsidePanel');
- },
-
- getMaxPopulation: function() {
- return $SM.get('game.buildings["hut"]', true) * 4;
- },
-
- increasePopulation: function() {
- var space = Outside.getMaxPopulation() - $SM.get('game.population');
- if(space > 0) {
- var num = Math.floor(Math.random()*(space/2) + space/2);
- if(num === 0) num = 1;
- if(num == 1) {
- Notifications.notify(null, _('a stranger arrives in the night'));
- } else if(num < 5) {
- Notifications.notify(null, _('a weathered family takes up in one of the huts.'));
- } else if(num < 10) {
- Notifications.notify(null, _('a small group arrives, all dust and bones.'));
- } else if(num < 30) {
- Notifications.notify(null, _('a convoy lurches in, equal parts worry and hope.'));
- } else {
- Notifications.notify(null, _("the town's booming. word does get around."));
- }
- Engine.log('population increased by ' + num);
- $SM.add('game.population', num);
- }
- Outside.schedulePopIncrease();
- },
-
- killVillagers: function(num) {
- $SM.add('game.population', num * -1);
- if($SM.get('game.population') < 0) {
- $SM.set('game.population', 0);
- }
- var remaining = Outside.getNumGatherers();
- if(remaining < 0) {
- var gap = -remaining;
- for(var k in $SM.get('game.workers')) {
- var numWorkers = $SM.get('game.workers["'+k+'"]');
- if(numWorkers < gap) {
- gap -= numWorkers;
- $SM.set('game.workers["'+k+'"]', 0);
- } else {
- $SM.add('game.workers["'+k+'"]', gap * -1);
- break;
- }
- }
- }
- },
-
- schedulePopIncrease: function() {
- var nextIncrease = Math.floor(Math.random()*(Outside._POP_DELAY[1] - Outside._POP_DELAY[0])) + Outside._POP_DELAY[0];
- Engine.log('next population increase scheduled in ' + nextIncrease + ' minutes');
- Outside._popTimeout = Engine.setTimeout(Outside.increasePopulation, nextIncrease * 60 * 1000);
- },
-
- updateWorkersView: function() {
- var workers = $('div#workers');
-
- // If our population is 0 and we don't already have a workers view,
- // there's nothing to do here.
- if(!workers.length && $SM.get('game.population') === 0) return;
-
- var needsAppend = false;
- if(workers.length === 0) {
- needsAppend = true;
- workers = $('
').attr('id', 'workers').css('opacity', 0);
- }
-
- var numGatherers = $SM.get('game.population');
- var gatherer = $('div#workers_row_gatherer', workers);
-
- for(var k in $SM.get('game.workers')) {
- var workerCount = $SM.get('game.workers["'+k+'"]');
- var row = $('div#workers_row_' + k.replace(' ', '-'), workers);
- if(row.length === 0) {
- row = Outside.makeWorkerRow(k, workerCount);
-
- var curPrev = null;
- workers.children().each(function(i) {
- var child = $(this);
- var cName = child.attr('id').substring(12).replace('-', ' ');
- if(cName != 'gatherer') {
- if(cName < k && (curPrev == null || cName > curPrev)) {
- curPrev = cName;
- }
- }
- });
- if(curPrev == null && gatherer.length === 0) {
- row.prependTo(workers);
- }
- else if(curPrev == null)
- {
- row.insertAfter(gatherer);
- }
- else
- {
- row.insertAfter(workers.find('#workers_row_' + curPrev.replace(' ', '-')));
- }
-
- } else {
- $('div#' + row.attr('id') + ' > div.row_val > span', workers).text(workerCount);
- }
- numGatherers -= workerCount;
- if(workerCount === 0) {
- $('.dnBtn', row).addClass('disabled');
- $('.dnManyBtn', row).addClass('disabled');
- } else {
- $('.dnBtn', row).removeClass('disabled');
- $('.dnManyBtn', row).removeClass('disabled');
- }
- }
-
- if(gatherer.length === 0) {
- gatherer = Outside.makeWorkerRow('gatherer', numGatherers);
- gatherer.prependTo(workers);
- } else {
- $('div#workers_row_gatherer > div.row_val > span', workers).text(numGatherers);
- }
-
- if(numGatherers === 0) {
- $('.upBtn', '#workers').addClass('disabled');
- $('.upManyBtn', '#workers').addClass('disabled');
- } else {
- $('.upBtn', '#workers').removeClass('disabled');
- $('.upManyBtn', '#workers').removeClass('disabled');
- }
-
-
- if(needsAppend && workers.children().length > 0) {
- workers.appendTo('#outsidePanel').animate({opacity:1}, 300, 'linear');
- }
- },
-
- getNumGatherers: function() {
- var num = $SM.get('game.population');
- for(var k in $SM.get('game.workers')) {
- num -= $SM.get('game.workers["'+k+'"]');
- }
- return num;
- },
-
- makeWorkerRow: function(key, num) {
- name = Outside._INCOME[key].name;
- if(!name) name = key;
- var row = $('
')
- .attr('key', key)
- .attr('id', 'workers_row_' + key.replace(' ','-'))
- .addClass('workerRow');
- $('
').addClass('row_key').text(name).appendTo(row);
- var val = $('
').addClass('row_val').appendTo(row);
-
- $('
').text(num).appendTo(val);
-
- if(key != 'gatherer') {
- $('').addClass('upManyBtn').appendTo(val).click([10], Outside.increaseWorker);
- $('
').addClass('upBtn').appendTo(val).click([1], Outside.increaseWorker);
- $('
').addClass('dnBtn').appendTo(val).click([1], Outside.decreaseWorker);
- $('
').addClass('dnManyBtn').appendTo(val).click([10], Outside.decreaseWorker);
- }
-
- $('
').addClass('clear').appendTo(row);
-
- var tooltip = $('
').addClass('tooltip bottom right').appendTo(row);
- var income = Outside._INCOME[key];
- for(var s in income.stores) {
- var r = $('
').addClass('storeRow');
- $('
').addClass('row_key').text(_(s)).appendTo(r);
- $('
').addClass('row_val').text(Engine.getIncomeMsg(income.stores[s], income.delay)).appendTo(r);
- r.appendTo(tooltip);
- }
-
- return row;
- },
-
- increaseWorker: function(btn) {
- var worker = $(this).closest('.workerRow').attr('key');
- if(Outside.getNumGatherers() > 0) {
- var increaseAmt = Math.min(Outside.getNumGatherers(), btn.data);
- Engine.log('increasing ' + worker + ' by ' + increaseAmt);
- $SM.add('game.workers["'+worker+'"]', increaseAmt);
- }
- },
-
- decreaseWorker: function(btn) {
- var worker = $(this).closest('.workerRow').attr('key');
- if($SM.get('game.workers["'+worker+'"]') > 0) {
- var decreaseAmt = Math.min($SM.get('game.workers["'+worker+'"]') || 0, btn.data);
- Engine.log('decreasing ' + worker + ' by ' + decreaseAmt);
- $SM.add('game.workers["'+worker+'"]', decreaseAmt * -1);
- }
- },
-
- updateVillageRow: function(name, num, village) {
- var id = 'building_row_' + name.replace(' ', '-');
- var row = $('div#' + id, village);
- if(row.length === 0 && num > 0) {
- row = $('
').attr('id', id).addClass('storeRow');
- $('
').addClass('row_key').text(_(name)).appendTo(row);
- $('
').addClass('row_val').text(num).appendTo(row);
- $('
').addClass('clear').appendTo(row);
- var curPrev = null;
- village.children().each(function(i) {
- var child = $(this);
- if(child.attr('id') != 'population') {
- var cName = child.attr('id').substring(13).replace('-', ' ');
- if(cName < name && (curPrev == null || cName > curPrev)) {
- curPrev = cName;
- }
- }
- });
- if(curPrev == null) {
- row.prependTo(village);
- } else {
- row.insertAfter('#building_row_' + curPrev.replace(' ', '-'));
- }
- } else if(num > 0) {
- $('div#' + row.attr('id') + ' > div.row_val', village).text(num);
- } else if(num === 0) {
- row.remove();
- }
- },
-
- updateVillage: function(ignoreStores) {
- var village = $('div#village');
- var population = $('div#population');
- var needsAppend = false;
- if(village.length === 0) {
- needsAppend = true;
- village = $('
').attr('id', 'village').css('opacity', 0);
- population = $('
').attr('id', 'population').appendTo(village);
- }
-
- for(var k in $SM.get('game.buildings')) {
- if(k == 'trap') {
- var numTraps = $SM.get('game.buildings["'+k+'"]');
- var numBait = $SM.get('stores.bait', true);
- var traps = numTraps - numBait;
- traps = traps < 0 ? 0 : traps;
- Outside.updateVillageRow(k, traps, village);
- Outside.updateVillageRow('baited trap', numBait > numTraps ? numTraps : numBait, village);
- } else {
- if(Outside.checkWorker(k)) {
- Outside.updateWorkersView();
- }
- Outside.updateVillageRow(k, $SM.get('game.buildings["'+k+'"]'), village);
- }
- }
- /// TRANSLATORS : pop is short for population.
- population.text(_('pop ') + $SM.get('game.population') + '/' + this.getMaxPopulation());
-
- var hasPeeps;
- if($SM.get('game.buildings["hut"]', true) === 0) {
- hasPeeps = false;
- village.addClass('noHuts');
- } else {
- hasPeeps = true;
- village.removeClass('noHuts');
- }
-
- if(needsAppend && village.children().length > 1) {
- village.appendTo('#outsidePanel');
- village.animate({opacity:1}, 300, 'linear');
- }
-
- if(hasPeeps && typeof Outside._popTimeout == 'undefined') {
- Outside.schedulePopIncrease();
- }
-
- this.setTitle();
-
- if(!ignoreStores && Engine.activeModule === Outside && village.children().length > 1) {
- $('#storesContainer').css({top: village.height() + 26 + 'px'});
- }
- },
-
- checkWorker: function(name) {
- var jobMap = {
- 'lodge': ['hunter', 'trapper'],
- 'tannery': ['tanner'],
- 'smokehouse': ['charcutier'],
- 'iron mine': ['iron miner'],
- 'coal mine': ['coal miner'],
- 'sulphur mine': ['sulphur miner'],
- 'steelworks': ['steelworker'],
- 'armoury' : ['armourer']
- };
-
- var jobs = jobMap[name];
- var added = false;
- if(typeof jobs == 'object') {
- for(var i = 0, len = jobs.length; i < len; i++) {
- var job = jobs[i];
- if(typeof $SM.get('game.buildings["'+name+'"]') == 'number' &&
- typeof $SM.get('game.workers["'+job+'"]') != 'number') {
- Engine.log('adding ' + job + ' to the workers list');
- $SM.set('game.workers["'+job+'"]', 0);
- added = true;
- }
- }
- }
- return added;
- },
-
- updateVillageIncome: function() {
- for(var worker in Outside._INCOME) {
- var income = Outside._INCOME[worker];
- var num = worker == 'gatherer' ? Outside.getNumGatherers() : $SM.get('game.workers["'+worker+'"]');
- if(typeof num == 'number') {
- var stores = {};
- if(num < 0) num = 0;
- var tooltip = $('.tooltip', 'div#workers_row_' + worker.replace(' ', '-'));
- tooltip.empty();
- var needsUpdate = false;
- var curIncome = $SM.getIncome(worker);
- for(var store in income.stores) {
- stores[store] = income.stores[store] * num;
- if(curIncome[store] != stores[store]) needsUpdate = true;
- var row = $('
').addClass('storeRow');
- $('
').addClass('row_key').text(_(store)).appendTo(row);
- $('
').addClass('row_val').text(Engine.getIncomeMsg(stores[store], income.delay)).appendTo(row);
- row.appendTo(tooltip);
- }
- if(needsUpdate) {
- $SM.setIncome(worker, {
- delay: income.delay,
- stores: stores
- });
- }
- }
- }
- Room.updateIncomeView();
- },
-
- updateTrapButton: function() {
- var btn = $('div#trapsButton');
- if($SM.get('game.buildings["trap"]', true) > 0) {
- if(btn.length === 0) {
- new Button.Button({
- id: 'trapsButton',
- text: _("check traps"),
- click: Outside.checkTraps,
- cooldown: Outside._TRAPS_DELAY,
- width: '80px'
- }).appendTo('div#outsidePanel');
- } else {
- Button.setDisabled(btn, false);
- }
- } else {
- if(btn.length > 0) {
- Button.setDisabled(btn, true);
- }
- }
- },
-
- setTitle: function() {
- var numHuts = $SM.get('game.buildings["hut"]', true);
- var title;
- if(numHuts === 0) {
- title = _("A Silent Forest");
- } else if(numHuts == 1) {
- title = _("A Lonely Hut");
- } else if(numHuts <= 4) {
- title = _("A Tiny Village");
- } else if(numHuts <= 8) {
- title = _("A Modest Village");
- } else if(numHuts <= 14) {
- title = _("A Large Village");
- } else {
- title = _("A Raucous Village");
- }
-
- if(Engine.activeModule == this) {
- document.title = title;
- }
- $('#location_outside').text(title);
- },
-
- onArrival: function(transition_diff) {
- Outside.setTitle();
- if(!$SM.get('game.outside.seenForest')) {
- Notifications.notify(Outside, _("the sky is grey and the wind blows relentlessly"));
- $SM.set('game.outside.seenForest', true);
- }
- Outside.updateTrapButton();
- Outside.updateVillage(true);
-
- Engine.moveStoresView($('#village'), transition_diff);
- },
-
- gatherWood: function() {
- Notifications.notify(Outside, _("dry brush and dead branches litter the forest floor"));
- var gatherAmt = $SM.get('game.buildings["cart"]', true) > 0 ? 50 : 10;
- $SM.add('stores.wood', gatherAmt);
- },
-
- checkTraps: function() {
- var drops = {};
- var msg = [];
- var numTraps = $SM.get('game.buildings["trap"]', true);
- var numBait = $SM.get('stores.bait', true);
- var numDrops = numTraps + (numBait < numTraps ? numBait : numTraps);
- for(var i = 0; i < numDrops; i++) {
- var roll = Math.random();
- for(var j in Outside.TrapDrops) {
- var drop = Outside.TrapDrops[j];
- if(roll < drop.rollUnder) {
- var num = drops[drop.name];
- if(typeof num == 'undefined') {
- num = 0;
- msg.push(drop.message);
- }
- drops[drop.name] = num + 1;
- break;
- }
- }
- }
- /// TRANSLATORS : Mind the whitespace at the end.
- var s = _('the traps contain ');
- for(var i = 0, len = msg.length; i < len; i++) {
- if(len > 1 && i > 0 && i < len - 1) {
- s += ", ";
- } else if(len > 1 && i == len - 1) {
- /// TRANSLATORS : Mind the whitespaces at the beginning and end.
- s += _(" and ");
- }
- s += msg[i];
- }
-
- var baitUsed = numBait < numTraps ? numBait : numTraps;
- drops['bait'] = -baitUsed;
-
- Notifications.notify(Outside, s);
- $SM.addM('stores', drops);
- },
-
- handleStateUpdates: function(e){
- if(e.category == 'stores'){
- Outside.updateVillage();
- } else if(e.stateName.indexOf('game.workers') === 0 || e.stateName.indexOf('game.population') === 0){
- Outside.updateVillage();
- Outside.updateWorkersView();
- Outside.updateVillageIncome();
- }
- }
-};
+/**
+ * Module that registers the outdoors functionality
+ */
+var Outside = {
+ name: _("Outside"),
+
+ _GATHER_DELAY: 60,
+ _TRAPS_DELAY: 90,
+ _POP_DELAY: [0.5, 3],
+
+ _INCOME: {
+ 'gatherer': {
+ name: _('gatherer'),
+ delay: 10,
+ stores: {
+ 'wood': 1
+ }
+ },
+ 'hunter': {
+ name: _('hunter'),
+ delay: 10,
+ stores: {
+ 'fur': 0.5,
+ 'meat': 0.5
+ }
+ },
+ 'trapper': {
+ name: _('trapper'),
+ delay: 10,
+ stores: {
+ 'meat': -1,
+ 'bait': 1
+ }
+ },
+ 'tanner': {
+ name: _('tanner'),
+ delay: 10,
+ stores: {
+ 'fur': -5,
+ 'leather': 1
+ }
+ },
+ 'charcutier': {
+ name: _('charcutier'),
+ delay: 10,
+ stores: {
+ 'meat': -5,
+ 'wood': -5,
+ 'cured meat': 1
+ }
+ },
+ 'iron miner': {
+ name: _('iron miner'),
+ delay: 10,
+ stores: {
+ 'cured meat': -1,
+ 'iron': 1
+ }
+ },
+ 'coal miner': {
+ name: _('coal miner'),
+ delay: 10,
+ stores: {
+ 'cured meat': -1,
+ 'coal': 1
+ }
+ },
+ 'sulphur miner': {
+ name: _('sulphur miner'),
+ delay: 10,
+ stores: {
+ 'cured meat': -1,
+ 'sulphur': 1
+ }
+ },
+ 'steelworker': {
+ name: _('steelworker'),
+ delay: 10,
+ stores: {
+ 'iron': -1,
+ 'coal': -1,
+ 'steel': 1
+ }
+ },
+ 'armourer': {
+ name: _('armourer'),
+ delay: 10,
+ stores: {
+ 'steel': -1,
+ 'sulphur': -1,
+ 'bullets': 1
+ }
+ }
+ },
+
+ TrapDrops: [
+ {
+ rollUnder: 0.5,
+ name: 'fur',
+ message: _('scraps of fur')
+ },
+ {
+ rollUnder: 0.75,
+ name: 'meat',
+ message: _('bits of meat')
+ },
+ {
+ rollUnder: 0.85,
+ name: 'scales',
+ message: _('strange scales')
+ },
+ {
+ rollUnder: 0.93,
+ name: 'teeth',
+ message: _('scattered teeth')
+ },
+ {
+ rollUnder: 0.995,
+ name: 'cloth',
+ message: _('tattered cloth')
+ },
+ {
+ rollUnder: 1.0,
+ name: 'charm',
+ message: _('a crudely made charm')
+ }
+ ],
+
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ if(Engine._debug) {
+ this._GATHER_DELAY = 0;
+ this._TRAPS_DELAY = 0;
+ }
+
+ // Create the outside tab
+ this.tab = Header.addLocation(_("A Silent Forest"), "outside", Outside);
+
+ // Create the Outside panel
+ this.panel = $('
').attr('id', "outsidePanel")
+ .addClass('location')
+ .appendTo('div#locationSlider');
+
+ //subscribe to stateUpdates
+ $.Dispatch('stateUpdate').subscribe(Outside.handleStateUpdates);
+
+ if(typeof $SM.get('features.location.outside') == 'undefined') {
+ $SM.set('features.location.outside', true);
+ if(!$SM.get('game.buildings')) $SM.set('game.buildings', {});
+ if(!$SM.get('game.population')) $SM.set('game.population', 0);
+ if(!$SM.get('game.workers')) $SM.set('game.workers', {});
+ }
+
+ this.updateVillage();
+ Outside.updateWorkersView();
+
+ Engine.updateSlider();
+
+ // Create the gather button
+ new Button.Button({
+ id: 'gatherButton',
+ text: _("gather wood"),
+ click: Outside.gatherWood,
+ cooldown: Outside._GATHER_DELAY,
+ width: '80px'
+ }).appendTo('div#outsidePanel');
+ },
+
+ getMaxPopulation: function() {
+ return $SM.get('game.buildings["hut"]', true) * 4;
+ },
+
+ increasePopulation: function() {
+ var space = Outside.getMaxPopulation() - $SM.get('game.population');
+ if(space > 0) {
+ var num = Math.floor(Math.random()*(space/2) + space/2);
+ if(num === 0) num = 1;
+ if(num == 1) {
+ Notifications.notify(null, _('a stranger arrives in the night'));
+ } else if(num < 5) {
+ Notifications.notify(null, _('a weathered family takes up in one of the huts.'));
+ } else if(num < 10) {
+ Notifications.notify(null, _('a small group arrives, all dust and bones.'));
+ } else if(num < 30) {
+ Notifications.notify(null, _('a convoy lurches in, equal parts worry and hope.'));
+ } else {
+ Notifications.notify(null, _("the town's booming. word does get around."));
+ }
+ Engine.log('population increased by ' + num);
+ $SM.add('game.population', num);
+ }
+ Outside.schedulePopIncrease();
+ },
+
+ killVillagers: function(num) {
+ $SM.add('game.population', num * -1);
+ if($SM.get('game.population') < 0) {
+ $SM.set('game.population', 0);
+ }
+ var remaining = Outside.getNumGatherers();
+ if(remaining < 0) {
+ var gap = -remaining;
+ for(var k in $SM.get('game.workers')) {
+ var numWorkers = $SM.get('game.workers["'+k+'"]');
+ if(numWorkers < gap) {
+ gap -= numWorkers;
+ $SM.set('game.workers["'+k+'"]', 0);
+ } else {
+ $SM.add('game.workers["'+k+'"]', gap * -1);
+ break;
+ }
+ }
+ }
+ },
+
+ schedulePopIncrease: function() {
+ var nextIncrease = Math.floor(Math.random()*(Outside._POP_DELAY[1] - Outside._POP_DELAY[0])) + Outside._POP_DELAY[0];
+ Engine.log('next population increase scheduled in ' + nextIncrease + ' minutes');
+ Outside._popTimeout = Engine.setTimeout(Outside.increasePopulation, nextIncrease * 60 * 1000);
+ },
+
+ updateWorkersView: function() {
+ var workers = $('div#workers');
+
+ // If our population is 0 and we don't already have a workers view,
+ // there's nothing to do here.
+ if(!workers.length && $SM.get('game.population') === 0) return;
+
+ var needsAppend = false;
+ if(workers.length === 0) {
+ needsAppend = true;
+ workers = $('
').attr('id', 'workers').css('opacity', 0);
+ }
+
+ var numGatherers = $SM.get('game.population');
+ var gatherer = $('div#workers_row_gatherer', workers);
+
+ for(var k in $SM.get('game.workers')) {
+ var workerCount = $SM.get('game.workers["'+k+'"]');
+ var row = $('div#workers_row_' + k.replace(' ', '-'), workers);
+ if(row.length === 0) {
+ row = Outside.makeWorkerRow(k, workerCount);
+
+ var curPrev = null;
+ workers.children().each(function(i) {
+ var child = $(this);
+ var cName = child.attr('id').substring(12).replace('-', ' ');
+ if(cName != 'gatherer') {
+ if(cName < k && (curPrev == null || cName > curPrev)) {
+ curPrev = cName;
+ }
+ }
+ });
+ if(curPrev == null && gatherer.length === 0) {
+ row.prependTo(workers);
+ }
+ else if(curPrev == null)
+ {
+ row.insertAfter(gatherer);
+ }
+ else
+ {
+ row.insertAfter(workers.find('#workers_row_' + curPrev.replace(' ', '-')));
+ }
+
+ } else {
+ $('div#' + row.attr('id') + ' > div.row_val > span', workers).text(workerCount);
+ }
+ numGatherers -= workerCount;
+ if(workerCount === 0) {
+ $('.dnBtn', row).addClass('disabled');
+ $('.dnManyBtn', row).addClass('disabled');
+ } else {
+ $('.dnBtn', row).removeClass('disabled');
+ $('.dnManyBtn', row).removeClass('disabled');
+ }
+ }
+
+ if(gatherer.length === 0) {
+ gatherer = Outside.makeWorkerRow('gatherer', numGatherers);
+ gatherer.prependTo(workers);
+ } else {
+ $('div#workers_row_gatherer > div.row_val > span', workers).text(numGatherers);
+ }
+
+ if(numGatherers === 0) {
+ $('.upBtn', '#workers').addClass('disabled');
+ $('.upManyBtn', '#workers').addClass('disabled');
+ } else {
+ $('.upBtn', '#workers').removeClass('disabled');
+ $('.upManyBtn', '#workers').removeClass('disabled');
+ }
+
+
+ if(needsAppend && workers.children().length > 0) {
+ workers.appendTo('#outsidePanel').animate({opacity:1}, 300, 'linear');
+ }
+ },
+
+ getNumGatherers: function() {
+ var num = $SM.get('game.population');
+ for(var k in $SM.get('game.workers')) {
+ num -= $SM.get('game.workers["'+k+'"]');
+ }
+ return num;
+ },
+
+ makeWorkerRow: function(key, num) {
+ name = Outside._INCOME[key].name;
+ if(!name) name = key;
+ var row = $('
')
+ .attr('key', key)
+ .attr('id', 'workers_row_' + key.replace(' ','-'))
+ .addClass('workerRow');
+ $('
').addClass('row_key').text(name).appendTo(row);
+ var val = $('
').addClass('row_val').appendTo(row);
+
+ $('
').text(num).appendTo(val);
+
+ if(key != 'gatherer') {
+ $('').addClass('upManyBtn').appendTo(val).click([10], Outside.increaseWorker);
+ $('
').addClass('upBtn').appendTo(val).click([1], Outside.increaseWorker);
+ $('
').addClass('dnBtn').appendTo(val).click([1], Outside.decreaseWorker);
+ $('
').addClass('dnManyBtn').appendTo(val).click([10], Outside.decreaseWorker);
+ }
+
+ $('
').addClass('clear').appendTo(row);
+
+ var tooltip = $('
').addClass('tooltip bottom right').appendTo(row);
+ var income = Outside._INCOME[key];
+ for(var s in income.stores) {
+ var r = $('
').addClass('storeRow');
+ $('
').addClass('row_key').text(_(s)).appendTo(r);
+ $('
').addClass('row_val').text(Engine.getIncomeMsg(income.stores[s], income.delay)).appendTo(r);
+ r.appendTo(tooltip);
+ }
+
+ return row;
+ },
+
+ increaseWorker: function(btn) {
+ var worker = $(this).closest('.workerRow').attr('key');
+ if(Outside.getNumGatherers() > 0) {
+ var increaseAmt = Math.min(Outside.getNumGatherers(), btn.data);
+ Engine.log('increasing ' + worker + ' by ' + increaseAmt);
+ $SM.add('game.workers["'+worker+'"]', increaseAmt);
+ }
+ },
+
+ decreaseWorker: function(btn) {
+ var worker = $(this).closest('.workerRow').attr('key');
+ if($SM.get('game.workers["'+worker+'"]') > 0) {
+ var decreaseAmt = Math.min($SM.get('game.workers["'+worker+'"]') || 0, btn.data);
+ Engine.log('decreasing ' + worker + ' by ' + decreaseAmt);
+ $SM.add('game.workers["'+worker+'"]', decreaseAmt * -1);
+ }
+ },
+
+ updateVillageRow: function(name, num, village) {
+ var id = 'building_row_' + name.replace(' ', '-');
+ var row = $('div#' + id, village);
+ if(row.length === 0 && num > 0) {
+ row = $('
').attr('id', id).addClass('storeRow');
+ $('
').addClass('row_key').text(_(name)).appendTo(row);
+ $('
').addClass('row_val').text(num).appendTo(row);
+ $('
').addClass('clear').appendTo(row);
+ var curPrev = null;
+ village.children().each(function(i) {
+ var child = $(this);
+ if(child.attr('id') != 'population') {
+ var cName = child.attr('id').substring(13).replace('-', ' ');
+ if(cName < name && (curPrev == null || cName > curPrev)) {
+ curPrev = cName;
+ }
+ }
+ });
+ if(curPrev == null) {
+ row.prependTo(village);
+ } else {
+ row.insertAfter('#building_row_' + curPrev.replace(' ', '-'));
+ }
+ } else if(num > 0) {
+ $('div#' + row.attr('id') + ' > div.row_val', village).text(num);
+ } else if(num === 0) {
+ row.remove();
+ }
+ },
+
+ updateVillage: function(ignoreStores) {
+ var village = $('div#village');
+ var population = $('div#population');
+ var needsAppend = false;
+ if(village.length === 0) {
+ needsAppend = true;
+ village = $('
').attr('id', 'village').css('opacity', 0);
+ population = $('
').attr('id', 'population').appendTo(village);
+ }
+
+ for(var k in $SM.get('game.buildings')) {
+ if(k == 'trap') {
+ var numTraps = $SM.get('game.buildings["'+k+'"]');
+ var numBait = $SM.get('stores.bait', true);
+ var traps = numTraps - numBait;
+ traps = traps < 0 ? 0 : traps;
+ Outside.updateVillageRow(k, traps, village);
+ Outside.updateVillageRow('baited trap', numBait > numTraps ? numTraps : numBait, village);
+ } else {
+ if(Outside.checkWorker(k)) {
+ Outside.updateWorkersView();
+ }
+ Outside.updateVillageRow(k, $SM.get('game.buildings["'+k+'"]'), village);
+ }
+ }
+ /// TRANSLATORS : pop is short for population.
+ population.text(_('pop ') + $SM.get('game.population') + '/' + this.getMaxPopulation());
+
+ var hasPeeps;
+ if($SM.get('game.buildings["hut"]', true) === 0) {
+ hasPeeps = false;
+ village.addClass('noHuts');
+ } else {
+ hasPeeps = true;
+ village.removeClass('noHuts');
+ }
+
+ if(needsAppend && village.children().length > 1) {
+ village.appendTo('#outsidePanel');
+ village.animate({opacity:1}, 300, 'linear');
+ }
+
+ if(hasPeeps && typeof Outside._popTimeout == 'undefined') {
+ Outside.schedulePopIncrease();
+ }
+
+ this.setTitle();
+
+ if(!ignoreStores && Engine.activeModule === Outside && village.children().length > 1) {
+ $('#storesContainer').css({top: village.height() + 26 + 'px'});
+ }
+ },
+
+ checkWorker: function(name) {
+ var jobMap = {
+ 'lodge': ['hunter', 'trapper'],
+ 'tannery': ['tanner'],
+ 'smokehouse': ['charcutier'],
+ 'iron mine': ['iron miner'],
+ 'coal mine': ['coal miner'],
+ 'sulphur mine': ['sulphur miner'],
+ 'steelworks': ['steelworker'],
+ 'armoury' : ['armourer']
+ };
+
+ var jobs = jobMap[name];
+ var added = false;
+ if(typeof jobs == 'object') {
+ for(var i = 0, len = jobs.length; i < len; i++) {
+ var job = jobs[i];
+ if(typeof $SM.get('game.buildings["'+name+'"]') == 'number' &&
+ typeof $SM.get('game.workers["'+job+'"]') != 'number') {
+ Engine.log('adding ' + job + ' to the workers list');
+ $SM.set('game.workers["'+job+'"]', 0);
+ added = true;
+ }
+ }
+ }
+ return added;
+ },
+
+ updateVillageIncome: function() {
+ for(var worker in Outside._INCOME) {
+ var income = Outside._INCOME[worker];
+ var num = worker == 'gatherer' ? Outside.getNumGatherers() : $SM.get('game.workers["'+worker+'"]');
+ if(typeof num == 'number') {
+ var stores = {};
+ if(num < 0) num = 0;
+ var tooltip = $('.tooltip', 'div#workers_row_' + worker.replace(' ', '-'));
+ tooltip.empty();
+ var needsUpdate = false;
+ var curIncome = $SM.getIncome(worker);
+ for(var store in income.stores) {
+ stores[store] = income.stores[store] * num;
+ if(curIncome[store] != stores[store]) needsUpdate = true;
+ var row = $('
').addClass('storeRow');
+ $('
').addClass('row_key').text(_(store)).appendTo(row);
+ $('
').addClass('row_val').text(Engine.getIncomeMsg(stores[store], income.delay)).appendTo(row);
+ row.appendTo(tooltip);
+ }
+ if(needsUpdate) {
+ $SM.setIncome(worker, {
+ delay: income.delay,
+ stores: stores
+ });
+ }
+ }
+ }
+ Room.updateIncomeView();
+ },
+
+ updateTrapButton: function() {
+ var btn = $('div#trapsButton');
+ if($SM.get('game.buildings["trap"]', true) > 0) {
+ if(btn.length === 0) {
+ new Button.Button({
+ id: 'trapsButton',
+ text: _("check traps"),
+ click: Outside.checkTraps,
+ cooldown: Outside._TRAPS_DELAY,
+ width: '80px'
+ }).appendTo('div#outsidePanel');
+ } else {
+ Button.setDisabled(btn, false);
+ }
+ } else {
+ if(btn.length > 0) {
+ Button.setDisabled(btn, true);
+ }
+ }
+ },
+
+ setTitle: function() {
+ var numHuts = $SM.get('game.buildings["hut"]', true);
+ var title;
+ if(numHuts === 0) {
+ title = _("A Silent Forest");
+ } else if(numHuts == 1) {
+ title = _("A Lonely Hut");
+ } else if(numHuts <= 4) {
+ title = _("A Tiny Village");
+ } else if(numHuts <= 8) {
+ title = _("A Modest Village");
+ } else if(numHuts <= 14) {
+ title = _("A Large Village");
+ } else {
+ title = _("A Raucous Village");
+ }
+
+ if(Engine.activeModule == this) {
+ document.title = title;
+ }
+ $('#location_outside').text(title);
+ },
+
+ onArrival: function(transition_diff) {
+ Outside.setTitle();
+ if(!$SM.get('game.outside.seenForest')) {
+ Notifications.notify(Outside, _("the sky is grey and the wind blows relentlessly"));
+ $SM.set('game.outside.seenForest', true);
+ }
+ Outside.updateTrapButton();
+ Outside.updateVillage(true);
+
+ Engine.moveStoresView($('#village'), transition_diff);
+ },
+
+ gatherWood: function() {
+ Notifications.notify(Outside, _("dry brush and dead branches litter the forest floor"));
+ var gatherAmt = $SM.get('game.buildings["cart"]', true) > 0 ? 50 : 10;
+ $SM.add('stores.wood', gatherAmt);
+ },
+
+ checkTraps: function() {
+ var drops = {};
+ var msg = [];
+ var numTraps = $SM.get('game.buildings["trap"]', true);
+ var numBait = $SM.get('stores.bait', true);
+ var numDrops = numTraps + (numBait < numTraps ? numBait : numTraps);
+ for(var i = 0; i < numDrops; i++) {
+ var roll = Math.random();
+ for(var j in Outside.TrapDrops) {
+ var drop = Outside.TrapDrops[j];
+ if(roll < drop.rollUnder) {
+ var num = drops[drop.name];
+ if(typeof num == 'undefined') {
+ num = 0;
+ msg.push(drop.message);
+ }
+ drops[drop.name] = num + 1;
+ break;
+ }
+ }
+ }
+ /// TRANSLATORS : Mind the whitespace at the end.
+ var s = _('the traps contain ');
+ for(var i = 0, len = msg.length; i < len; i++) {
+ if(len > 1 && i > 0 && i < len - 1) {
+ s += ", ";
+ } else if(len > 1 && i == len - 1) {
+ /// TRANSLATORS : Mind the whitespaces at the beginning and end.
+ s += _(" and ");
+ }
+ s += msg[i];
+ }
+
+ var baitUsed = numBait < numTraps ? numBait : numTraps;
+ drops['bait'] = -baitUsed;
+
+ Notifications.notify(Outside, s);
+ $SM.addM('stores', drops);
+ },
+
+ handleStateUpdates: function(e){
+ if(e.category == 'stores'){
+ Outside.updateVillage();
+ } else if(e.stateName.indexOf('game.workers') === 0 || e.stateName.indexOf('game.population') === 0){
+ Outside.updateVillage();
+ Outside.updateWorkersView();
+ Outside.updateVillageIncome();
+ }
+ }
+};
diff --git a/script/path.js b/script/path.js
index 1c1c05f..bb73f09 100644
--- a/script/path.js
+++ b/script/path.js
@@ -1,317 +1,317 @@
-var Path = {
-
- DEFAULT_BAG_SPACE: 10,
-
- // Everything not in this list weighs 1
- Weight: {
- 'bone spear': 2,
- 'iron sword': 3,
- 'steel sword': 5,
- 'rifle': 5,
- 'bullets': 0.1,
- 'energy cell': 0.2,
- 'laser rifle': 5,
- 'bolas': 0.5
- },
-
- name: 'Path',
- options: {}, // Nuthin'
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- // Init the World
- World.init();
-
- // Create the path tab
- this.tab = Header.addLocation(_("A Dusty Path"), "path", Path);
-
- // Create the Path panel
- this.panel = $('
').attr('id', "pathPanel")
- .addClass('location')
- .appendTo('div#locationSlider');
-
- // Add the outfitting area
- var outfitting = $('
').attr('id', 'outfitting').appendTo(this.panel);
- $('
').attr('id', 'bagspace').appendTo(outfitting);
-
- // Add the embark button
- new Button.Button({
- id: 'embarkButton',
- text: _("embark"),
- click: Path.embark,
- width: '80px',
- cooldown: World.DEATH_COOLDOWN
- }).appendTo(this.panel);
-
- Path.outfit = $SM.get('outfit');
-
- Engine.updateSlider();
-
- //subscribe to stateUpdates
- $.Dispatch('stateUpdate').subscribe(Path.handleStateUpdates);
- },
-
- openPath: function() {
- Path.init();
- Engine.event('progress', 'path');
- Notifications.notify(Room, _('the compass points ' + World.dir));
- },
-
- getWeight: function(thing) {
- var w = Path.Weight[thing];
- if(typeof w != 'number') w = 1;
-
- return w;
- },
-
- getCapacity: function() {
- if($SM.get('stores.convoy', true) > 0) {
- return Path.DEFAULT_BAG_SPACE + 60;
- } else if($SM.get('stores.wagon', true) > 0) {
- return Path.DEFAULT_BAG_SPACE + 30;
- } else if($SM.get('stores.rucksack', true) > 0) {
- return Path.DEFAULT_BAG_SPACE + 10;
- }
- return Path.DEFAULT_BAG_SPACE;
- },
-
- getFreeSpace: function() {
- var num = 0;
- if(Path.outfit) {
- for(var k in Path.outfit) {
- var n = Path.outfit[k];
- if(isNaN(n)) {
- // No idea how this happens, but I will fix it here!
- Path.outfit[k] = n = 0;
- }
- num += n * Path.getWeight(k);
- }
- }
- return Path.getCapacity() - num;
- },
-
- updatePerks: function(ignoreStores) {
- 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 $SM.get('character.perks')) {
- var id = 'perk_' + k.replace(' ', '-');
- var r = $('#' + id);
- 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);
- }
- }
-
- if(needsAppend && perks.children().length > 0) {
- perks.appendTo(Path.panel);
- }
-
- if(!ignoreStores && Engine.activeModule === Path) {
- $('#storesContainer').css({top: perks.height() + 26 + 'px'});
- }
- }
- },
-
- updateOutfitting: function() {
- var outfit = $('div#outfitting');
-
- if(!Path.outfit) {
- Path.outfit = {};
- }
-
- // Add the armour row
- var armour = _("none");
- if($SM.get('stores["s armour"]', true) > 0)
- armour = _("steel");
- else if($SM.get('stores["i armour"]', true) > 0)
- armour = _("iron");
- else if($SM.get('stores["l armour"]', true) > 0)
- armour = _("leather");
- var aRow = $('#armourRow');
- if(aRow.length === 0) {
- aRow = $('
').attr('id', 'armourRow').addClass('outfitRow').prependTo(outfit);
- $('
').addClass('row_key').text(_('armour')).appendTo(aRow);
- $('
').addClass('row_val').text(armour).appendTo(aRow);
- $('
').addClass('clear').appendTo(aRow);
- } else {
- $('.row_val', aRow).text(armour);
- }
-
- // Add the water row
- var wRow = $('#waterRow');
- if(wRow.length === 0) {
- wRow = $('
').attr('id', 'waterRow').addClass('outfitRow').insertAfter(aRow);
- $('
').addClass('row_key').text(_('water')).appendTo(wRow);
- $('
').addClass('row_val').text(World.getMaxWater()).appendTo(wRow);
- $('
').addClass('clear').appendTo(wRow);
- } else {
- $('.row_val', wRow).text(World.getMaxWater());
- }
-
-
- var space = Path.getFreeSpace();
- var total = 0;
- // Add the non-craftables to the craftables
- var carryable = $.extend({
- 'cured meat': { type: 'tool' },
- 'bullets': { type: 'tool' },
- 'grenade': {type: 'weapon' },
- 'bolas': {type: 'weapon' },
- 'laser rifle': {type: 'weapon' },
- 'energy cell': {type: 'tool' },
- 'bayonet': {type: 'weapon' },
- 'charm': {type: 'tool'},
- 'medicine': {type: 'tool'}
- }, Room.Craftables);
-
- for(var k in carryable) {
- var store = carryable[k];
- var have = $SM.get('stores["'+k+'"]');
- var num = Path.outfit[k];
- num = typeof num == 'number' ? num : 0;
- if (have < num) { num = have; }
- var numAvailable = $SM.get('stores["'+k+'"]', true);
- var row = $('div#outfit_row_' + k.replace(' ', '-'), outfit);
- if((store.type == 'tool' || store.type == 'weapon') && have > 0) {
- total += num * Path.getWeight(k);
- if(row.length === 0) {
- row = Path.createOutfittingRow(k, num, store.name);
-
- var curPrev = null;
- outfit.children().each(function(i) {
- var child = $(this);
- if(child.attr('id').indexOf('outfit_row_') === 0) {
- var cName = child.attr('id').substring(11).replace('-', ' ');
- if(cName < k && (curPrev == null || cName > curPrev)) {
- curPrev = cName;
- }
- }
- });
- if(curPrev == null) {
- row.insertAfter(wRow);
- }
- else
- {
- row.insertAfter(outfit.find('#outfit_row_' + curPrev.replace(' ', '-')));
- }
- } else {
- $('div#' + row.attr('id') + ' > div.row_val > span', outfit).text(num);
- $('div#' + row.attr('id') + ' .tooltip .numAvailable', outfit).text(numAvailable - num);
- }
- if(num === 0) {
- $('.dnBtn', row).addClass('disabled');
- $('.dnManyBtn', row).addClass('disabled');
- } else {
- $('.dnBtn', row).removeClass('disabled');
- $('.dnManyBtn', row).removeClass('disabled');
- }
- if(num >= numAvailable || space < Path.getWeight(k)) {
- $('.upBtn', row).addClass('disabled');
- $('.upManyBtn', row).addClass('disabled');
- } else if(space >= Path.getWeight(k)) {
- $('.upBtn', row).removeClass('disabled');
- $('.upManyBtn', row).removeClass('disabled');
- }
- } else if(have === 0 && row.length > 0) {
- row.remove();
- }
- }
-
- // Update bagspace
- $('#bagspace').text(_('free {0}/{1}', Math.floor(Path.getCapacity() - total) , Path.getCapacity()));
-
- if(Path.outfit['cured meat'] > 0) {
- Button.setDisabled($('#embarkButton'), false);
- } else {
- Button.setDisabled($('#embarkButton'), true);
- }
- },
-
- createOutfittingRow: function(key, num, name) {
- if(!name) name = _(key);
- var row = $('
').attr('id', 'outfit_row_' + key.replace(' ', '-')).addClass('outfitRow').attr('key',key);
- $('
').addClass('row_key').text(name).appendTo(row);
- var val = $('
').addClass('row_val').appendTo(row);
-
- $('
').text(num).appendTo(val);
- $('').addClass('upBtn').appendTo(val).click([1], Path.increaseSupply);
- $('
').addClass('dnBtn').appendTo(val).click([1], Path.decreaseSupply);
- $('
').addClass('upManyBtn').appendTo(val).click([10], Path.increaseSupply);
- $('
').addClass('dnManyBtn').appendTo(val).click([10], Path.decreaseSupply);
- $('
').addClass('clear').appendTo(row);
-
- var numAvailable = $SM.get('stores["'+key+'"]', true);
- var tt = $('
').addClass('tooltip bottom right').appendTo(row);
- $('
').addClass('row_key').text(_('weight')).appendTo(tt);
- $('
').addClass('row_val').text(Path.getWeight(key)).appendTo(tt);
- $('
').addClass('row_key').text(_('available')).appendTo(tt);
- $('
').addClass('row_val').addClass('numAvailable').text(numAvailable).appendTo(tt);
-
- return row;
- },
-
- increaseSupply: function(btn) {
- var supply = $(this).closest('.outfitRow').attr('key');
- Engine.log('increasing ' + supply + ' by up to ' + btn.data);
- var cur = Path.outfit[supply];
- cur = typeof cur == 'number' ? cur : 0;
- if(Path.getFreeSpace() >= Path.getWeight(supply) && cur < $SM.get('stores["'+supply+'"]', true)) {
- var maxExtraByWeight = Math.floor(Path.getFreeSpace() / Path.getWeight(supply));
- var maxExtraByStore = $SM.get('stores["'+supply+'"]', true) - cur;
- var maxExtraByBtn = btn.data;
- Path.outfit[supply] = cur + Math.min(maxExtraByBtn, Math.min(maxExtraByWeight, maxExtraByStore));
- $SM.set('outfit['+supply+']', Path.outfit[supply]);
- Path.updateOutfitting();
- }
- },
-
- decreaseSupply: function(btn) {
- var supply = $(this).closest('.outfitRow').attr('key');
- Engine.log('decreasing ' + supply + ' by up to ' + btn.data);
- var cur = Path.outfit[supply];
- cur = typeof cur == 'number' ? cur : 0;
- if(cur > 0) {
- Path.outfit[supply] = Math.max(0, cur - btn.data);
- $SM.set('outfit['+supply+']', Path.outfit[supply]);
- Path.updateOutfitting();
- }
- },
-
- onArrival: function(transition_diff) {
- Path.setTitle();
- Path.updateOutfitting();
- Path.updatePerks(true);
- $SM.set('outfit', Path.outfit);
-
- Engine.moveStoresView($('#perks'), transition_diff);
- },
-
- setTitle: function() {
- document.title = _('A Dusty Path');
- },
-
- embark: function() {
- for(var k in Path.outfit) {
- $SM.add('stores["'+k+'"]', -Path.outfit[k]);
- }
- $SM.remove('outfit');
- World.onArrival();
- $('#outerSlider').animate({left: '-700px'}, 300);
- Engine.activeModule = World;
- },
-
- handleStateUpdates: function(e){
- if(e.category == 'character' && e.stateName.indexOf('character.perks') === 0 && Engine.activeModule == Path){
- Path.updatePerks();
- }
- }
-};
+var Path = {
+
+ DEFAULT_BAG_SPACE: 10,
+
+ // Everything not in this list weighs 1
+ Weight: {
+ 'bone spear': 2,
+ 'iron sword': 3,
+ 'steel sword': 5,
+ 'rifle': 5,
+ 'bullets': 0.1,
+ 'energy cell': 0.2,
+ 'laser rifle': 5,
+ 'bolas': 0.5
+ },
+
+ name: 'Path',
+ options: {}, // Nuthin'
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ // Init the World
+ World.init();
+
+ // Create the path tab
+ this.tab = Header.addLocation(_("A Dusty Path"), "path", Path);
+
+ // Create the Path panel
+ this.panel = $('
').attr('id', "pathPanel")
+ .addClass('location')
+ .appendTo('div#locationSlider');
+
+ // Add the outfitting area
+ var outfitting = $('
').attr('id', 'outfitting').appendTo(this.panel);
+ $('
').attr('id', 'bagspace').appendTo(outfitting);
+
+ // Add the embark button
+ new Button.Button({
+ id: 'embarkButton',
+ text: _("embark"),
+ click: Path.embark,
+ width: '80px',
+ cooldown: World.DEATH_COOLDOWN
+ }).appendTo(this.panel);
+
+ Path.outfit = $SM.get('outfit');
+
+ Engine.updateSlider();
+
+ //subscribe to stateUpdates
+ $.Dispatch('stateUpdate').subscribe(Path.handleStateUpdates);
+ },
+
+ openPath: function() {
+ Path.init();
+ Engine.event('progress', 'path');
+ Notifications.notify(Room, _('the compass points ' + World.dir));
+ },
+
+ getWeight: function(thing) {
+ var w = Path.Weight[thing];
+ if(typeof w != 'number') w = 1;
+
+ return w;
+ },
+
+ getCapacity: function() {
+ if($SM.get('stores.convoy', true) > 0) {
+ return Path.DEFAULT_BAG_SPACE + 60;
+ } else if($SM.get('stores.wagon', true) > 0) {
+ return Path.DEFAULT_BAG_SPACE + 30;
+ } else if($SM.get('stores.rucksack', true) > 0) {
+ return Path.DEFAULT_BAG_SPACE + 10;
+ }
+ return Path.DEFAULT_BAG_SPACE;
+ },
+
+ getFreeSpace: function() {
+ var num = 0;
+ if(Path.outfit) {
+ for(var k in Path.outfit) {
+ var n = Path.outfit[k];
+ if(isNaN(n)) {
+ // No idea how this happens, but I will fix it here!
+ Path.outfit[k] = n = 0;
+ }
+ num += n * Path.getWeight(k);
+ }
+ }
+ return Path.getCapacity() - num;
+ },
+
+ updatePerks: function(ignoreStores) {
+ 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 $SM.get('character.perks')) {
+ var id = 'perk_' + k.replace(' ', '-');
+ var r = $('#' + id);
+ 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);
+ }
+ }
+
+ if(needsAppend && perks.children().length > 0) {
+ perks.appendTo(Path.panel);
+ }
+
+ if(!ignoreStores && Engine.activeModule === Path) {
+ $('#storesContainer').css({top: perks.height() + 26 + 'px'});
+ }
+ }
+ },
+
+ updateOutfitting: function() {
+ var outfit = $('div#outfitting');
+
+ if(!Path.outfit) {
+ Path.outfit = {};
+ }
+
+ // Add the armour row
+ var armour = _("none");
+ if($SM.get('stores["s armour"]', true) > 0)
+ armour = _("steel");
+ else if($SM.get('stores["i armour"]', true) > 0)
+ armour = _("iron");
+ else if($SM.get('stores["l armour"]', true) > 0)
+ armour = _("leather");
+ var aRow = $('#armourRow');
+ if(aRow.length === 0) {
+ aRow = $('
').attr('id', 'armourRow').addClass('outfitRow').prependTo(outfit);
+ $('
').addClass('row_key').text(_('armour')).appendTo(aRow);
+ $('
').addClass('row_val').text(armour).appendTo(aRow);
+ $('
').addClass('clear').appendTo(aRow);
+ } else {
+ $('.row_val', aRow).text(armour);
+ }
+
+ // Add the water row
+ var wRow = $('#waterRow');
+ if(wRow.length === 0) {
+ wRow = $('
').attr('id', 'waterRow').addClass('outfitRow').insertAfter(aRow);
+ $('
').addClass('row_key').text(_('water')).appendTo(wRow);
+ $('
').addClass('row_val').text(World.getMaxWater()).appendTo(wRow);
+ $('
').addClass('clear').appendTo(wRow);
+ } else {
+ $('.row_val', wRow).text(World.getMaxWater());
+ }
+
+
+ var space = Path.getFreeSpace();
+ var total = 0;
+ // Add the non-craftables to the craftables
+ var carryable = $.extend({
+ 'cured meat': { type: 'tool' },
+ 'bullets': { type: 'tool' },
+ 'grenade': {type: 'weapon' },
+ 'bolas': {type: 'weapon' },
+ 'laser rifle': {type: 'weapon' },
+ 'energy cell': {type: 'tool' },
+ 'bayonet': {type: 'weapon' },
+ 'charm': {type: 'tool'},
+ 'medicine': {type: 'tool'}
+ }, Room.Craftables);
+
+ for(var k in carryable) {
+ var store = carryable[k];
+ var have = $SM.get('stores["'+k+'"]');
+ var num = Path.outfit[k];
+ num = typeof num == 'number' ? num : 0;
+ if (have < num) { num = have; }
+ var numAvailable = $SM.get('stores["'+k+'"]', true);
+ var row = $('div#outfit_row_' + k.replace(' ', '-'), outfit);
+ if((store.type == 'tool' || store.type == 'weapon') && have > 0) {
+ total += num * Path.getWeight(k);
+ if(row.length === 0) {
+ row = Path.createOutfittingRow(k, num, store.name);
+
+ var curPrev = null;
+ outfit.children().each(function(i) {
+ var child = $(this);
+ if(child.attr('id').indexOf('outfit_row_') === 0) {
+ var cName = child.attr('id').substring(11).replace('-', ' ');
+ if(cName < k && (curPrev == null || cName > curPrev)) {
+ curPrev = cName;
+ }
+ }
+ });
+ if(curPrev == null) {
+ row.insertAfter(wRow);
+ }
+ else
+ {
+ row.insertAfter(outfit.find('#outfit_row_' + curPrev.replace(' ', '-')));
+ }
+ } else {
+ $('div#' + row.attr('id') + ' > div.row_val > span', outfit).text(num);
+ $('div#' + row.attr('id') + ' .tooltip .numAvailable', outfit).text(numAvailable - num);
+ }
+ if(num === 0) {
+ $('.dnBtn', row).addClass('disabled');
+ $('.dnManyBtn', row).addClass('disabled');
+ } else {
+ $('.dnBtn', row).removeClass('disabled');
+ $('.dnManyBtn', row).removeClass('disabled');
+ }
+ if(num >= numAvailable || space < Path.getWeight(k)) {
+ $('.upBtn', row).addClass('disabled');
+ $('.upManyBtn', row).addClass('disabled');
+ } else if(space >= Path.getWeight(k)) {
+ $('.upBtn', row).removeClass('disabled');
+ $('.upManyBtn', row).removeClass('disabled');
+ }
+ } else if(have === 0 && row.length > 0) {
+ row.remove();
+ }
+ }
+
+ // Update bagspace
+ $('#bagspace').text(_('free {0}/{1}', Math.floor(Path.getCapacity() - total) , Path.getCapacity()));
+
+ if(Path.outfit['cured meat'] > 0) {
+ Button.setDisabled($('#embarkButton'), false);
+ } else {
+ Button.setDisabled($('#embarkButton'), true);
+ }
+ },
+
+ createOutfittingRow: function(key, num, name) {
+ if(!name) name = _(key);
+ var row = $('
').attr('id', 'outfit_row_' + key.replace(' ', '-')).addClass('outfitRow').attr('key',key);
+ $('
').addClass('row_key').text(name).appendTo(row);
+ var val = $('
').addClass('row_val').appendTo(row);
+
+ $('
').text(num).appendTo(val);
+ $('').addClass('upBtn').appendTo(val).click([1], Path.increaseSupply);
+ $('
').addClass('dnBtn').appendTo(val).click([1], Path.decreaseSupply);
+ $('
').addClass('upManyBtn').appendTo(val).click([10], Path.increaseSupply);
+ $('
').addClass('dnManyBtn').appendTo(val).click([10], Path.decreaseSupply);
+ $('
').addClass('clear').appendTo(row);
+
+ var numAvailable = $SM.get('stores["'+key+'"]', true);
+ var tt = $('
').addClass('tooltip bottom right').appendTo(row);
+ $('
').addClass('row_key').text(_('weight')).appendTo(tt);
+ $('
').addClass('row_val').text(Path.getWeight(key)).appendTo(tt);
+ $('
').addClass('row_key').text(_('available')).appendTo(tt);
+ $('
').addClass('row_val').addClass('numAvailable').text(numAvailable).appendTo(tt);
+
+ return row;
+ },
+
+ increaseSupply: function(btn) {
+ var supply = $(this).closest('.outfitRow').attr('key');
+ Engine.log('increasing ' + supply + ' by up to ' + btn.data);
+ var cur = Path.outfit[supply];
+ cur = typeof cur == 'number' ? cur : 0;
+ if(Path.getFreeSpace() >= Path.getWeight(supply) && cur < $SM.get('stores["'+supply+'"]', true)) {
+ var maxExtraByWeight = Math.floor(Path.getFreeSpace() / Path.getWeight(supply));
+ var maxExtraByStore = $SM.get('stores["'+supply+'"]', true) - cur;
+ var maxExtraByBtn = btn.data;
+ Path.outfit[supply] = cur + Math.min(maxExtraByBtn, Math.min(maxExtraByWeight, maxExtraByStore));
+ $SM.set('outfit['+supply+']', Path.outfit[supply]);
+ Path.updateOutfitting();
+ }
+ },
+
+ decreaseSupply: function(btn) {
+ var supply = $(this).closest('.outfitRow').attr('key');
+ Engine.log('decreasing ' + supply + ' by up to ' + btn.data);
+ var cur = Path.outfit[supply];
+ cur = typeof cur == 'number' ? cur : 0;
+ if(cur > 0) {
+ Path.outfit[supply] = Math.max(0, cur - btn.data);
+ $SM.set('outfit['+supply+']', Path.outfit[supply]);
+ Path.updateOutfitting();
+ }
+ },
+
+ onArrival: function(transition_diff) {
+ Path.setTitle();
+ Path.updateOutfitting();
+ Path.updatePerks(true);
+ $SM.set('outfit', Path.outfit);
+
+ Engine.moveStoresView($('#perks'), transition_diff);
+ },
+
+ setTitle: function() {
+ document.title = _('A Dusty Path');
+ },
+
+ embark: function() {
+ for(var k in Path.outfit) {
+ $SM.add('stores["'+k+'"]', -Path.outfit[k]);
+ }
+ $SM.remove('outfit');
+ World.onArrival();
+ $('#outerSlider').animate({left: '-700px'}, 300);
+ Engine.activeModule = World;
+ },
+
+ handleStateUpdates: function(e){
+ if(e.category == 'character' && e.stateName.indexOf('character.perks') === 0 && Engine.activeModule == Path){
+ Path.updatePerks();
+ }
+ }
+};
diff --git a/script/room.js b/script/room.js
index 32bd49b..5be65d3 100644
--- a/script/room.js
+++ b/script/room.js
@@ -1,1120 +1,1120 @@
-/**
- * Module that registers the simple room functionality
- */
-var Room = {
- // times in (minutes * seconds * milliseconds)
- _FIRE_COOL_DELAY: 5 * 60 * 1000, // time after a stoke before the fire cools
- _ROOM_WARM_DELAY: 30 * 1000, // time between room temperature updates
- _BUILDER_STATE_DELAY: 0.5 * 60 * 1000, // time between builder state updates
- _STOKE_COOLDOWN: 10, // cooldown to stoke the fire
- _NEED_WOOD_DELAY: 15 * 1000, // from when the stranger shows up, to when you need wood
-
- buttons:{},
-
- Craftables: {
- 'trap': {
- name: _('trap'),
- button: null,
- maximum: 10,
- availableMsg: _('builder says she can make traps to catch any creatures might still be alive out there'),
- buildMsg: _('more traps to catch more creatures'),
- maxMsg: _("more traps won't help now"),
- type: 'building',
- cost: function() {
- var n = $SM.get('game.buildings["trap"]', true);
- return {
- 'wood': 10 + (n*10)
- };
- }
- },
- 'cart': {
- name: _('cart'),
- button: null,
- maximum: 1,
- availableMsg: _('builder says she can make a cart for carrying wood'),
- buildMsg: _('the rickety cart will carry more wood from the forest'),
- type: 'building',
- cost: function() {
- return {
- 'wood': 30
- };
- }
- },
- 'hut': {
- name: _('hut'),
- button: null,
- maximum: 20,
- availableMsg: _("builder says there are more wanderers. says they'll work, too."),
- buildMsg: _('builder puts up a hut, out in the forest. says word will get around.'),
- maxMsg: _('no more room for huts.'),
- type: 'building',
- cost: function() {
- var n = $SM.get('game.buildings["hut"]', true);
- return {
- 'wood': 100 + (n*50)
- };
- }
- },
- 'lodge': {
- name: _('lodge'),
- button: null,
- maximum: 1,
- availableMsg: _('villagers could help hunt, given the means'),
- buildMsg: _('the hunting lodge stands in the forest, a ways out of town'),
- type: 'building',
- cost: function() {
- return {
- wood: 200,
- fur: 10,
- meat: 5
- };
- }
- },
- 'trading post': {
- name: _('trading post'),
- button: null,
- maximum: 1,
- availableMsg: _("a trading post would make commerce easier"),
- buildMsg: _("now the nomads have a place to set up shop, they might stick around a while"),
- type: 'building',
- cost: function() {
- return {
- 'wood': 400,
- 'fur': 100
- };
- }
- },
- 'tannery': {
- name: _('tannery'),
- button: null,
- maximum: 1,
- availableMsg: _("builder says leather could be useful. says the villagers could make it."),
- buildMsg: _('tannery goes up quick, on the edge of the village'),
- type: 'building',
- cost: function() {
- return {
- 'wood': 500,
- 'fur': 50
- };
- }
- },
- 'smokehouse': {
- name: _('smokehouse'),
- button: null,
- maximum: 1,
- availableMsg: _("should cure the meat, or it'll spoil. builder says she can fix something up."),
- buildMsg: _('builder finishes the smokehouse. she looks hungry.'),
- type: 'building',
- cost: function() {
- return {
- 'wood': 600,
- 'meat': 50
- };
- }
- },
- 'workshop': {
- name: _('workshop'),
- button: null,
- maximum: 1,
- availableMsg: _("builder says she could make finer things, if she had the tools"),
- buildMsg: _("workshop's finally ready. builder's excited to get to it"),
- type: 'building',
- cost: function() {
- return {
- 'wood': 800,
- 'leather': 100,
- 'scales': 10
- };
- }
- },
- 'steelworks': {
- name: _('steelworks'),
- button: null,
- maximum: 1,
- availableMsg: _("builder says the villagers could make steel, given the tools"),
- buildMsg: _("a haze falls over the village as the steelworks fires up"),
- type: 'building',
- cost: function() {
- return {
- 'wood': 1500,
- 'iron': 100,
- 'coal': 100
- };
- }
- },
- 'armoury': {
- name: _('armoury'),
- button: null,
- maximum: 1,
- availableMsg: _("builder says it'd be useful to have a steady source of bullets"),
- buildMsg: _("armoury's done, welcoming back the weapons of the past."),
- type: 'building',
- cost: function() {
- return {
- 'wood': 3000,
- 'steel': 100,
- 'sulphur': 50
- };
- }
- },
- 'torch': {
- name: _('torch'),
- button: null,
- type: 'tool',
- buildMsg: _('a torch to keep the dark away'),
- cost: function() {
- return {
- 'wood': 1,
- 'cloth': 1
- };
- }
- },
- 'waterskin': {
- name: _('waterskin'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('this waterskin\'ll hold a bit of water, at least'),
- cost: function() {
- return {
- 'leather': 50
- };
- }
- },
- 'cask': {
- name: _('cask'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('the cask holds enough water for longer expeditions'),
- cost: function() {
- return {
- 'leather': 100,
- 'iron': 20
- };
- }
- },
- 'water tank': {
- name: _('water tank'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('never go thirsty again'),
- cost: function() {
- return {
- 'iron': 100,
- 'steel': 50
- };
- }
- },
- 'bone spear': {
- name: _('bone spear'),
- button: null,
- type: 'weapon',
- buildMsg: _("this spear's not elegant, but it's pretty good at stabbing"),
- cost: function() {
- return {
- 'wood': 100,
- 'teeth': 5
- };
- }
- },
- 'rucksack': {
- name: _('rucksack'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('carrying more means longer expeditions to the wilds'),
- cost: function() {
- return {
- 'leather': 200
- };
- }
- },
- 'wagon': {
- name: _('wagon'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('the wagon can carry a lot of supplies'),
- cost: function() {
- return {
- 'wood': 500,
- 'iron': 100
- };
- }
- },
- 'convoy': {
- name: _('convoy'),
- button: null,
- type: 'upgrade',
- maximum: 1,
- buildMsg: _('the convoy can haul mostly everything'),
- cost: function() {
- return {
- 'wood': 1000,
- 'iron': 200,
- 'steel': 100
- };
- }
- },
- 'l armour': {
- name: _('l armour'),
- type: 'upgrade',
- maximum: 1,
- buildMsg: _("leather's not strong. better than rags, though."),
- cost: function() {
- return {
- 'leather': 200,
- 'scales': 20
- };
- }
- },
- 'i armour': {
- name: _('i armour'),
- type: 'upgrade',
- maximum: 1,
- buildMsg: _("iron's stronger than leather"),
- cost: function() {
- return {
- 'leather': 200,
- 'iron': 100
- };
- }
- },
- 's armour': {
- name: _('s armour'),
- type: 'upgrade',
- maximum: 1,
- buildMsg: _("steel's stronger than iron"),
- cost: function() {
- return {
- 'leather': 200,
- 'steel': 100
- };
- }
- },
- 'iron sword': {
- name: _('iron sword'),
- button: null,
- type: 'weapon',
- buildMsg: _("sword is sharp. good protection out in the wilds."),
- cost: function() {
- return {
- 'wood': 200,
- 'leather': 50,
- 'iron': 20
- };
- }
- },
- 'steel sword': {
- name: _('steel sword'),
- button: null,
- type: 'weapon',
- buildMsg: _("the steel is strong, and the blade true."),
- cost: function() {
- return {
- 'wood': 500,
- 'leather': 100,
- 'steel': 20
- };
- }
- },
- 'rifle': {
- name: _('rifle'),
- type: 'weapon',
- buildMsg: _("black powder and bullets, like the old days."),
- cost: function() {
- return {
- 'wood': 200,
- 'steel': 50,
- 'sulphur': 50
- };
- }
- }
- },
-
- TradeGoods: {
- 'scales': {
- type: 'good',
- cost: function() {
- return { fur: 150 };
- }
- },
- 'teeth': {
- type: 'good',
- cost: function() {
- return { fur: 300 };
- }
- },
- 'iron': {
- type: 'good',
- cost: function() {
- return {
- 'fur': 150,
- 'scales': 50
- };
- }
- },
- 'coal': {
- type: 'good',
- cost: function() {
- return {
- 'fur': 200,
- 'teeth': 50
- };
- }
- },
- 'steel': {
- type: 'good',
- cost: function() {
- return {
- 'fur': 300,
- 'scales': 50,
- 'teeth': 50
- };
- }
- },
- 'medicine': {
- type: 'good',
- cost: function() {
- return {
- 'scales': 50, 'teeth': 30
- };
- }
- },
- 'bullets': {
- type: 'good',
- cost: function() {
- return {
- 'scales': 10
- };
- }
- },
- 'energy cell': {
- type: 'good',
- cost: function() {
- return {
- 'scales': 10,
- 'teeth': 10
- };
- }
- },
- 'bolas': {
- type: 'weapon',
- cost: function() {
- return {
- 'teeth': 10
- };
- }
- },
- 'grenade': {
- type: 'weapon',
- cost: function() {
- return {
- 'scales': 100,
- 'teeth': 50
- };
- }
- },
- 'bayonet': {
- type: 'weapon',
- cost: function() {
- return {
- 'scales': 500,
- 'teeth': 250
- };
- }
- },
- 'alien alloy': {
- type: 'good',
- cost: function() {
- return {
- 'fur': 1500,
- 'scales': 750,
- 'teeth': 300
- };
- }
- },
- 'compass': {
- type: 'upgrade',
- maximum: 1,
- cost: function() {
- return {
- fur: 400,
- scales: 20,
- teeth: 10
- };
- }
- }
- },
-
- MiscItems: {
- 'laser rifle': {
- type: 'weapon'
- }
- },
-
- name: _("Room"),
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- if(Engine._debug) {
- this._ROOM_WARM_DELAY = 5000;
- this._BUILDER_STATE_DELAY = 5000;
- this._STOKE_COOLDOWN = 0;
- this._NEED_WOOD_DELAY = 5000;
- }
-
- if(typeof $SM.get('features.location.room') == 'undefined') {
- $SM.set('features.location.room', true);
- $SM.set('game.builder.level', -1);
- }
-
- // If this is the first time playing, the fire is dead and it's freezing.
- // Otherwise grab past save state temp and fire level.
- $SM.set('game.temperature', $SM.get('game.temperature.value')===undefined?this.TempEnum.Freezing:$SM.get('game.temperature'));
- $SM.set('game.fire', $SM.get('game.fire.value')===undefined?this.FireEnum.Dead:$SM.get('game.fire'));
-
- // Create the room tab
- this.tab = Header.addLocation(_("A Dark Room"), "room", Room);
-
- // Create the Room panel
- this.panel = $('
')
- .attr('id', "roomPanel")
- .addClass('location')
- .appendTo('div#locationSlider');
-
- Engine.updateSlider();
-
- // Create the light button
- new Button.Button({
- id: 'lightButton',
- text: _('light fire'),
- click: Room.lightFire,
- cooldown: Room._STOKE_COOLDOWN,
- width: '80px',
- cost: {'wood': 5}
- }).appendTo('div#roomPanel');
-
- // Create the stoke button
- new Button.Button({
- id: 'stokeButton',
- text: _("stoke fire"),
- click: Room.stokeFire,
- cooldown: Room._STOKE_COOLDOWN,
- width: '80px',
- cost: {'wood': 1}
- }).appendTo('div#roomPanel');
-
- // Create the stores container
- $('
').attr('id', 'storesContainer').appendTo('div#roomPanel');
-
- //subscribe to stateUpdates
- $.Dispatch('stateUpdate').subscribe(Room.handleStateUpdates);
-
- Room.updateButton();
- Room.updateStoresView();
- Room.updateIncomeView();
- Room.updateBuildButtons();
-
- Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
- Room._tempTimer = Engine.setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY);
-
- /*
- * Builder states:
- * 0 - Approaching
- * 1 - Collapsed
- * 2 - Shivering
- * 3 - Sleeping
- * 4 - Helping
- */
- if($SM.get('game.builder.level') >= 0 && $SM.get('game.builder.level') < 3) {
- Room._builderTimer = Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
- }
- if($SM.get('game.builder.level') == 1 && $SM.get('stores.wood', true) < 0) {
- Engine.setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY);
- }
- Engine.setTimeout($SM.collectIncome, 1000);
-
- Notifications.notify(Room, _("the room is {0}", Room.TempEnum.fromInt($SM.get('game.temperature.value')).text));
- Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text));
- },
-
- options: {}, // Nothing for now
-
- onArrival: function(transition_diff) {
- Room.setTitle();
- if(Room.changed) {
- Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text));
- Notifications.notify(Room, _("the room is {0}", Room.TempEnum.fromInt($SM.get('game.temperature.value')).text));
- Room.changed = false;
- }
- if($SM.get('game.builder.level') == 3) {
- $SM.add('game.builder.level', 1);
- $SM.setIncome('builder', {
- delay: 10,
- stores: {'wood' : 2 }
- });
- Room.updateIncomeView();
- Notifications.notify(Room, _("the stranger is standing by the fire. she says she can help. says she builds things."));
- }
-
- Engine.moveStoresView(null, transition_diff);
- },
-
- TempEnum: {
- fromInt: function(value) {
- for(var k in this) {
- if(typeof this[k].value != 'undefined' && this[k].value == value) {
- return this[k];
- }
- }
- return null;
- },
- Freezing: { value: 0, text: _('freezing') },
- Cold: { value: 1, text: _('cold') },
- Mild: { value: 2, text: _('mild') },
- Warm: { value: 3, text: _('warm') },
- Hot: { value: 4, text: _('hot') }
- },
-
- FireEnum: {
- fromInt: function(value) {
- for(var k in this) {
- if(typeof this[k].value != 'undefined' && this[k].value == value) {
- return this[k];
- }
- }
- return null;
- },
- Dead: { value: 0, text: _('dead') },
- Smoldering: { value: 1, text: _('smoldering') },
- Flickering: { value: 2, text: _('flickering') },
- Burning: { value: 3, text: _('burning') },
- Roaring: { value: 4, text: _('roaring') }
- },
-
- setTitle: function() {
- var title = $SM.get('game.fire.value') < 2 ? _("A Dark Room") : _("A Firelit Room");
- if(Engine.activeModule == this) {
- document.title = title;
- }
- $('div#location_room').text(title);
- },
-
- updateButton: function() {
- var light = $('#lightButton.button');
- var stoke = $('#stokeButton.button');
- if($SM.get('game.fire.value') == Room.FireEnum.Dead.value && stoke.css('display') != 'none') {
- stoke.hide();
- light.show();
- if(stoke.hasClass('disabled')) {
- Button.cooldown(light);
- }
- } else if(light.css('display') != 'none') {
- stoke.show();
- light.hide();
- if(light.hasClass('disabled')) {
- Button.cooldown(stoke);
- }
- }
-
- if(!$SM.get('stores.wood')) {
- light.addClass('free');
- stoke.addClass('free');
- } else {
- light.removeClass('free');
- stoke.removeClass('free');
- }
- },
-
- _fireTimer: null,
- _tempTimer: null,
- lightFire: function() {
- var wood = $SM.get('stores.wood');
- if(wood < 5) {
- Notifications.notify(Room, _("not enough wood to get the fire going"));
- Button.clearCooldown($('#lightButton.button'));
- return;
- } else if(wood > 4) {
- $SM.set('stores.wood', wood - 5);
- }
- $SM.set('game.fire', Room.FireEnum.Burning);
- Room.onFireChange();
- },
-
- stokeFire: function() {
- var wood = $SM.get('stores.wood');
- if(wood === 0) {
- Notifications.notify(Room, _("the wood has run out"));
- Button.clearCooldown($('#stokeButton.button'));
- return;
- }
- if(wood > 0) {
- $SM.set('stores.wood', wood - 1);
- }
- if($SM.get('game.fire.value') < 4) {
- $SM.set('game.fire', Room.FireEnum.fromInt($SM.get('game.fire.value') + 1));
- }
- Room.onFireChange();
- },
-
- onFireChange: function() {
- if(Engine.activeModule != Room) {
- Room.changed = true;
- }
- Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text), true);
- if($SM.get('game.fire.value') > 1 && $SM.get('game.builder.level') < 0) {
- $SM.set('game.builder.level', 0);
- Notifications.notify(Room, _("the light from the fire spills from the windows, out into the dark"));
- Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
- }
- window.clearTimeout(Room._fireTimer);
- Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
- Room.updateButton();
- Room.setTitle();
- },
-
- coolFire: function() {
- var wood = $SM.get('stores.wood');
- if($SM.get('game.fire.value') <= Room.FireEnum.Flickering.value &&
- $SM.get('game.builder.level') > 3 && wood > 0) {
- Notifications.notify(Room, _("builder stokes the fire"), true);
- $SM.set('stores.wood', wood - 1);
- $SM.set('game.fire',Room.FireEnum.fromInt($SM.get('game.fire.value') + 1));
- }
- if($SM.get('game.fire.value') > 0) {
- $SM.set('game.fire',Room.FireEnum.fromInt($SM.get('game.fire.value') - 1));
- Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
- Room.onFireChange();
- }
- },
-
- adjustTemp: function() {
- var old = $SM.get('game.temperature.value');
- if($SM.get('game.temperature.value') > 0 && $SM.get('game.temperature.value') > $SM.get('game.fire.value')) {
- $SM.set('game.temperature',Room.TempEnum.fromInt($SM.get('game.temperature.value') - 1));
- Notifications.notify(Room, _("the room is {0}" , Room.TempEnum.fromInt($SM.get('game.temperature.value')).text), true);
- }
- if($SM.get('game.temperature.value') < 4 && $SM.get('game.temperature.value') < $SM.get('game.fire.value')) {
- $SM.set('game.temperature', Room.TempEnum.fromInt($SM.get('game.temperature.value') + 1));
- Notifications.notify(Room, _("the room is {0}" , Room.TempEnum.fromInt($SM.get('game.temperature.value')).text), true);
- }
- if($SM.get('game.temperature.value') != old) {
- Room.changed = true;
- }
- Room._tempTimer = Engine.setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY);
- },
-
- unlockForest: function() {
- $SM.set('stores.wood', 4);
- Outside.init();
- Notifications.notify(Room, _("the wind howls outside"));
- Notifications.notify(Room, _("the wood is running out"));
- Engine.event('progress', 'outside');
- },
-
- updateBuilderState: function() {
- var lBuilder = $SM.get('game.builder.level');
- if(lBuilder === 0) {
- Notifications.notify(Room, _("a ragged stranger stumbles through the door and collapses in the corner"));
- lBuilder = $SM.setget('game.builder.level', 1);
- Engine.setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY);
- }
- else if(lBuilder < 3 && $SM.get('game.temperature.value') >= Room.TempEnum.Warm.value) {
- var msg = "";
- switch(lBuilder) {
- case 1:
- msg = _("the stranger shivers, and mumbles quietly. her words are unintelligible.");
- break;
- case 2:
- msg = _("the stranger in the corner stops shivering. her breathing calms.");
- break;
- }
- Notifications.notify(Room, msg);
- if(lBuilder < 3) {
- lBuilder = $SM.setget('game.builder.level', lBuilder + 1);
- }
- }
- if(lBuilder < 3) {
- Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
- }
- Engine.saveGame();
- },
-
- updateStoresView: function() {
- var stores = $('div#stores');
- var weapons = $('div#weapons');
- var needsAppend = false, wNeedsAppend = false, newRow = false;
- if(stores.length === 0) {
- stores = $('
').attr({
- id: 'stores'
- }).css('opacity', 0);
- needsAppend = true;
- }
- if(weapons.length === 0) {
- weapons = $('
').attr({
- id: 'weapons'
- }).css('opacity', 0);
- wNeedsAppend = true;
- }
- for(var k in $SM.get('stores')) {
-
- var type = null;
- if(Room.Craftables[k]) {
- type = Room.Craftables[k].type;
- } else if(Room.TradeGoods[k]) {
- type = Room.TradeGoods[k].type;
- } else if (Room.MiscItems[k]) {
- type = Room.MiscItems[k].type;
- }
-
- var location;
- switch(type) {
- case 'upgrade':
- // Don't display upgrades on the Room screen
- continue;
- case 'weapon':
- location = weapons;
- break;
- default:
- location = stores;
- break;
- }
-
- var id = "row_" + k.replace(' ', '-');
- var row = $('div#' + id, location);
- 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 = 0;
- $SM.set('stores["'+k+'"]', 0);
- }
-
-
- // thieves?
- if(typeof $SM.get('game.thieves') == 'undefined' && num > 5000 && $SM.get('features.location.world')) {
- $SM.startThieves();
- }
-
- if(row.length === 0 && num > 0) {
- row = $('
').attr('id', id).addClass('storeRow');
- $('
').addClass('row_key').text(_(k)).appendTo(row);
- $('
').addClass('row_val').text(Math.floor(num)).appendTo(row);
- $('
').addClass('clear').appendTo(row);
- var curPrev = null;
- location.children().each(function(i) {
- var child = $(this);
- var cName = child.attr('id').substring(4).replace('-', ' ');
- if(cName < k && (curPrev == null || cName > curPrev)) {
- curPrev = cName;
- }
- });
- if(curPrev == null) {
- row.prependTo(location);
- } else {
- row.insertAfter(location.find('#row_' + curPrev.replace(' ', '-')));
- }
- newRow = true;
- } else if(num>= 0){
- $('div#' + row.attr('id') + ' > div.row_val', location).text(Math.floor(num));
- }
- }
-
- if(needsAppend && stores.children().length > 0) {
- stores.appendTo('div#storesContainer');
- stores.animate({opacity: 1}, 300, 'linear');
- }
-
- if(wNeedsAppend && weapons.children().length > 0) {
- weapons.appendTo('div#storesContainer');
- weapons.animate({opacity: 1}, 300, 'linear');
- }
-
- if(newRow) {
- Room.updateIncomeView();
- }
-
- if($("div#outsidePanel").length) {
- Outside.updateVillage();
- }
- },
-
- updateIncomeView: function() {
- var stores = $('div#stores');
- 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 $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);
- $('
')
- .addClass('row_val')
- .text(Engine.getIncomeMsg(income.stores[store], income.delay))
- .appendTo(tt);
- }
- }
- }
- if(tt.children().length > 0) {
- tt.appendTo(el);
- }
- });
- },
-
- buy: function(buyBtn) {
- var thing = $(buyBtn).attr('buildThing');
- var good = Room.TradeGoods[thing];
- var numThings = $SM.get('stores["'+thing+'"]', true);
- if(numThings < 0) numThings = 0;
- if(good.maximum <= numThings) {
- return;
- }
-
- var storeMod = {};
- var cost = good.cost();
- for(var k in cost) {
- var have = $SM.get('stores["'+k+'"]', true);
- if(have < cost[k]) {
- Notifications.notify(Room, _("not enough " + k));
- return false;
- } else {
- storeMod[k] = have - cost[k];
- }
- }
- $SM.setM('stores', storeMod);
-
- Notifications.notify(Room, good.buildMsg);
-
- $SM.add('stores["'+thing+'"]', 1);
-
- if(thing == 'compass') {
- Path.openPath();
- }
- },
-
- build: function(buildBtn) {
- var thing = $(buildBtn).attr('buildThing');
- if($SM.get('game.temperature.value') <= Room.TempEnum.Cold.value) {
- Notifications.notify(Room, _("builder just shivers"));
- return false;
- }
- var craftable = Room.Craftables[thing];
-
- var numThings = 0;
- switch(craftable.type) {
- case 'good':
- case 'weapon':
- case 'tool':
- case 'upgrade':
- numThings = $SM.get('stores["'+thing+'"]', true);
- break;
- case 'building':
- numThings = $SM.get('game.buildings["'+thing+'"]', true);
- break;
- }
-
- if(numThings < 0) numThings = 0;
- if(craftable.maximum <= numThings) {
- return;
- }
-
- var storeMod = {};
- var cost = craftable.cost();
- for(var k in cost) {
- var have = $SM.get('stores["'+k+'"]', true);
- if(have < cost[k]) {
- Notifications.notify(Room, _("not enough "+k));
- return false;
- } else {
- storeMod[k] = have - cost[k];
- }
- }
- $SM.setM('stores', storeMod);
-
- Notifications.notify(Room, craftable.buildMsg);
-
- switch(craftable.type) {
- case 'good':
- case 'weapon':
- case 'upgrade':
- case 'tool':
- $SM.add('stores["'+thing+'"]', 1);
- break;
- case 'building':
- $SM.add('game.buildings["'+thing+'"]', 1);
- break;
- }
- },
-
- needsWorkshop: function(type) {
- return type == 'weapon' || type == 'upgrade' || type =='tool';
- },
-
- craftUnlocked: function(thing) {
- if(Room.buttons[thing]) {
- return true;
- }
- if($SM.get('game.builder.level') < 4) return false;
- var craftable = Room.Craftables[thing];
- if(Room.needsWorkshop(craftable.type) && $SM.get('game.buildings["'+'workshop'+'"]', true) === 0) return false;
- var cost = craftable.cost();
-
- //show button if one has already been built
- if($SM.get('game.buildings["'+thing+'"]') > 0){
- Room.buttons[thing] = true;
- return true;
- }
- // Show buttons if we have at least 1/2 the wood, and all other components have been seen.
- if($SM.get('stores.wood', true) < cost['wood'] * 0.5) {
- return false;
- }
- for(var c in cost) {
- if(!$SM.get('stores["'+c+'"]')) {
- return false;
- }
- }
-
- Room.buttons[thing] = true;
- //don't notify if it has already been built before
- if(!$SM.get('game.buildings["'+thing+'"]')){
- Notifications.notify(Room, craftable.availableMsg);
- }
- return true;
- },
-
- buyUnlocked: function(thing) {
- if(Room.buttons[thing]) {
- return true;
- } else if($SM.get('game.buildings["trading post"]', true) > 0) {
- if(thing == 'compass' || typeof $SM.get('stores["'+thing+'"]') != 'undefined') {
- // Allow the purchase of stuff once you've seen it
- return true;
- }
- }
- return false;
- },
-
- updateBuildButtons: function() {
- var buildSection = $('#buildBtns');
- var needsAppend = false;
- if(buildSection.length === 0) {
- buildSection = $('
').attr('id', 'buildBtns').css('opacity', 0);
- needsAppend = true;
- }
-
- var craftSection = $('#craftBtns');
- var cNeedsAppend = false;
- if(craftSection.length === 0 && $SM.get('game.buildings["workshop"]', true) > 0) {
- craftSection = $('
').attr('id', 'craftBtns').css('opacity', 0);
- cNeedsAppend = true;
- }
-
- var buySection = $('#buyBtns');
- var bNeedsAppend = false;
- if(buySection.length === 0 && $SM.get('game.buildings["trading post"]', true) > 0) {
- buySection = $('
').attr('id', 'buyBtns').css('opacity', 0);
- bNeedsAppend = true;
- }
-
- for(var k in Room.Craftables) {
- craftable = Room.Craftables[k];
- var max = $SM.num(k, craftable) + 1 > craftable.maximum;
- if(craftable.button == null) {
- if(Room.craftUnlocked(k)) {
- var loc = Room.needsWorkshop(craftable.type) ? craftSection : buildSection;
- craftable.button = new Button.Button({
- id: 'build_' + k,
- cost: craftable.cost(),
- text: _(k),
- click: Room.build,
- width: '80px',
- ttPos: loc.children().length > 10 ? 'top right' : 'bottom right'
- }).css('opacity', 0).attr('buildThing', k).appendTo(loc).animate({opacity: 1}, 300, 'linear');
- }
- } else {
- // refresh the tooltip
- var costTooltip = $('.tooltip', craftable.button);
- costTooltip.empty();
- var cost = craftable.cost();
- for(var k in cost) {
- $("
").addClass('row_key').text(_(k)).appendTo(costTooltip);
- $("
").addClass('row_val').text(cost[k]).appendTo(costTooltip);
- }
- if(max && !craftable.button.hasClass('disabled')) {
- Notifications.notify(Room, craftable.maxMsg);
- }
- }
- if(max) {
- Button.setDisabled(craftable.button, true);
- } else {
- Button.setDisabled(craftable.button, false);
- }
- }
-
- for(var k in Room.TradeGoods) {
- good = Room.TradeGoods[k];
- var max = $SM.num(k, good) + 1 > good.maximum;
- if(good.button == null) {
- if(Room.buyUnlocked(k)) {
- good.button = new Button.Button({
- id: 'build_' + k,
- cost: good.cost(),
- text: _(k),
- click: Room.buy,
- width: '80px'
- }).css('opacity', 0).attr('buildThing', k).appendTo(buySection).animate({opacity:1}, 300, 'linear');
- }
- } else {
- // refresh the tooltip
- var costTooltip = $('.tooltip', good.button);
- costTooltip.empty();
- var cost = good.cost();
- for(var k in cost) {
- $("
").addClass('row_key').text(_(k)).appendTo(costTooltip);
- $("
").addClass('row_val').text(cost[k]).appendTo(costTooltip);
- }
- if(max && !good.button.hasClass('disabled')) {
- Notifications.notify(Room, good.maxMsg);
- }
- }
- if(max) {
- Button.setDisabled(good.button, true);
- } else {
- Button.setDisabled(good.button, false);
- }
- }
-
- if(needsAppend && buildSection.children().length > 0) {
- buildSection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
- }
- if(cNeedsAppend && craftSection.children().length > 0) {
- craftSection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
- }
- if(bNeedsAppend && buildSection.children().length > 0) {
- buySection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
- }
- },
-
- handleStateUpdates: function(e){
- if(e.category == 'stores'){
- Room.updateStoresView();
- Room.updateBuildButtons();
- } else if(e.category == 'income'){
- Room.updateStoresView();
- Room.updateIncomeView();
- } else if(e.stateName.indexOf('game.buildings') === 0){
- Room.updateBuildButtons();
- }
- }
-};
+/**
+ * Module that registers the simple room functionality
+ */
+var Room = {
+ // times in (minutes * seconds * milliseconds)
+ _FIRE_COOL_DELAY: 5 * 60 * 1000, // time after a stoke before the fire cools
+ _ROOM_WARM_DELAY: 30 * 1000, // time between room temperature updates
+ _BUILDER_STATE_DELAY: 0.5 * 60 * 1000, // time between builder state updates
+ _STOKE_COOLDOWN: 10, // cooldown to stoke the fire
+ _NEED_WOOD_DELAY: 15 * 1000, // from when the stranger shows up, to when you need wood
+
+ buttons:{},
+
+ Craftables: {
+ 'trap': {
+ name: _('trap'),
+ button: null,
+ maximum: 10,
+ availableMsg: _('builder says she can make traps to catch any creatures might still be alive out there'),
+ buildMsg: _('more traps to catch more creatures'),
+ maxMsg: _("more traps won't help now"),
+ type: 'building',
+ cost: function() {
+ var n = $SM.get('game.buildings["trap"]', true);
+ return {
+ 'wood': 10 + (n*10)
+ };
+ }
+ },
+ 'cart': {
+ name: _('cart'),
+ button: null,
+ maximum: 1,
+ availableMsg: _('builder says she can make a cart for carrying wood'),
+ buildMsg: _('the rickety cart will carry more wood from the forest'),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 30
+ };
+ }
+ },
+ 'hut': {
+ name: _('hut'),
+ button: null,
+ maximum: 20,
+ availableMsg: _("builder says there are more wanderers. says they'll work, too."),
+ buildMsg: _('builder puts up a hut, out in the forest. says word will get around.'),
+ maxMsg: _('no more room for huts.'),
+ type: 'building',
+ cost: function() {
+ var n = $SM.get('game.buildings["hut"]', true);
+ return {
+ 'wood': 100 + (n*50)
+ };
+ }
+ },
+ 'lodge': {
+ name: _('lodge'),
+ button: null,
+ maximum: 1,
+ availableMsg: _('villagers could help hunt, given the means'),
+ buildMsg: _('the hunting lodge stands in the forest, a ways out of town'),
+ type: 'building',
+ cost: function() {
+ return {
+ wood: 200,
+ fur: 10,
+ meat: 5
+ };
+ }
+ },
+ 'trading post': {
+ name: _('trading post'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("a trading post would make commerce easier"),
+ buildMsg: _("now the nomads have a place to set up shop, they might stick around a while"),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 400,
+ 'fur': 100
+ };
+ }
+ },
+ 'tannery': {
+ name: _('tannery'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("builder says leather could be useful. says the villagers could make it."),
+ buildMsg: _('tannery goes up quick, on the edge of the village'),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 500,
+ 'fur': 50
+ };
+ }
+ },
+ 'smokehouse': {
+ name: _('smokehouse'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("should cure the meat, or it'll spoil. builder says she can fix something up."),
+ buildMsg: _('builder finishes the smokehouse. she looks hungry.'),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 600,
+ 'meat': 50
+ };
+ }
+ },
+ 'workshop': {
+ name: _('workshop'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("builder says she could make finer things, if she had the tools"),
+ buildMsg: _("workshop's finally ready. builder's excited to get to it"),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 800,
+ 'leather': 100,
+ 'scales': 10
+ };
+ }
+ },
+ 'steelworks': {
+ name: _('steelworks'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("builder says the villagers could make steel, given the tools"),
+ buildMsg: _("a haze falls over the village as the steelworks fires up"),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 1500,
+ 'iron': 100,
+ 'coal': 100
+ };
+ }
+ },
+ 'armoury': {
+ name: _('armoury'),
+ button: null,
+ maximum: 1,
+ availableMsg: _("builder says it'd be useful to have a steady source of bullets"),
+ buildMsg: _("armoury's done, welcoming back the weapons of the past."),
+ type: 'building',
+ cost: function() {
+ return {
+ 'wood': 3000,
+ 'steel': 100,
+ 'sulphur': 50
+ };
+ }
+ },
+ 'torch': {
+ name: _('torch'),
+ button: null,
+ type: 'tool',
+ buildMsg: _('a torch to keep the dark away'),
+ cost: function() {
+ return {
+ 'wood': 1,
+ 'cloth': 1
+ };
+ }
+ },
+ 'waterskin': {
+ name: _('waterskin'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('this waterskin\'ll hold a bit of water, at least'),
+ cost: function() {
+ return {
+ 'leather': 50
+ };
+ }
+ },
+ 'cask': {
+ name: _('cask'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('the cask holds enough water for longer expeditions'),
+ cost: function() {
+ return {
+ 'leather': 100,
+ 'iron': 20
+ };
+ }
+ },
+ 'water tank': {
+ name: _('water tank'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('never go thirsty again'),
+ cost: function() {
+ return {
+ 'iron': 100,
+ 'steel': 50
+ };
+ }
+ },
+ 'bone spear': {
+ name: _('bone spear'),
+ button: null,
+ type: 'weapon',
+ buildMsg: _("this spear's not elegant, but it's pretty good at stabbing"),
+ cost: function() {
+ return {
+ 'wood': 100,
+ 'teeth': 5
+ };
+ }
+ },
+ 'rucksack': {
+ name: _('rucksack'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('carrying more means longer expeditions to the wilds'),
+ cost: function() {
+ return {
+ 'leather': 200
+ };
+ }
+ },
+ 'wagon': {
+ name: _('wagon'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('the wagon can carry a lot of supplies'),
+ cost: function() {
+ return {
+ 'wood': 500,
+ 'iron': 100
+ };
+ }
+ },
+ 'convoy': {
+ name: _('convoy'),
+ button: null,
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _('the convoy can haul mostly everything'),
+ cost: function() {
+ return {
+ 'wood': 1000,
+ 'iron': 200,
+ 'steel': 100
+ };
+ }
+ },
+ 'l armour': {
+ name: _('l armour'),
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _("leather's not strong. better than rags, though."),
+ cost: function() {
+ return {
+ 'leather': 200,
+ 'scales': 20
+ };
+ }
+ },
+ 'i armour': {
+ name: _('i armour'),
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _("iron's stronger than leather"),
+ cost: function() {
+ return {
+ 'leather': 200,
+ 'iron': 100
+ };
+ }
+ },
+ 's armour': {
+ name: _('s armour'),
+ type: 'upgrade',
+ maximum: 1,
+ buildMsg: _("steel's stronger than iron"),
+ cost: function() {
+ return {
+ 'leather': 200,
+ 'steel': 100
+ };
+ }
+ },
+ 'iron sword': {
+ name: _('iron sword'),
+ button: null,
+ type: 'weapon',
+ buildMsg: _("sword is sharp. good protection out in the wilds."),
+ cost: function() {
+ return {
+ 'wood': 200,
+ 'leather': 50,
+ 'iron': 20
+ };
+ }
+ },
+ 'steel sword': {
+ name: _('steel sword'),
+ button: null,
+ type: 'weapon',
+ buildMsg: _("the steel is strong, and the blade true."),
+ cost: function() {
+ return {
+ 'wood': 500,
+ 'leather': 100,
+ 'steel': 20
+ };
+ }
+ },
+ 'rifle': {
+ name: _('rifle'),
+ type: 'weapon',
+ buildMsg: _("black powder and bullets, like the old days."),
+ cost: function() {
+ return {
+ 'wood': 200,
+ 'steel': 50,
+ 'sulphur': 50
+ };
+ }
+ }
+ },
+
+ TradeGoods: {
+ 'scales': {
+ type: 'good',
+ cost: function() {
+ return { fur: 150 };
+ }
+ },
+ 'teeth': {
+ type: 'good',
+ cost: function() {
+ return { fur: 300 };
+ }
+ },
+ 'iron': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'fur': 150,
+ 'scales': 50
+ };
+ }
+ },
+ 'coal': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'fur': 200,
+ 'teeth': 50
+ };
+ }
+ },
+ 'steel': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'fur': 300,
+ 'scales': 50,
+ 'teeth': 50
+ };
+ }
+ },
+ 'medicine': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'scales': 50, 'teeth': 30
+ };
+ }
+ },
+ 'bullets': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'scales': 10
+ };
+ }
+ },
+ 'energy cell': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'scales': 10,
+ 'teeth': 10
+ };
+ }
+ },
+ 'bolas': {
+ type: 'weapon',
+ cost: function() {
+ return {
+ 'teeth': 10
+ };
+ }
+ },
+ 'grenade': {
+ type: 'weapon',
+ cost: function() {
+ return {
+ 'scales': 100,
+ 'teeth': 50
+ };
+ }
+ },
+ 'bayonet': {
+ type: 'weapon',
+ cost: function() {
+ return {
+ 'scales': 500,
+ 'teeth': 250
+ };
+ }
+ },
+ 'alien alloy': {
+ type: 'good',
+ cost: function() {
+ return {
+ 'fur': 1500,
+ 'scales': 750,
+ 'teeth': 300
+ };
+ }
+ },
+ 'compass': {
+ type: 'upgrade',
+ maximum: 1,
+ cost: function() {
+ return {
+ fur: 400,
+ scales: 20,
+ teeth: 10
+ };
+ }
+ }
+ },
+
+ MiscItems: {
+ 'laser rifle': {
+ type: 'weapon'
+ }
+ },
+
+ name: _("Room"),
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ if(Engine._debug) {
+ this._ROOM_WARM_DELAY = 5000;
+ this._BUILDER_STATE_DELAY = 5000;
+ this._STOKE_COOLDOWN = 0;
+ this._NEED_WOOD_DELAY = 5000;
+ }
+
+ if(typeof $SM.get('features.location.room') == 'undefined') {
+ $SM.set('features.location.room', true);
+ $SM.set('game.builder.level', -1);
+ }
+
+ // If this is the first time playing, the fire is dead and it's freezing.
+ // Otherwise grab past save state temp and fire level.
+ $SM.set('game.temperature', $SM.get('game.temperature.value')===undefined?this.TempEnum.Freezing:$SM.get('game.temperature'));
+ $SM.set('game.fire', $SM.get('game.fire.value')===undefined?this.FireEnum.Dead:$SM.get('game.fire'));
+
+ // Create the room tab
+ this.tab = Header.addLocation(_("A Dark Room"), "room", Room);
+
+ // Create the Room panel
+ this.panel = $('
')
+ .attr('id', "roomPanel")
+ .addClass('location')
+ .appendTo('div#locationSlider');
+
+ Engine.updateSlider();
+
+ // Create the light button
+ new Button.Button({
+ id: 'lightButton',
+ text: _('light fire'),
+ click: Room.lightFire,
+ cooldown: Room._STOKE_COOLDOWN,
+ width: '80px',
+ cost: {'wood': 5}
+ }).appendTo('div#roomPanel');
+
+ // Create the stoke button
+ new Button.Button({
+ id: 'stokeButton',
+ text: _("stoke fire"),
+ click: Room.stokeFire,
+ cooldown: Room._STOKE_COOLDOWN,
+ width: '80px',
+ cost: {'wood': 1}
+ }).appendTo('div#roomPanel');
+
+ // Create the stores container
+ $('
').attr('id', 'storesContainer').appendTo('div#roomPanel');
+
+ //subscribe to stateUpdates
+ $.Dispatch('stateUpdate').subscribe(Room.handleStateUpdates);
+
+ Room.updateButton();
+ Room.updateStoresView();
+ Room.updateIncomeView();
+ Room.updateBuildButtons();
+
+ Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
+ Room._tempTimer = Engine.setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY);
+
+ /*
+ * Builder states:
+ * 0 - Approaching
+ * 1 - Collapsed
+ * 2 - Shivering
+ * 3 - Sleeping
+ * 4 - Helping
+ */
+ if($SM.get('game.builder.level') >= 0 && $SM.get('game.builder.level') < 3) {
+ Room._builderTimer = Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
+ }
+ if($SM.get('game.builder.level') == 1 && $SM.get('stores.wood', true) < 0) {
+ Engine.setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY);
+ }
+ Engine.setTimeout($SM.collectIncome, 1000);
+
+ Notifications.notify(Room, _("the room is {0}", Room.TempEnum.fromInt($SM.get('game.temperature.value')).text));
+ Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text));
+ },
+
+ options: {}, // Nothing for now
+
+ onArrival: function(transition_diff) {
+ Room.setTitle();
+ if(Room.changed) {
+ Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text));
+ Notifications.notify(Room, _("the room is {0}", Room.TempEnum.fromInt($SM.get('game.temperature.value')).text));
+ Room.changed = false;
+ }
+ if($SM.get('game.builder.level') == 3) {
+ $SM.add('game.builder.level', 1);
+ $SM.setIncome('builder', {
+ delay: 10,
+ stores: {'wood' : 2 }
+ });
+ Room.updateIncomeView();
+ Notifications.notify(Room, _("the stranger is standing by the fire. she says she can help. says she builds things."));
+ }
+
+ Engine.moveStoresView(null, transition_diff);
+ },
+
+ TempEnum: {
+ fromInt: function(value) {
+ for(var k in this) {
+ if(typeof this[k].value != 'undefined' && this[k].value == value) {
+ return this[k];
+ }
+ }
+ return null;
+ },
+ Freezing: { value: 0, text: _('freezing') },
+ Cold: { value: 1, text: _('cold') },
+ Mild: { value: 2, text: _('mild') },
+ Warm: { value: 3, text: _('warm') },
+ Hot: { value: 4, text: _('hot') }
+ },
+
+ FireEnum: {
+ fromInt: function(value) {
+ for(var k in this) {
+ if(typeof this[k].value != 'undefined' && this[k].value == value) {
+ return this[k];
+ }
+ }
+ return null;
+ },
+ Dead: { value: 0, text: _('dead') },
+ Smoldering: { value: 1, text: _('smoldering') },
+ Flickering: { value: 2, text: _('flickering') },
+ Burning: { value: 3, text: _('burning') },
+ Roaring: { value: 4, text: _('roaring') }
+ },
+
+ setTitle: function() {
+ var title = $SM.get('game.fire.value') < 2 ? _("A Dark Room") : _("A Firelit Room");
+ if(Engine.activeModule == this) {
+ document.title = title;
+ }
+ $('div#location_room').text(title);
+ },
+
+ updateButton: function() {
+ var light = $('#lightButton.button');
+ var stoke = $('#stokeButton.button');
+ if($SM.get('game.fire.value') == Room.FireEnum.Dead.value && stoke.css('display') != 'none') {
+ stoke.hide();
+ light.show();
+ if(stoke.hasClass('disabled')) {
+ Button.cooldown(light);
+ }
+ } else if(light.css('display') != 'none') {
+ stoke.show();
+ light.hide();
+ if(light.hasClass('disabled')) {
+ Button.cooldown(stoke);
+ }
+ }
+
+ if(!$SM.get('stores.wood')) {
+ light.addClass('free');
+ stoke.addClass('free');
+ } else {
+ light.removeClass('free');
+ stoke.removeClass('free');
+ }
+ },
+
+ _fireTimer: null,
+ _tempTimer: null,
+ lightFire: function() {
+ var wood = $SM.get('stores.wood');
+ if(wood < 5) {
+ Notifications.notify(Room, _("not enough wood to get the fire going"));
+ Button.clearCooldown($('#lightButton.button'));
+ return;
+ } else if(wood > 4) {
+ $SM.set('stores.wood', wood - 5);
+ }
+ $SM.set('game.fire', Room.FireEnum.Burning);
+ Room.onFireChange();
+ },
+
+ stokeFire: function() {
+ var wood = $SM.get('stores.wood');
+ if(wood === 0) {
+ Notifications.notify(Room, _("the wood has run out"));
+ Button.clearCooldown($('#stokeButton.button'));
+ return;
+ }
+ if(wood > 0) {
+ $SM.set('stores.wood', wood - 1);
+ }
+ if($SM.get('game.fire.value') < 4) {
+ $SM.set('game.fire', Room.FireEnum.fromInt($SM.get('game.fire.value') + 1));
+ }
+ Room.onFireChange();
+ },
+
+ onFireChange: function() {
+ if(Engine.activeModule != Room) {
+ Room.changed = true;
+ }
+ Notifications.notify(Room, _("the fire is {0}", Room.FireEnum.fromInt($SM.get('game.fire.value')).text), true);
+ if($SM.get('game.fire.value') > 1 && $SM.get('game.builder.level') < 0) {
+ $SM.set('game.builder.level', 0);
+ Notifications.notify(Room, _("the light from the fire spills from the windows, out into the dark"));
+ Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
+ }
+ window.clearTimeout(Room._fireTimer);
+ Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
+ Room.updateButton();
+ Room.setTitle();
+ },
+
+ coolFire: function() {
+ var wood = $SM.get('stores.wood');
+ if($SM.get('game.fire.value') <= Room.FireEnum.Flickering.value &&
+ $SM.get('game.builder.level') > 3 && wood > 0) {
+ Notifications.notify(Room, _("builder stokes the fire"), true);
+ $SM.set('stores.wood', wood - 1);
+ $SM.set('game.fire',Room.FireEnum.fromInt($SM.get('game.fire.value') + 1));
+ }
+ if($SM.get('game.fire.value') > 0) {
+ $SM.set('game.fire',Room.FireEnum.fromInt($SM.get('game.fire.value') - 1));
+ Room._fireTimer = Engine.setTimeout(Room.coolFire, Room._FIRE_COOL_DELAY);
+ Room.onFireChange();
+ }
+ },
+
+ adjustTemp: function() {
+ var old = $SM.get('game.temperature.value');
+ if($SM.get('game.temperature.value') > 0 && $SM.get('game.temperature.value') > $SM.get('game.fire.value')) {
+ $SM.set('game.temperature',Room.TempEnum.fromInt($SM.get('game.temperature.value') - 1));
+ Notifications.notify(Room, _("the room is {0}" , Room.TempEnum.fromInt($SM.get('game.temperature.value')).text), true);
+ }
+ if($SM.get('game.temperature.value') < 4 && $SM.get('game.temperature.value') < $SM.get('game.fire.value')) {
+ $SM.set('game.temperature', Room.TempEnum.fromInt($SM.get('game.temperature.value') + 1));
+ Notifications.notify(Room, _("the room is {0}" , Room.TempEnum.fromInt($SM.get('game.temperature.value')).text), true);
+ }
+ if($SM.get('game.temperature.value') != old) {
+ Room.changed = true;
+ }
+ Room._tempTimer = Engine.setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY);
+ },
+
+ unlockForest: function() {
+ $SM.set('stores.wood', 4);
+ Outside.init();
+ Notifications.notify(Room, _("the wind howls outside"));
+ Notifications.notify(Room, _("the wood is running out"));
+ Engine.event('progress', 'outside');
+ },
+
+ updateBuilderState: function() {
+ var lBuilder = $SM.get('game.builder.level');
+ if(lBuilder === 0) {
+ Notifications.notify(Room, _("a ragged stranger stumbles through the door and collapses in the corner"));
+ lBuilder = $SM.setget('game.builder.level', 1);
+ Engine.setTimeout(Room.unlockForest, Room._NEED_WOOD_DELAY);
+ }
+ else if(lBuilder < 3 && $SM.get('game.temperature.value') >= Room.TempEnum.Warm.value) {
+ var msg = "";
+ switch(lBuilder) {
+ case 1:
+ msg = _("the stranger shivers, and mumbles quietly. her words are unintelligible.");
+ break;
+ case 2:
+ msg = _("the stranger in the corner stops shivering. her breathing calms.");
+ break;
+ }
+ Notifications.notify(Room, msg);
+ if(lBuilder < 3) {
+ lBuilder = $SM.setget('game.builder.level', lBuilder + 1);
+ }
+ }
+ if(lBuilder < 3) {
+ Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
+ }
+ Engine.saveGame();
+ },
+
+ updateStoresView: function() {
+ var stores = $('div#stores');
+ var weapons = $('div#weapons');
+ var needsAppend = false, wNeedsAppend = false, newRow = false;
+ if(stores.length === 0) {
+ stores = $('
').attr({
+ id: 'stores'
+ }).css('opacity', 0);
+ needsAppend = true;
+ }
+ if(weapons.length === 0) {
+ weapons = $('
').attr({
+ id: 'weapons'
+ }).css('opacity', 0);
+ wNeedsAppend = true;
+ }
+ for(var k in $SM.get('stores')) {
+
+ var type = null;
+ if(Room.Craftables[k]) {
+ type = Room.Craftables[k].type;
+ } else if(Room.TradeGoods[k]) {
+ type = Room.TradeGoods[k].type;
+ } else if (Room.MiscItems[k]) {
+ type = Room.MiscItems[k].type;
+ }
+
+ var location;
+ switch(type) {
+ case 'upgrade':
+ // Don't display upgrades on the Room screen
+ continue;
+ case 'weapon':
+ location = weapons;
+ break;
+ default:
+ location = stores;
+ break;
+ }
+
+ var id = "row_" + k.replace(' ', '-');
+ var row = $('div#' + id, location);
+ 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 = 0;
+ $SM.set('stores["'+k+'"]', 0);
+ }
+
+
+ // thieves?
+ if(typeof $SM.get('game.thieves') == 'undefined' && num > 5000 && $SM.get('features.location.world')) {
+ $SM.startThieves();
+ }
+
+ if(row.length === 0 && num > 0) {
+ row = $('
').attr('id', id).addClass('storeRow');
+ $('
').addClass('row_key').text(_(k)).appendTo(row);
+ $('
').addClass('row_val').text(Math.floor(num)).appendTo(row);
+ $('
').addClass('clear').appendTo(row);
+ var curPrev = null;
+ location.children().each(function(i) {
+ var child = $(this);
+ var cName = child.attr('id').substring(4).replace('-', ' ');
+ if(cName < k && (curPrev == null || cName > curPrev)) {
+ curPrev = cName;
+ }
+ });
+ if(curPrev == null) {
+ row.prependTo(location);
+ } else {
+ row.insertAfter(location.find('#row_' + curPrev.replace(' ', '-')));
+ }
+ newRow = true;
+ } else if(num>= 0){
+ $('div#' + row.attr('id') + ' > div.row_val', location).text(Math.floor(num));
+ }
+ }
+
+ if(needsAppend && stores.children().length > 0) {
+ stores.appendTo('div#storesContainer');
+ stores.animate({opacity: 1}, 300, 'linear');
+ }
+
+ if(wNeedsAppend && weapons.children().length > 0) {
+ weapons.appendTo('div#storesContainer');
+ weapons.animate({opacity: 1}, 300, 'linear');
+ }
+
+ if(newRow) {
+ Room.updateIncomeView();
+ }
+
+ if($("div#outsidePanel").length) {
+ Outside.updateVillage();
+ }
+ },
+
+ updateIncomeView: function() {
+ var stores = $('div#stores');
+ 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 $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);
+ $('
')
+ .addClass('row_val')
+ .text(Engine.getIncomeMsg(income.stores[store], income.delay))
+ .appendTo(tt);
+ }
+ }
+ }
+ if(tt.children().length > 0) {
+ tt.appendTo(el);
+ }
+ });
+ },
+
+ buy: function(buyBtn) {
+ var thing = $(buyBtn).attr('buildThing');
+ var good = Room.TradeGoods[thing];
+ var numThings = $SM.get('stores["'+thing+'"]', true);
+ if(numThings < 0) numThings = 0;
+ if(good.maximum <= numThings) {
+ return;
+ }
+
+ var storeMod = {};
+ var cost = good.cost();
+ for(var k in cost) {
+ var have = $SM.get('stores["'+k+'"]', true);
+ if(have < cost[k]) {
+ Notifications.notify(Room, _("not enough " + k));
+ return false;
+ } else {
+ storeMod[k] = have - cost[k];
+ }
+ }
+ $SM.setM('stores', storeMod);
+
+ Notifications.notify(Room, good.buildMsg);
+
+ $SM.add('stores["'+thing+'"]', 1);
+
+ if(thing == 'compass') {
+ Path.openPath();
+ }
+ },
+
+ build: function(buildBtn) {
+ var thing = $(buildBtn).attr('buildThing');
+ if($SM.get('game.temperature.value') <= Room.TempEnum.Cold.value) {
+ Notifications.notify(Room, _("builder just shivers"));
+ return false;
+ }
+ var craftable = Room.Craftables[thing];
+
+ var numThings = 0;
+ switch(craftable.type) {
+ case 'good':
+ case 'weapon':
+ case 'tool':
+ case 'upgrade':
+ numThings = $SM.get('stores["'+thing+'"]', true);
+ break;
+ case 'building':
+ numThings = $SM.get('game.buildings["'+thing+'"]', true);
+ break;
+ }
+
+ if(numThings < 0) numThings = 0;
+ if(craftable.maximum <= numThings) {
+ return;
+ }
+
+ var storeMod = {};
+ var cost = craftable.cost();
+ for(var k in cost) {
+ var have = $SM.get('stores["'+k+'"]', true);
+ if(have < cost[k]) {
+ Notifications.notify(Room, _("not enough "+k));
+ return false;
+ } else {
+ storeMod[k] = have - cost[k];
+ }
+ }
+ $SM.setM('stores', storeMod);
+
+ Notifications.notify(Room, craftable.buildMsg);
+
+ switch(craftable.type) {
+ case 'good':
+ case 'weapon':
+ case 'upgrade':
+ case 'tool':
+ $SM.add('stores["'+thing+'"]', 1);
+ break;
+ case 'building':
+ $SM.add('game.buildings["'+thing+'"]', 1);
+ break;
+ }
+ },
+
+ needsWorkshop: function(type) {
+ return type == 'weapon' || type == 'upgrade' || type =='tool';
+ },
+
+ craftUnlocked: function(thing) {
+ if(Room.buttons[thing]) {
+ return true;
+ }
+ if($SM.get('game.builder.level') < 4) return false;
+ var craftable = Room.Craftables[thing];
+ if(Room.needsWorkshop(craftable.type) && $SM.get('game.buildings["'+'workshop'+'"]', true) === 0) return false;
+ var cost = craftable.cost();
+
+ //show button if one has already been built
+ if($SM.get('game.buildings["'+thing+'"]') > 0){
+ Room.buttons[thing] = true;
+ return true;
+ }
+ // Show buttons if we have at least 1/2 the wood, and all other components have been seen.
+ if($SM.get('stores.wood', true) < cost['wood'] * 0.5) {
+ return false;
+ }
+ for(var c in cost) {
+ if(!$SM.get('stores["'+c+'"]')) {
+ return false;
+ }
+ }
+
+ Room.buttons[thing] = true;
+ //don't notify if it has already been built before
+ if(!$SM.get('game.buildings["'+thing+'"]')){
+ Notifications.notify(Room, craftable.availableMsg);
+ }
+ return true;
+ },
+
+ buyUnlocked: function(thing) {
+ if(Room.buttons[thing]) {
+ return true;
+ } else if($SM.get('game.buildings["trading post"]', true) > 0) {
+ if(thing == 'compass' || typeof $SM.get('stores["'+thing+'"]') != 'undefined') {
+ // Allow the purchase of stuff once you've seen it
+ return true;
+ }
+ }
+ return false;
+ },
+
+ updateBuildButtons: function() {
+ var buildSection = $('#buildBtns');
+ var needsAppend = false;
+ if(buildSection.length === 0) {
+ buildSection = $('
').attr('id', 'buildBtns').css('opacity', 0);
+ needsAppend = true;
+ }
+
+ var craftSection = $('#craftBtns');
+ var cNeedsAppend = false;
+ if(craftSection.length === 0 && $SM.get('game.buildings["workshop"]', true) > 0) {
+ craftSection = $('
').attr('id', 'craftBtns').css('opacity', 0);
+ cNeedsAppend = true;
+ }
+
+ var buySection = $('#buyBtns');
+ var bNeedsAppend = false;
+ if(buySection.length === 0 && $SM.get('game.buildings["trading post"]', true) > 0) {
+ buySection = $('
').attr('id', 'buyBtns').css('opacity', 0);
+ bNeedsAppend = true;
+ }
+
+ for(var k in Room.Craftables) {
+ craftable = Room.Craftables[k];
+ var max = $SM.num(k, craftable) + 1 > craftable.maximum;
+ if(craftable.button == null) {
+ if(Room.craftUnlocked(k)) {
+ var loc = Room.needsWorkshop(craftable.type) ? craftSection : buildSection;
+ craftable.button = new Button.Button({
+ id: 'build_' + k,
+ cost: craftable.cost(),
+ text: _(k),
+ click: Room.build,
+ width: '80px',
+ ttPos: loc.children().length > 10 ? 'top right' : 'bottom right'
+ }).css('opacity', 0).attr('buildThing', k).appendTo(loc).animate({opacity: 1}, 300, 'linear');
+ }
+ } else {
+ // refresh the tooltip
+ var costTooltip = $('.tooltip', craftable.button);
+ costTooltip.empty();
+ var cost = craftable.cost();
+ for(var k in cost) {
+ $("
").addClass('row_key').text(_(k)).appendTo(costTooltip);
+ $("
").addClass('row_val').text(cost[k]).appendTo(costTooltip);
+ }
+ if(max && !craftable.button.hasClass('disabled')) {
+ Notifications.notify(Room, craftable.maxMsg);
+ }
+ }
+ if(max) {
+ Button.setDisabled(craftable.button, true);
+ } else {
+ Button.setDisabled(craftable.button, false);
+ }
+ }
+
+ for(var k in Room.TradeGoods) {
+ good = Room.TradeGoods[k];
+ var max = $SM.num(k, good) + 1 > good.maximum;
+ if(good.button == null) {
+ if(Room.buyUnlocked(k)) {
+ good.button = new Button.Button({
+ id: 'build_' + k,
+ cost: good.cost(),
+ text: _(k),
+ click: Room.buy,
+ width: '80px'
+ }).css('opacity', 0).attr('buildThing', k).appendTo(buySection).animate({opacity:1}, 300, 'linear');
+ }
+ } else {
+ // refresh the tooltip
+ var costTooltip = $('.tooltip', good.button);
+ costTooltip.empty();
+ var cost = good.cost();
+ for(var k in cost) {
+ $("
").addClass('row_key').text(_(k)).appendTo(costTooltip);
+ $("
").addClass('row_val').text(cost[k]).appendTo(costTooltip);
+ }
+ if(max && !good.button.hasClass('disabled')) {
+ Notifications.notify(Room, good.maxMsg);
+ }
+ }
+ if(max) {
+ Button.setDisabled(good.button, true);
+ } else {
+ Button.setDisabled(good.button, false);
+ }
+ }
+
+ if(needsAppend && buildSection.children().length > 0) {
+ buildSection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
+ }
+ if(cNeedsAppend && craftSection.children().length > 0) {
+ craftSection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
+ }
+ if(bNeedsAppend && buildSection.children().length > 0) {
+ buySection.appendTo('div#roomPanel').animate({opacity: 1}, 300, 'linear');
+ }
+ },
+
+ handleStateUpdates: function(e){
+ if(e.category == 'stores'){
+ Room.updateStoresView();
+ Room.updateBuildButtons();
+ } else if(e.category == 'income'){
+ Room.updateStoresView();
+ Room.updateIncomeView();
+ } else if(e.stateName.indexOf('game.buildings') === 0){
+ Room.updateBuildButtons();
+ }
+ }
+};
diff --git a/script/space.js b/script/space.js
index 27ae696..d9d91b8 100644
--- a/script/space.js
+++ b/script/space.js
@@ -1,509 +1,509 @@
-/**
- * Module that registers spaaaaaaaaace!
- */
-var Space = {
- SHIP_SPEED: 3,
- BASE_ASTEROID_DELAY: 500,
- BASE_ASTEROID_SPEED: 1500,
- FTB_SPEED: 60000,
- STAR_WIDTH: 3000,
- STAR_HEIGHT: 3000,
- NUM_STARS: 200,
- STAR_SPEED: 60000,
- FRAME_DELAY: 100,
-
- stars: null,
- backStars: null,
- ship: null,
- lastMove: null,
- done: false,
- shipX: null,
- shipY: null,
-
- hull: 0,
-
- name: "Space",
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- // Create the Space panel
- this.panel = $('
').attr('id', "spacePanel")
- .addClass('location')
- .appendTo('#outerSlider');
-
- // Create the ship
- Space.ship = $('
').text("@").attr('id', 'ship').appendTo(this.panel);
-
- // Create the hull display
- var h = $('
').attr('id', 'hullRemaining').appendTo(this.panel);
- $('
').addClass('row_key').text(_('hull: ')).appendTo(h);
- $('
').addClass('row_val').appendTo(h);
-
- //subscribe to stateUpdates
- $.Dispatch('stateUpdate').subscribe(Space.handleStateUpdates);
- },
-
- options: {}, // Nothing for now
-
- onArrival: function() {
- Space.done = false;
- Engine.keyLock = false;
- Space.hull = Ship.getMaxHull();
- Space.altitude = 0;
- Space.setTitle();
- Space.updateHull();
-
- Space.up =
- Space.down =
- Space.left =
- Space.right = false;
-
- Space.ship.css({
- top: '350px',
- left: '350px'
- });
- Space.startAscent();
- Space._shipTimer = setInterval(Space.moveShip, 33);
- },
-
- setTitle: function() {
- if(Engine.activeModule == this) {
- var t;
- if(Space.altitude < 10) {
- t = _("Troposphere");
- } else if(Space.altitude < 20) {
- t = _("Stratosphere");
- } else if(Space.altitude < 30) {
- t = _("Mesosphere");
- } else if(Space.altitude < 45) {
- t = _("Thermosphere");
- } else if(Space.altitude < 60){
- t = _("Exosphere");
- } else {
- t = _("Space");
- }
- document.title = t;
- }
- },
-
- getSpeed: function() {
- return Space.SHIP_SPEED + $SM.get('game.spaceShip.thrusters');
- },
-
- updateHull: function() {
- $('div#hullRemaining div.row_val', Space.panel).text(Space.hull + '/' + Ship.getMaxHull());
- },
-
- createAsteroid: function(noNext) {
- var r = Math.random();
- var c;
- if(r < 0.2)
- c = '#';
- else if(r < 0.4)
- c = '$';
- else if(r < 0.6)
- c = '%';
- else if(r < 0.8)
- c = '&';
- else
- c = 'H';
-
- var x = Math.floor(Math.random() * 700);
- var a = $('
').addClass('asteroid').text(c).appendTo('#spacePanel').css('left', x + 'px');
- a.data({
- xMin: x,
- xMax: x + a.width(),
- height: a.height()
- });
- a.animate({
- top: '740px'
- }, {
- duration: Space.BASE_ASTEROID_SPEED - Math.floor(Math.random() * (Space.BASE_ASTEROID_SPEED * 0.65)),
- easing: 'linear',
- progress: function() {
- // Collision detection
- var t = $(this);
- if(t.data('xMin') <= Space.shipX && t.data('xMax') >= Space.shipX) {
- var aY = t.css('top');
- aY = parseFloat(aY.substring(0, aY.length - 2));
-
- if(aY <= Space.shipY && aY + t.data('height') >= Space.shipY) {
- // Collision
- Engine.log('collision');
- t.remove();
- Space.hull--;
- Space.updateHull();
- if(Space.hull === 0) {
- Space.crash();
- }
- }
- }
- },
- complete: function() {
- $(this).remove();
- }
- });
- if(!noNext) {
-
- // Harder
- if(Space.altitude > 10) {
- Space.createAsteroid(true);
- }
-
- // HARDER
- if(Space.altitude > 20) {
- Space.createAsteroid(true);
- Space.createAsteroid(true);
- }
-
- // HAAAAAARDERRRRR!!!!1
- if(Space.altitude > 40) {
- Space.createAsteroid(true);
- Space.createAsteroid(true);
- }
-
- if(!Space.done) {
- Engine.setTimeout(Space.createAsteroid, 1000 - (Space.altitude * 10));
- }
- }
- },
-
- moveShip: function() {
- var x = Space.ship.css('left');
- x = parseFloat(x.substring(0, x.length - 2));
- var y = Space.ship.css('top');
- y = parseFloat(y.substring(0, y.length - 2));
-
- var dx = 0, dy = 0;
-
- if(Space.up) {
- dy -= Space.getSpeed();
- } else if(Space.down) {
- dy += Space.getSpeed();
- }
- if(Space.left) {
- dx -= Space.getSpeed();
- } else if(Space.right) {
- dx += Space.getSpeed();
- }
-
- if(dx !== 0 && dy !== 0) {
- dx = dx / Math.sqrt(2);
- dy = dy / Math.sqrt(2);
- }
-
- if(Space.lastMove != null) {
- var dt = Date.now() - Space.lastMove;
- dx *= dt / 33;
- dy *= dt / 33;
- }
-
- x = x + dx;
- y = y + dy;
- if(x < 10) {
- x = 10;
- } else if(x > 690) {
- x = 690;
- }
- if(y < 10) {
- y = 10;
- } else if(y > 690) {
- y = 690;
- }
-
- Space.shipX = x;
- Space.shipY = y;
-
- Space.ship.css({
- left: x + 'px',
- top: y + 'px'
- });
-
- Space.lastMove = Date.now();
- },
-
- startAscent: function() {
- var body_color;
- var to_color;
- if (Engine.isLightsOff()) {
- body_color = '#272823';
- to_color = '#EEEEEE';
- }
- else {
- body_color = '#FFFFFF';
- to_color = '#000000';
- }
-
- $('body').addClass('noMask').css({backgroundColor: body_color}).animate({
- backgroundColor: to_color
- }, {
- duration: Space.FTB_SPEED,
- easing: 'linear',
- progress: function() {
- var cur = $('body').css('background-color');
- var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
- cur.substring(3, cur.length - 1) + ', 1) 100%)';
- $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
- },
- complete: Space.endGame
- });
- Space.drawStars();
- Space._timer = setInterval(function() {
- Space.altitude += 1;
- if(Space.altitude % 10 === 0) {
- Space.setTitle();
- }
- if(Space.altitude > 60) {
- clearInterval(Space._timer);
- }
- }, 1000);
-
- Space._panelTimeout = Engine.setTimeout(function() {
- if (Engine.isLightsOff())
- $('#spacePanel, .menu, select.menuBtn').animate({color: '#272823'}, 500, 'linear');
- else
- $('#spacePanel, .menu, select.menuBtn').animate({color: 'white'}, 500, 'linear');
- }, Space.FTB_SPEED / 2);
-
- Space.createAsteroid();
- },
-
- drawStars: function(duration) {
- var starsContainer = $('
').attr('id', 'starsContainer').appendTo('body');
- Space.stars = $('
').css('bottom', '0px').attr('id', 'stars').appendTo(starsContainer);
- var s1 = $('
').css({
- width: Space.STAR_WIDTH + 'px',
- height: Space.STAR_HEIGHT + 'px'
- });
- var s2 = s1.clone();
- Space.stars.append(s1).append(s2);
- Space.drawStarAsync(s1, s2, 0);
- Space.stars.data('speed', Space.STAR_SPEED);
- Space.startAnimation(Space.stars);
-
- Space.starsBack = $('
').css('bottom', '0px').attr('id', 'starsBack').appendTo(starsContainer);
- s1 = $('
').css({
- width: Space.STAR_WIDTH + 'px',
- height: Space.STAR_HEIGHT + 'px'
- });
- s2 = s1.clone();
- Space.starsBack.append(s1).append(s2);
- Space.drawStarAsync(s1, s2, 0);
- Space.starsBack.data('speed', Space.STAR_SPEED * 2);
- Space.startAnimation(Space.starsBack);
- },
-
- startAnimation: function(el) {
- el.animate({bottom: '-3000px'}, el.data('speed'), 'linear', function() {
- $(this).css('bottom', '0px');
- Space.startAnimation($(this));
- });
- },
-
- drawStarAsync: function(el, el2, num) {
- var top = Math.floor(Math.random() * Space.STAR_HEIGHT) + 'px';
- var left = Math.floor(Math.random() * Space.STAR_WIDTH) + 'px';
- $('
').text('.').addClass('star').css({
- top: top,
- left: left
- }).appendTo(el);
- $('
').text('.').addClass('star').css({
- top: top,
- left: left
- }).appendTo(el2);
- if(num < Space.NUM_STARS) {
- Engine.setTimeout(function() { Space.drawStarAsync(el, el2, num + 1); }, 100);
- }
- },
-
- crash: function() {
- if(Space.done) return;
- Engine.keyLock = true;
- Space.done = true;
- clearInterval(Space._timer);
- clearInterval(Space._shipTimer);
- clearTimeout(Space._panelTimeout);
- var body_color;
- if (Engine.isLightsOff())
- body_color = '#272823';
- else
- body_color = '#FFFFFF';
- // Craaaaash!
- $('body').removeClass('noMask').stop().animate({
- backgroundColor: body_color
- }, {
- duration: 300,
- progress: function() {
- var cur = $('body').css('background-color');
- var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
- cur.substring(3, cur.length - 1) + ', 1) 100%)';
- $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
- },
- complete: function() {
- Space.stars.remove();
- Space.starsBack.remove();
- Space.stars = Space.starsBack = null;
- $('#starsContainer').remove();
- $('body').attr('style', '');
- $('#notifyGradient').attr('style', '');
- $('#spacePanel').attr('style', '');
- }
- });
- $('.menu, select.menuBtn').animate({color: '#666'}, 300, 'linear');
- $('#outerSlider').animate({top: '0px'}, 300, 'linear');
- Engine.activeModule = Ship;
- Ship.onArrival();
- Button.cooldown($('#liftoffButton'));
- Engine.event('progress', 'crash');
- },
-
- endGame: function() {
- if(Space.done) return;
- Engine.event('progress', 'win');
- Space.done = true;
- clearInterval(Space._timer);
- clearInterval(Space._shipTimer);
- clearTimeout(Engine._saveTimer);
- clearTimeout(Outside._popTimeout);
- clearTimeout(Engine._incomeTimeout);
- clearTimeout(Events._eventTimeout);
- clearTimeout(Room._fireTimer);
- clearTimeout(Room._tempTimer);
- for(var k in Room.Craftables) {
- Room.Craftables[k].button = null;
- }
- for(var k in Room.TradeGoods) {
- Room.TradeGoods[k].button = null;
- }
- delete Outside._popTimeout;
-
- $('#hullRemaining', Space.panel).animate({opacity: 0}, 500, 'linear');
- Space.ship.animate({
- top: '350px',
- left: '240px'
- }, 3000, 'linear', function() {
- Engine.setTimeout(function() {
- Space.ship.animate({
- top: '-100px'
- }, 200, 'linear', function() {
- // Restart everything! Play FOREVER!
- $('#outerSlider').css({'left': '0px', 'top': '0px'});
- $('#locationSlider, #worldPanel, #spacePanel, #notifications').remove();
- $('#header').empty();
- Engine.setTimeout(function() {
- $('body').stop();
- var container_color;
- if (Engine.isLightsOff())
- container_color = '#EEE';
- else
- container_color = '#000';
- $('#starsContainer').animate({
- opacity: 0,
- 'background-color': container_color
- }, {
- duration: 2000,
- progress: function() {
- var cur = $('body').css('background-color');
- var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
- cur.substring(3, cur.length - 1) + ', 1) 100%)';
- $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
- },
- complete: function() {
- Engine.GAME_OVER = true;
- Score.save();
- Prestige.save();
-
- $('
')
- .addClass('centerCont')
- .appendTo('body');
- $('')
- .addClass('endGame')
- .text(_('score for this game: {0}', Score.calculateScore()))
- .appendTo('.centerCont')
- .animate({opacity:1},1500);
- $('
')
- .appendTo('.centerCont');
- $('')
- .addClass('endGame')
- .text(_('total score: {0}', Prestige.get().score))
- .appendTo('.centerCont')
- .animate({opacity:1},1500);
- $('
')
- .appendTo('.centerCont');
- $('
')
- .appendTo('.centerCont');
- $('#starsContainer').remove();
- $('#content, #notifications').remove();
- $('')
- .addClass('endGame endGameRestart')
- .text(_('restart.'))
- .click(Engine.confirmDelete)
- .appendTo('.centerCont')
- .animate({opacity:1},1500);
- Engine.options = {};
- Engine.deleteSave(true);
- }
- });
- }, 2000);
- });
- }, 2000);
- });
- },
-
- keyDown: function(event) {
- switch(event.which) {
- case 38: // Up
- case 87:
- Space.up = true;
- Engine.log('up on');
- break;
- case 40: // Down
- case 83:
- Space.down = true;
- Engine.log('down on');
- break;
- case 37: // Left
- case 65:
- Space.left = true;
- Engine.log('left on');
- break;
- case 39: // Right
- case 68:
- Space.right = true;
- Engine.log('right on');
- break;
- }
- },
-
- keyUp: function(event) {
- switch(event.which) {
- case 38: // Up
- case 87:
- Space.up = false;
- Engine.log('up off');
- break;
- case 40: // Down
- case 83:
- Space.down = false;
- Engine.log('down off');
- break;
- case 37: // Left
- case 65:
- Space.left = false;
- Engine.log('left off');
- break;
- case 39: // Right
- case 68:
- Space.right = false;
- Engine.log('right off');
- break;
- }
- },
-
- handleStateUpdates: function(e){
-
- }
-};
+/**
+ * Module that registers spaaaaaaaaace!
+ */
+var Space = {
+ SHIP_SPEED: 3,
+ BASE_ASTEROID_DELAY: 500,
+ BASE_ASTEROID_SPEED: 1500,
+ FTB_SPEED: 60000,
+ STAR_WIDTH: 3000,
+ STAR_HEIGHT: 3000,
+ NUM_STARS: 200,
+ STAR_SPEED: 60000,
+ FRAME_DELAY: 100,
+
+ stars: null,
+ backStars: null,
+ ship: null,
+ lastMove: null,
+ done: false,
+ shipX: null,
+ shipY: null,
+
+ hull: 0,
+
+ name: "Space",
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ // Create the Space panel
+ this.panel = $('').attr('id', "spacePanel")
+ .addClass('location')
+ .appendTo('#outerSlider');
+
+ // Create the ship
+ Space.ship = $('
').text("@").attr('id', 'ship').appendTo(this.panel);
+
+ // Create the hull display
+ var h = $('
').attr('id', 'hullRemaining').appendTo(this.panel);
+ $('
').addClass('row_key').text(_('hull: ')).appendTo(h);
+ $('
').addClass('row_val').appendTo(h);
+
+ //subscribe to stateUpdates
+ $.Dispatch('stateUpdate').subscribe(Space.handleStateUpdates);
+ },
+
+ options: {}, // Nothing for now
+
+ onArrival: function() {
+ Space.done = false;
+ Engine.keyLock = false;
+ Space.hull = Ship.getMaxHull();
+ Space.altitude = 0;
+ Space.setTitle();
+ Space.updateHull();
+
+ Space.up =
+ Space.down =
+ Space.left =
+ Space.right = false;
+
+ Space.ship.css({
+ top: '350px',
+ left: '350px'
+ });
+ Space.startAscent();
+ Space._shipTimer = setInterval(Space.moveShip, 33);
+ },
+
+ setTitle: function() {
+ if(Engine.activeModule == this) {
+ var t;
+ if(Space.altitude < 10) {
+ t = _("Troposphere");
+ } else if(Space.altitude < 20) {
+ t = _("Stratosphere");
+ } else if(Space.altitude < 30) {
+ t = _("Mesosphere");
+ } else if(Space.altitude < 45) {
+ t = _("Thermosphere");
+ } else if(Space.altitude < 60){
+ t = _("Exosphere");
+ } else {
+ t = _("Space");
+ }
+ document.title = t;
+ }
+ },
+
+ getSpeed: function() {
+ return Space.SHIP_SPEED + $SM.get('game.spaceShip.thrusters');
+ },
+
+ updateHull: function() {
+ $('div#hullRemaining div.row_val', Space.panel).text(Space.hull + '/' + Ship.getMaxHull());
+ },
+
+ createAsteroid: function(noNext) {
+ var r = Math.random();
+ var c;
+ if(r < 0.2)
+ c = '#';
+ else if(r < 0.4)
+ c = '$';
+ else if(r < 0.6)
+ c = '%';
+ else if(r < 0.8)
+ c = '&';
+ else
+ c = 'H';
+
+ var x = Math.floor(Math.random() * 700);
+ var a = $('
').addClass('asteroid').text(c).appendTo('#spacePanel').css('left', x + 'px');
+ a.data({
+ xMin: x,
+ xMax: x + a.width(),
+ height: a.height()
+ });
+ a.animate({
+ top: '740px'
+ }, {
+ duration: Space.BASE_ASTEROID_SPEED - Math.floor(Math.random() * (Space.BASE_ASTEROID_SPEED * 0.65)),
+ easing: 'linear',
+ progress: function() {
+ // Collision detection
+ var t = $(this);
+ if(t.data('xMin') <= Space.shipX && t.data('xMax') >= Space.shipX) {
+ var aY = t.css('top');
+ aY = parseFloat(aY.substring(0, aY.length - 2));
+
+ if(aY <= Space.shipY && aY + t.data('height') >= Space.shipY) {
+ // Collision
+ Engine.log('collision');
+ t.remove();
+ Space.hull--;
+ Space.updateHull();
+ if(Space.hull === 0) {
+ Space.crash();
+ }
+ }
+ }
+ },
+ complete: function() {
+ $(this).remove();
+ }
+ });
+ if(!noNext) {
+
+ // Harder
+ if(Space.altitude > 10) {
+ Space.createAsteroid(true);
+ }
+
+ // HARDER
+ if(Space.altitude > 20) {
+ Space.createAsteroid(true);
+ Space.createAsteroid(true);
+ }
+
+ // HAAAAAARDERRRRR!!!!1
+ if(Space.altitude > 40) {
+ Space.createAsteroid(true);
+ Space.createAsteroid(true);
+ }
+
+ if(!Space.done) {
+ Engine.setTimeout(Space.createAsteroid, 1000 - (Space.altitude * 10));
+ }
+ }
+ },
+
+ moveShip: function() {
+ var x = Space.ship.css('left');
+ x = parseFloat(x.substring(0, x.length - 2));
+ var y = Space.ship.css('top');
+ y = parseFloat(y.substring(0, y.length - 2));
+
+ var dx = 0, dy = 0;
+
+ if(Space.up) {
+ dy -= Space.getSpeed();
+ } else if(Space.down) {
+ dy += Space.getSpeed();
+ }
+ if(Space.left) {
+ dx -= Space.getSpeed();
+ } else if(Space.right) {
+ dx += Space.getSpeed();
+ }
+
+ if(dx !== 0 && dy !== 0) {
+ dx = dx / Math.sqrt(2);
+ dy = dy / Math.sqrt(2);
+ }
+
+ if(Space.lastMove != null) {
+ var dt = Date.now() - Space.lastMove;
+ dx *= dt / 33;
+ dy *= dt / 33;
+ }
+
+ x = x + dx;
+ y = y + dy;
+ if(x < 10) {
+ x = 10;
+ } else if(x > 690) {
+ x = 690;
+ }
+ if(y < 10) {
+ y = 10;
+ } else if(y > 690) {
+ y = 690;
+ }
+
+ Space.shipX = x;
+ Space.shipY = y;
+
+ Space.ship.css({
+ left: x + 'px',
+ top: y + 'px'
+ });
+
+ Space.lastMove = Date.now();
+ },
+
+ startAscent: function() {
+ var body_color;
+ var to_color;
+ if (Engine.isLightsOff()) {
+ body_color = '#272823';
+ to_color = '#EEEEEE';
+ }
+ else {
+ body_color = '#FFFFFF';
+ to_color = '#000000';
+ }
+
+ $('body').addClass('noMask').css({backgroundColor: body_color}).animate({
+ backgroundColor: to_color
+ }, {
+ duration: Space.FTB_SPEED,
+ easing: 'linear',
+ progress: function() {
+ var cur = $('body').css('background-color');
+ var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
+ cur.substring(3, cur.length - 1) + ', 1) 100%)';
+ $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
+ },
+ complete: Space.endGame
+ });
+ Space.drawStars();
+ Space._timer = setInterval(function() {
+ Space.altitude += 1;
+ if(Space.altitude % 10 === 0) {
+ Space.setTitle();
+ }
+ if(Space.altitude > 60) {
+ clearInterval(Space._timer);
+ }
+ }, 1000);
+
+ Space._panelTimeout = Engine.setTimeout(function() {
+ if (Engine.isLightsOff())
+ $('#spacePanel, .menu, select.menuBtn').animate({color: '#272823'}, 500, 'linear');
+ else
+ $('#spacePanel, .menu, select.menuBtn').animate({color: 'white'}, 500, 'linear');
+ }, Space.FTB_SPEED / 2);
+
+ Space.createAsteroid();
+ },
+
+ drawStars: function(duration) {
+ var starsContainer = $('
').attr('id', 'starsContainer').appendTo('body');
+ Space.stars = $('
').css('bottom', '0px').attr('id', 'stars').appendTo(starsContainer);
+ var s1 = $('
').css({
+ width: Space.STAR_WIDTH + 'px',
+ height: Space.STAR_HEIGHT + 'px'
+ });
+ var s2 = s1.clone();
+ Space.stars.append(s1).append(s2);
+ Space.drawStarAsync(s1, s2, 0);
+ Space.stars.data('speed', Space.STAR_SPEED);
+ Space.startAnimation(Space.stars);
+
+ Space.starsBack = $('
').css('bottom', '0px').attr('id', 'starsBack').appendTo(starsContainer);
+ s1 = $('
').css({
+ width: Space.STAR_WIDTH + 'px',
+ height: Space.STAR_HEIGHT + 'px'
+ });
+ s2 = s1.clone();
+ Space.starsBack.append(s1).append(s2);
+ Space.drawStarAsync(s1, s2, 0);
+ Space.starsBack.data('speed', Space.STAR_SPEED * 2);
+ Space.startAnimation(Space.starsBack);
+ },
+
+ startAnimation: function(el) {
+ el.animate({bottom: '-3000px'}, el.data('speed'), 'linear', function() {
+ $(this).css('bottom', '0px');
+ Space.startAnimation($(this));
+ });
+ },
+
+ drawStarAsync: function(el, el2, num) {
+ var top = Math.floor(Math.random() * Space.STAR_HEIGHT) + 'px';
+ var left = Math.floor(Math.random() * Space.STAR_WIDTH) + 'px';
+ $('
').text('.').addClass('star').css({
+ top: top,
+ left: left
+ }).appendTo(el);
+ $('
').text('.').addClass('star').css({
+ top: top,
+ left: left
+ }).appendTo(el2);
+ if(num < Space.NUM_STARS) {
+ Engine.setTimeout(function() { Space.drawStarAsync(el, el2, num + 1); }, 100);
+ }
+ },
+
+ crash: function() {
+ if(Space.done) return;
+ Engine.keyLock = true;
+ Space.done = true;
+ clearInterval(Space._timer);
+ clearInterval(Space._shipTimer);
+ clearTimeout(Space._panelTimeout);
+ var body_color;
+ if (Engine.isLightsOff())
+ body_color = '#272823';
+ else
+ body_color = '#FFFFFF';
+ // Craaaaash!
+ $('body').removeClass('noMask').stop().animate({
+ backgroundColor: body_color
+ }, {
+ duration: 300,
+ progress: function() {
+ var cur = $('body').css('background-color');
+ var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
+ cur.substring(3, cur.length - 1) + ', 1) 100%)';
+ $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
+ },
+ complete: function() {
+ Space.stars.remove();
+ Space.starsBack.remove();
+ Space.stars = Space.starsBack = null;
+ $('#starsContainer').remove();
+ $('body').attr('style', '');
+ $('#notifyGradient').attr('style', '');
+ $('#spacePanel').attr('style', '');
+ }
+ });
+ $('.menu, select.menuBtn').animate({color: '#666'}, 300, 'linear');
+ $('#outerSlider').animate({top: '0px'}, 300, 'linear');
+ Engine.activeModule = Ship;
+ Ship.onArrival();
+ Button.cooldown($('#liftoffButton'));
+ Engine.event('progress', 'crash');
+ },
+
+ endGame: function() {
+ if(Space.done) return;
+ Engine.event('progress', 'win');
+ Space.done = true;
+ clearInterval(Space._timer);
+ clearInterval(Space._shipTimer);
+ clearTimeout(Engine._saveTimer);
+ clearTimeout(Outside._popTimeout);
+ clearTimeout(Engine._incomeTimeout);
+ clearTimeout(Events._eventTimeout);
+ clearTimeout(Room._fireTimer);
+ clearTimeout(Room._tempTimer);
+ for(var k in Room.Craftables) {
+ Room.Craftables[k].button = null;
+ }
+ for(var k in Room.TradeGoods) {
+ Room.TradeGoods[k].button = null;
+ }
+ delete Outside._popTimeout;
+
+ $('#hullRemaining', Space.panel).animate({opacity: 0}, 500, 'linear');
+ Space.ship.animate({
+ top: '350px',
+ left: '240px'
+ }, 3000, 'linear', function() {
+ Engine.setTimeout(function() {
+ Space.ship.animate({
+ top: '-100px'
+ }, 200, 'linear', function() {
+ // Restart everything! Play FOREVER!
+ $('#outerSlider').css({'left': '0px', 'top': '0px'});
+ $('#locationSlider, #worldPanel, #spacePanel, #notifications').remove();
+ $('#header').empty();
+ Engine.setTimeout(function() {
+ $('body').stop();
+ var container_color;
+ if (Engine.isLightsOff())
+ container_color = '#EEE';
+ else
+ container_color = '#000';
+ $('#starsContainer').animate({
+ opacity: 0,
+ 'background-color': container_color
+ }, {
+ duration: 2000,
+ progress: function() {
+ var cur = $('body').css('background-color');
+ var s = 'linear-gradient(rgba' + cur.substring(3, cur.length - 1) + ', 0) 0%, rgba' +
+ cur.substring(3, cur.length - 1) + ', 1) 100%)';
+ $('#notifyGradient').attr('style', 'background-color:'+cur+';background:-webkit-' + s + ';background:' + s);
+ },
+ complete: function() {
+ Engine.GAME_OVER = true;
+ Score.save();
+ Prestige.save();
+
+ $('
')
+ .addClass('centerCont')
+ .appendTo('body');
+ $('')
+ .addClass('endGame')
+ .text(_('score for this game: {0}', Score.calculateScore()))
+ .appendTo('.centerCont')
+ .animate({opacity:1},1500);
+ $('
')
+ .appendTo('.centerCont');
+ $('')
+ .addClass('endGame')
+ .text(_('total score: {0}', Prestige.get().score))
+ .appendTo('.centerCont')
+ .animate({opacity:1},1500);
+ $('
')
+ .appendTo('.centerCont');
+ $('
')
+ .appendTo('.centerCont');
+ $('#starsContainer').remove();
+ $('#content, #notifications').remove();
+ $('')
+ .addClass('endGame endGameRestart')
+ .text(_('restart.'))
+ .click(Engine.confirmDelete)
+ .appendTo('.centerCont')
+ .animate({opacity:1},1500);
+ Engine.options = {};
+ Engine.deleteSave(true);
+ }
+ });
+ }, 2000);
+ });
+ }, 2000);
+ });
+ },
+
+ keyDown: function(event) {
+ switch(event.which) {
+ case 38: // Up
+ case 87:
+ Space.up = true;
+ Engine.log('up on');
+ break;
+ case 40: // Down
+ case 83:
+ Space.down = true;
+ Engine.log('down on');
+ break;
+ case 37: // Left
+ case 65:
+ Space.left = true;
+ Engine.log('left on');
+ break;
+ case 39: // Right
+ case 68:
+ Space.right = true;
+ Engine.log('right on');
+ break;
+ }
+ },
+
+ keyUp: function(event) {
+ switch(event.which) {
+ case 38: // Up
+ case 87:
+ Space.up = false;
+ Engine.log('up off');
+ break;
+ case 40: // Down
+ case 83:
+ Space.down = false;
+ Engine.log('down off');
+ break;
+ case 37: // Left
+ case 65:
+ Space.left = false;
+ Engine.log('left off');
+ break;
+ case 39: // Right
+ case 68:
+ Space.right = false;
+ Engine.log('right off');
+ break;
+ }
+ },
+
+ handleStateUpdates: function(e){
+
+ }
+};
diff --git a/script/world.js b/script/world.js
index b785d2b..df4377a 100644
--- a/script/world.js
+++ b/script/world.js
@@ -1,949 +1,949 @@
-var World = {
-
- RADIUS: 30,
- VILLAGE_POS: [30, 30],
- TILE: {
- VILLAGE: 'A',
- IRON_MINE: 'I',
- COAL_MINE: 'C',
- SULPHUR_MINE: 'S',
- FOREST: ';',
- FIELD: ',',
- BARRENS: '.',
- ROAD: '#',
- HOUSE: 'H',
- CAVE: 'V',
- TOWN: 'O',
- CITY: 'Y',
- OUTPOST: 'P',
- SHIP: 'W',
- BOREHOLE: 'B',
- BATTLEFIELD: 'F',
- SWAMP: 'M',
- CACHE: 'U'
- },
- TILE_PROBS: {},
- LANDMARKS: {},
- STICKINESS: 0.5, // 0 <= x <= 1
- LIGHT_RADIUS: 2,
- BASE_WATER: 10,
- MOVES_PER_FOOD: 2,
- MOVES_PER_WATER: 1,
- DEATH_COOLDOWN: 120,
- FIGHT_CHANCE: 0.20,
- BASE_HEALTH: 10,
- BASE_HIT_CHANCE: 0.8,
- MEAT_HEAL: 8,
- MEDS_HEAL: 20,
- FIGHT_DELAY: 3, // At least three moves between fights
- NORTH: [ 0, -1],
- SOUTH: [ 0, 1],
- WEST: [-1, 0],
- EAST: [ 1, 0],
-
- Weapons: {
- 'fists': {
- verb: _('punch'),
- type: 'unarmed',
- damage: 1,
- cooldown: 2
- },
- 'bone spear': {
- verb: _('stab'),
- type: 'melee',
- damage: 2,
- cooldown: 2
- },
- 'iron sword': {
- verb: _('swing'),
- type: 'melee',
- damage: 4,
- cooldown: 2
- },
- 'steel sword': {
- verb: _('slash'),
- type: 'melee',
- damage: 6,
- cooldown: 2
- },
- 'bayonet': {
- verb: _('thrust'),
- type: 'melee',
- damage: 8,
- cooldown: 2
- },
- 'rifle': {
- verb: _('shoot'),
- type: 'ranged',
- damage: 5,
- cooldown: 1,
- cost: { 'bullets': 1 }
- },
- 'laser rifle': {
- verb: _('blast'),
- type: 'ranged',
- damage: 8,
- cooldown: 1,
- cost: { 'energy cell': 1 }
- },
- 'grenade': {
- verb: _('lob'),
- type: 'ranged',
- damage: 15,
- cooldown: 5,
- cost: { 'grenade': 1 }
- },
- 'bolas': {
- verb: _('tangle'),
- type: 'ranged',
- damage: 'stun',
- cooldown: 15,
- cost: { 'bolas': 1 }
- }
- },
-
- name: 'World',
- options: {}, // Nothing for now
- init: function(options) {
- this.options = $.extend(
- this.options,
- options
- );
-
- // Setup probabilities. Sum must equal 1.
- World.TILE_PROBS[World.TILE.FOREST] = 0.15;
- World.TILE_PROBS[World.TILE.FIELD] = 0.35;
- World.TILE_PROBS[World.TILE.BARRENS] = 0.5;
-
- // Setpiece definitions
- World.LANDMARKS[World.TILE.OUTPOST] = { num: 0, minRadius: 0, maxRadius: 0, scene: 'outpost', label: _('An Outpost') };
- World.LANDMARKS[World.TILE.IRON_MINE] = { num: 1, minRadius: 5, maxRadius: 5, scene: 'ironmine', label: _('Iron Mine') };
- World.LANDMARKS[World.TILE.COAL_MINE] = { num: 1, minRadius: 10, maxRadius: 10, scene: 'coalmine', label: _('Coal Mine') };
- World.LANDMARKS[World.TILE.SULPHUR_MINE] = { num: 1, minRadius: 20, maxRadius: 20, scene: 'sulphurmine', label: _('Sulphur Mine') };
- World.LANDMARKS[World.TILE.HOUSE] = { num: 10, minRadius: 0, maxRadius: World.RADIUS * 1.5, scene: 'house', label: _('An Old House') };
- World.LANDMARKS[World.TILE.CAVE] = { num: 5, minRadius: 3, maxRadius: 10, scene: 'cave', label: _('A Damp Cave') };
- World.LANDMARKS[World.TILE.TOWN] = { num: 10, minRadius: 10, maxRadius: 20, scene: 'town', label: _('An Abandoned Town') };
- World.LANDMARKS[World.TILE.CITY] = { num: 20, minRadius: 20, maxRadius: World.RADIUS * 1.5, scene: 'city', label: _('A Ruined City') };
- World.LANDMARKS[World.TILE.SHIP] = { num: 1, minRadius: 28, maxRadius: 28, scene: 'ship', label: _('A Crashed Starship')};
- World.LANDMARKS[World.TILE.BOREHOLE] = { num: 10, minRadius: 15, maxRadius: World.RADIUS * 1.5, scene: 'borehole', label: _('A Borehole')};
- 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')};
-
- // Only add the cache if there is prestige data
- if($SM.get('previous.stores')) {
- World.LANDMARKS[World.TILE.CACHE] = { num: 1, minRadius: 10, maxRadius: World.RADIUS * 1.5, scene: 'cache', label: _('A Destroyed Village')};
- }
-
- 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
- this.panel = $('').attr('id', "worldPanel").addClass('location').appendTo('#outerSlider');
-
- // Create the shrink wrapper
- var outer = $('
').attr('id', 'worldOuter').appendTo(this.panel);
-
- // Create the bag panel
- $('
').attr('id', 'bagspace-world').append($('
')).appendTo(outer);
- $('
').attr('id', 'backpackTitle').appendTo(outer);
- $('
').attr('id', 'backpackSpace').appendTo(outer);
- $('
').attr('id', 'healthCounter').appendTo(outer);
-
- Engine.updateOuterSlider();
-
- //subscribe to stateUpdates
- $.Dispatch('stateUpdate').subscribe(World.handleStateUpdates);
- },
-
- clearDungeon: function() {
- Engine.event('progress', 'dungeon cleared');
- World.state.map[World.curPos[0]][World.curPos[1]] = World.TILE.OUTPOST;
- World.drawRoad();
- },
-
- drawRoad: function() {
- var findClosestRoad = function(startPos) {
- // We'll search in a spiral to find the closest road tile
- // We spiral out along manhattan distance contour
- // lines to ensure we draw the shortest road possible.
- // No attempt is made to reduce the search space for
- // tiles outside the map.
- var searchX, searchY, dtmp,
- x = 0,
- y = 0,
- dx = 1,
- dy = -1;
- for (var i = 0; i < Math.pow(World.getDistance(startPos, World.VILLAGE_POS) + 2, 2); i++) {
- searchX = startPos[0] + x;
- searchY = startPos[1] + y;
- if (0 < searchX && searchX < World.RADIUS * 2 && 0 < searchY && searchY < World.RADIUS * 2) {
- // check for road
- var tile = World.state.map[searchX][searchY];
- if (
- tile === World.TILE.ROAD ||
- (tile === World.TILE.OUTPOST && !(x === 0 && y === 0)) || // outposts are connected to roads
- tile === World.TILE.VILLAGE // all roads lead home
- ) {
- return [searchX, searchY];
- }
- }
- if (x === 0 || y === 0) {
- // Turn the corner
- dtmp = dx;
- dx = -dy;
- dy = dtmp;
- }
- if (x === 0 && y <= 0) {
- x++;
- } else {
- x += dx;
- y += dy;
- }
- }
- return World.VILLAGE_POS;
- };
- var closestRoad = findClosestRoad(World.curPos);
- var xDist = World.curPos[0] - closestRoad[0];
- var yDist = World.curPos[1] - closestRoad[1];
- var xDir = Math.abs(xDist)/xDist;
- var yDir = Math.abs(yDist)/yDist;
- var xIntersect, yIntersect;
- if(Math.abs(xDist) > Math.abs(yDist)) {
- xIntersect = closestRoad[0];
- yIntersect = closestRoad[1] + yDist;
- } else {
- xIntersect = closestRoad[0] + xDist;
- yIntersect = closestRoad[1];
- }
-
- for(var x = 0; x < Math.abs(xDist); x++) {
- if(World.isTerrain(World.state.map[closestRoad[0] + (xDir*x)][yIntersect])) {
- World.state.map[closestRoad[0] + (xDir*x)][yIntersect] = World.TILE.ROAD;
- }
- }
- for(var y = 0; y < Math.abs(yDist); y++) {
- if(World.isTerrain(World.state.map[xIntersect][closestRoad[1] + (yDir*y)])) {
- World.state.map[xIntersect][closestRoad[1] + (yDir*y)] = World.TILE.ROAD;
- }
- }
- World.drawMap();
- },
-
- updateSupplies: function() {
- var supplies = $('div#bagspace-world > div');
-
- if(!Path.outfit) {
- Path.outfit = {};
- }
-
- // Add water
- var water = $('div#supply_water');
- if(World.water > 0 && water.length === 0) {
- water = World.createItemDiv('water', World.water);
- water.prependTo(supplies);
- } else if(World.water > 0) {
- $('div#supply_water', supplies).text(_('water:{0}' , World.water));
- } else {
- water.remove();
- }
-
- var total = 0;
- for(var k in Path.outfit) {
- var item = $('div#supply_' + k.replace(' ', '-'), supplies);
- var num = Path.outfit[k];
- total += num * Path.getWeight(k);
- if(num > 0 && item.length === 0) {
- item = World.createItemDiv(k, num);
- if(k == 'cured meat' && World.water > 0) {
- item.insertAfter(water);
- } else if(k == 'cured meat') {
- item.prependTo(supplies);
- } else {
- item.appendTo(supplies);
- }
- } else if(num > 0) {
- $('div#' + item.attr('id'), supplies).text(_(k) + ':' + num);
- } else {
- item.remove();
- }
- }
-
- // Update label
- var t = _('pockets');
- if($SM.get('stores.rucksack', true) > 0) {
- t = _('rucksack');
- }
- $('#backpackTitle').text(t);
-
- // Update bagspace
- $('#backpackSpace').text(_('free {0}/{1}', Math.floor(Path.getCapacity() - total) , Path.getCapacity()));
- },
-
- setWater: function(w) {
- World.water = w;
- if(World.water > World.getMaxWater()) {
- World.water = World.getMaxWater();
- }
- World.updateSupplies();
- },
-
- setHp: function(hp) {
- if(typeof hp == 'number' && !isNaN(hp)) {
- World.health = hp;
- if(World.health > World.getMaxHealth()) {
- World.health = World.getMaxHealth();
- }
- $('#healthCounter').text(_('hp: {0}/{1}', World.health , World.getMaxHealth()));
- }
- },
-
- createItemDiv: function(name, num) {
- var div = $('
').attr('id', 'supply_' + name.replace(' ', '-'))
- .addClass('supplyItem')
- .text(_('{0}:{1}',_(name), num));
-
- return div;
- },
-
- moveNorth: function() {
- Engine.log('North');
- if(World.curPos[1] > 0) World.move(World.NORTH);
- },
-
- moveSouth: function() {
- Engine.log('South');
- if(World.curPos[1] < World.RADIUS * 2) World.move(World.SOUTH);
- },
-
- moveWest: function() {
- Engine.log('West');
- if(World.curPos[0] > 0) World.move(World.WEST);
- },
-
- moveEast: function() {
- Engine.log('East');
- if(World.curPos[0] < World.RADIUS * 2) World.move(World.EAST);
- },
-
- move: function(direction) {
- var oldTile = World.state.map[World.curPos[0]][World.curPos[1]];
- World.curPos[0] += direction[0];
- World.curPos[1] += direction[1];
- World.narrateMove(oldTile, World.state.map[World.curPos[0]][World.curPos[1]]);
- World.lightMap(World.curPos[0], World.curPos[1], World.state.mask);
- World.drawMap();
- World.doSpace();
- if(World.checkDanger()) {
- if(World.danger) {
- Notifications.notify(World, _('dangerous to be this far from the village without proper protection'));
- } else {
- Notifications.notify(World, _('safer here'));
- }
- }
- },
-
- keyDown: function(event) {
- switch(event.which) {
- case 38: // Up
- case 87:
- World.moveNorth();
- break;
- case 40: // Down
- case 83:
- World.moveSouth();
- break;
- case 37: // Left
- case 65:
- World.moveWest();
- break;
- case 39: // Right
- case 68:
- World.moveEast();
- break;
- default:
- break;
- }
- },
-
- swipeLeft: function(e) {
- World.moveWest();
- },
-
- swipeRight: function(e) {
- World.moveEast();
- },
-
- swipeUp: function(e) {
- World.moveNorth();
- },
-
- swipeDown: function(e) {
- World.moveSouth();
- },
-
- click: function(event) {
- var map = $('#map'),
- // measure clicks relative to the centre of the current location
- centreX = map.offset().left + map.width() * World.curPos[0] / (World.RADIUS * 2),
- centreY = map.offset().top + map.height() * World.curPos[1] / (World.RADIUS * 2),
- clickX = event.pageX - centreX,
- clickY = event.pageY - centreY;
- if (clickX > clickY && clickX < -clickY) {
- World.moveNorth();
- }
- if (clickX < clickY && clickX > -clickY) {
- World.moveSouth();
- }
- if (clickX < clickY && clickX < -clickY) {
- World.moveWest();
- }
- if (clickX > clickY && clickX > -clickY) {
- World.moveEast();
- }
- },
-
- checkDanger: function() {
- World.danger = typeof World.danger == 'undefined' ? false: World.danger;
- if(!World.danger) {
- if($SM.get('stores["i armour"]', true) === 0 && World.getDistance() >= 8) {
- World.danger = true;
- return true;
- }
- if($SM.get('stores["s armour"]', true) === 0 && World.getDistance() >= 18) {
- World.danger = true;
- return true;
- }
- } else {
- if(World.getDistance() < 8) {
- World.danger = false;
- return true;
- }
- if(World.getDistance < 18 && $SM.get('stores["i armour"]', true) > 0) {
- World.danger = false;
- return true;
- }
- }
- return false;
- },
-
- useSupplies: function() {
- World.foodMove++;
- World.waterMove++;
- // Food
- var movesPerFood = World.MOVES_PER_FOOD;
- movesPerFood *= $SM.hasPerk('slow metabolism') ? 2 : 1;
- if(World.foodMove >= movesPerFood) {
- World.foodMove = 0;
- var num = Path.outfit['cured meat'];
- num--;
- if(num === 0) {
- Notifications.notify(World, _('the meat has run out'));
- } else if(num < 0) {
- // Starvation! Hooray!
- num = 0;
- if(!World.starvation) {
- Notifications.notify(World, _('starvation sets in'));
- World.starvation = true;
- } else {
- $SM.set('character.starved', $SM.get('character.starved', true));
- $SM.add('character.starved', 1);
- if($SM.get('character.starved') >= 10 && !$SM.hasPerk('slow metabolism')) {
- $SM.addPerk('slow metabolism');
- }
- World.die();
- return false;
- }
- } else {
- World.starvation = false;
- World.setHp(World.health + World.meatHeal());
- }
- Path.outfit['cured meat'] = num;
- }
- // Water
- var movesPerWater = World.MOVES_PER_WATER;
- movesPerWater *= $SM.hasPerk('desert rat') ? 2 : 1;
- if(World.waterMove >= movesPerWater) {
- World.waterMove = 0;
- var water = World.water;
- water--;
- if(water === 0) {
- Notifications.notify(World, _('there is no more water'));
- } else if(water < 0) {
- water = 0;
- if(!World.thirst) {
- Notifications.notify(World, _('the thirst becomes unbearable'));
- World.thirst = true;
- } else {
- $SM.set('character.dehydrated', $SM.get('character.dehydrated', true));
- $SM.add('character.dehydrated', 1);
- if($SM.get('character.dehydrated') >= 10 && !$SM.hasPerk('desert rat')) {
- $SM.addPerk('desert rat');
- }
- World.die();
- return false;
- }
- } else {
- World.thirst = false;
- }
- World.setWater(water);
- World.updateSupplies();
- }
- return true;
- },
-
- meatHeal: function() {
- return World.MEAT_HEAL * ($SM.hasPerk('gastronome') ? 2 : 1);
- },
-
- medsHeal: function() {
- return World.MEDS_HEAL;
- },
-
- checkFight: function() {
- World.fightMove = typeof World.fightMove == 'number' ? World.fightMove : 0;
- World.fightMove++;
- if(World.fightMove > World.FIGHT_DELAY) {
- var chance = World.FIGHT_CHANCE;
- chance *= $SM.hasPerk('stealthy') ? 0.5 : 1;
- if(Math.random() < chance) {
- World.fightMove = 0;
- Events.triggerFight();
- }
- }
- },
-
- doSpace: function() {
- var curTile = World.state.map[World.curPos[0]][World.curPos[1]];
-
- if(curTile == World.TILE.VILLAGE) {
- World.goHome();
- } else if(typeof World.LANDMARKS[curTile] != 'undefined') {
- if(curTile != World.TILE.OUTPOST || !World.outpostUsed()) {
- Events.startEvent(Events.Setpieces[World.LANDMARKS[curTile].scene]);
- }
- } else {
- if(World.useSupplies()) {
- World.checkFight();
- }
- }
- },
-
- getDistance: function(from, to) {
- from = from || World.curPos;
- to = to || World.VILLAGE_POS;
- return Math.abs(from[0] - to[0]) + Math.abs(from[1] - to[1]);
- },
-
- getTerrain: function() {
- return World.state.map[World.curPos[0]][World.curPos[1]];
- },
-
- narrateMove: function(oldTile, newTile) {
- var msg = null;
- switch(oldTile) {
- case World.TILE.FOREST:
- switch(newTile) {
- case World.TILE.FIELD:
- msg = _("the trees yield to dry grass. the yellowed brush rustles in the wind.");
- break;
- case World.TILE.BARRENS:
- msg = _("the trees are gone. parched earth and blowing dust are poor replacements.");
- break;
- }
- break;
- case World.TILE.FIELD:
- switch(newTile) {
- case World.TILE.FOREST:
- msg = _("trees loom on the horizon. grasses gradually yield to a forest floor of dry branches and fallen leaves.");
- break;
- case World.TILE.BARRENS:
- msg = _("the grasses thin. soon, only dust remains.");
- break;
- }
- break;
- case World.TILE.BARRENS:
- switch(newTile) {
- case World.TILE.FIELD:
- msg = _("the barrens break at a sea of dying grass, swaying in the arid breeze.");
- break;
- case World.TILE.FOREST:
- msg = _("a wall of gnarled trees rises from the dust. their branches twist into a skeletal canopy overhead.");
- break;
- }
- break;
- }
- if(msg != null) {
- Notifications.notify(World, msg);
- }
- },
-
- newMask: function() {
- var mask = new Array(World.RADIUS * 2 + 1);
- for(var i = 0; i <= World.RADIUS * 2; i++) {
- mask[i] = new Array(World.RADIUS * 2 + 1);
- }
- World.lightMap(World.RADIUS, World.RADIUS, mask);
- return mask;
- },
-
- lightMap: function(x, y, mask) {
- var r = World.LIGHT_RADIUS;
- r *= $SM.hasPerk('scout') ? 2 : 1;
- World.uncoverMap(x, y, r, mask);
- return mask;
- },
-
- uncoverMap: function(x, y, r, mask) {
- mask[x][y] = true;
- for(var i = -r; i <= r; i++) {
- for(var j = -r + Math.abs(i); j <= r - Math.abs(i); j++) {
- if(y + j >= 0 && y + j <= World.RADIUS * 2 &&
- x + i <= World.RADIUS * 2 &&
- x + i >= 0) {
- mask[x+i][y+j] = true;
- }
- }
- }
- },
-
- 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, $SM.get('game.world.mask'));
- },
-
- generateMap: function() {
- var map = new Array(World.RADIUS * 2 + 1);
- for(var i = 0; i <= World.RADIUS * 2; i++) {
- map[i] = new Array(World.RADIUS * 2 + 1);
- }
- // The Village is always at the exact center
- // Spiral out from there
- map[World.RADIUS][World.RADIUS] = World.TILE.VILLAGE;
- for(var r = 1; r <= World.RADIUS; r++) {
- for(var t = 0; t < r * 8; t++) {
- var x, y;
- if(t < 2 * r) {
- x = World.RADIUS - r + t;
- y = World.RADIUS - r;
- } else if(t < 4 * r) {
- x = World.RADIUS + r;
- y = World.RADIUS - (3 * r) + t;
- } else if(t < 6 * r) {
- x = World.RADIUS + (5 * r) - t;
- y = World.RADIUS + r;
- } else {
- x = World.RADIUS - r;
- y = World.RADIUS + (7 * r) - t;
- }
-
- map[x][y] = World.chooseTile(x, y, map);
- }
- }
-
- // Place landmarks
- for(var k in World.LANDMARKS) {
- var landmark = World.LANDMARKS[k];
- for(var i = 0; i < landmark.num; i++) {
- var pos = World.placeLandmark(landmark.minRadius, landmark.maxRadius, k, map);
- if(k == World.TILE.SHIP) {
- var dx = pos[0] - World.RADIUS, dy = pos[1] - World.RADIUS;
- var horz = dx < 0 ? 'west' : 'east';
- var vert = dy < 0 ? 'north' : 'south';
- if(Math.abs(dx) / 2 > Math.abs(dy)) {
- World.dir = horz;
- } else if(Math.abs(dy) / 2 > Math.abs(dx)){
- World.dir = vert;
- } else {
- World.dir = vert + horz;
- }
- }
- }
- }
-
- return map;
- },
-
- placeLandmark: function(minRadius, maxRadius, landmark, map) {
-
- var x = World.RADIUS, y = World.RADIUS;
- while(!World.isTerrain(map[x][y])) {
- var r = Math.floor(Math.random() * (maxRadius - minRadius)) + minRadius;
- var xDist = Math.floor(Math.random() * r);
- var yDist = r - xDist;
- if(Math.random() < 0.5) xDist = -xDist;
- if(Math.random() < 0.5) yDist = -yDist;
- x = World.RADIUS + xDist;
- if(x < 0) x = 0;
- if(x > World.RADIUS * 2) x = World.RADIUS * 2;
- y = World.RADIUS + yDist;
- if(y < 0) y = 0;
- if(y > World.RADIUS * 2) y = World.RADIUS * 2;
- }
- map[x][y] = landmark;
- return [x, y];
- },
-
- isTerrain: function(tile) {
- return tile == World.TILE.FOREST || tile == World.TILE.FIELD || tile == World.TILE.BARRENS;
- },
-
- chooseTile: function(x, y, map) {
-
- var adjacent = [
- y > 0 ? map[x][y-1] : null,
- y < World.RADIUS * 2 ? map[x][y+1] : null,
- x < World.RADIUS * 2 ? map[x+1][y] : null,
- x > 0 ? map[x-1][y] : null
- ];
-
- var chances = {};
- var nonSticky = 1;
- for(var i in adjacent) {
- if(adjacent[i] == World.TILE.VILLAGE) {
- // Village must be in a forest to maintain thematic consistency, yo.
- return World.TILE.FOREST;
- } else if(typeof adjacent[i] == 'string') {
- var cur = chances[adjacent[i]];
- cur = typeof cur == 'number' ? cur : 0;
- chances[adjacent[i]] = cur + World.STICKINESS;
- nonSticky -= World.STICKINESS;
- }
- }
- for(var t in World.TILE) {
- var tile = World.TILE[t];
- if(World.isTerrain(tile)) {
- var cur = chances[tile];
- cur = typeof cur == 'number' ? cur : 0;
- cur += World.TILE_PROBS[tile] * nonSticky;
- chances[tile] = cur;
- }
- }
-
- var list = [];
- for(var t in chances) {
- list.push(chances[t] + '' + t);
- }
- list.sort(function(a, b) {
- var n1 = parseFloat(a.substring(0, a.length - 1));
- var n2 = parseFloat(b.substring(0, b.length - 1));
- return n2 - n1;
- });
-
- var c = 0;
- var r = Math.random();
- for(var i in list) {
- var prob = list[i];
- c += parseFloat(prob.substring(0,prob.length - 1));
- if(r < c) {
- return prob.charAt(prob.length - 1);
- }
- }
-
- return World.TILE.BARRENS;
- },
-
- markVisited: function(x, y) {
- World.state.map[x][y] = World.state.map[x][y] + '!';
- },
-
- drawMap: function() {
- var map = $('#map');
- if(map.length === 0) {
- map = new $('
').attr('id', 'map').appendTo('#worldOuter');
- // register click handler
- map.click(World.click);
- }
- var mapString = "";
- for(var j = 0; j <= World.RADIUS * 2; j++) {
- for(var i = 0; i <= World.RADIUS * 2; i++) {
- var ttClass = "";
- if(i > World.RADIUS) {
- ttClass += " left";
- } else {
- ttClass += " right";
- }
- if(j > World.RADIUS) {
- ttClass += " top";
- } else {
- ttClass += " bottom";
- }
- if(World.curPos[0] == i && World.curPos[1] == j) {
- mapString += '
@'+_('Wanderer')+'
';
- } else if(World.state.mask[i][j]) {
- var c = World.state.map[i][j];
- switch(c) {
- case World.TILE.VILLAGE:
- mapString += '
' + c + ''+_('The Village')+'
';
- break;
- default:
- if(typeof World.LANDMARKS[c] != 'undefined' && (c != World.TILE.OUTPOST || !World.outpostUsed(i, j))) {
- mapString += '
' + c + '' + World.LANDMARKS[c].label + '
';
- } else {
- if(c.length > 1) {
- c = c[0];
- }
- mapString += c;
- }
- break;
- }
- } else {
- mapString += ' ';
- }
- }
- mapString += '
';
- }
- map.html(mapString);
- },
-
- die: function() {
- if(!World.dead) {
- World.dead = true;
- Engine.log('player death');
- Engine.event('game event', 'death');
- Engine.keyLock = true;
- // Dead! Discard any world changes and go home
- Notifications.notify(World, _('the world fades'));
- World.state = null;
- Path.outfit = {};
- $('#outerSlider').animate({opacity: '0'}, 600, 'linear', function() {
- $('#outerSlider').css('left', '0px');
- $('#locationSlider').css('left', '0px');
- $('#storesContainer').css({'top': '0px', 'right': '0px'});
- Engine.activeModule = Room;
- $('div.headerButton').removeClass('selected');
- Room.tab.addClass('selected');
- Engine.setTimeout(function(){
- Room.onArrival();
- $('#outerSlider').animate({opacity:'1'}, 600, 'linear');
- Button.cooldown($('#embarkButton'));
- Engine.keyLock = false;
- }, 2000, true);
- });
- }
- },
-
- goHome: function() {
- // Home safe! Commit the changes.
- $SM.setM('game.world', World.state);
- if(World.state.sulphurmine && $SM.get('game.buildings["sulphur mine"]', true) === 0) {
- $SM.add('game.buildings["sulphur mine"]', 1);
- Engine.event('progress', 'sulphur mine');
- }
- if(World.state.ironmine && $SM.get('game.buildings["iron mine"]', true) === 0) {
- $SM.add('game.buildings["iron mine"]', 1);
- Engine.event('progress', 'iron mine');
- }
- if(World.state.coalmine && $SM.get('game.buildings["coal mine"]', true) === 0) {
- $SM.add('game.buildings["coal mine"]', 1);
- Engine.event('progress', 'coal mine');
- }
- if(World.state.ship && !$SM.get('features.location.spaceShip')) {
- Ship.init();
- Engine.event('progress', 'ship');
- }
- World.state = null;
-
- // Clear the embark cooldown
- var btn = Button.clearCooldown($('#embarkButton'));
- if(Path.outfit['cured meat'] > 0) {
- Button.setDisabled(btn, false);
- }
-
- for(var k in Path.outfit) {
- $SM.add('stores["'+k+'"]', Path.outfit[k]);
- if(World.leaveItAtHome(k)) {
- Path.outfit[k] = 0;
- }
- }
-
- $('#outerSlider').animate({left: '0px'}, 300);
- Engine.activeModule = Path;
- Path.onArrival();
- },
-
- leaveItAtHome: function(thing) {
- return thing != 'cured meat' && thing != 'bullets' && thing != 'energy cell' && thing != 'charm' && thing != 'medicine' &&
- typeof World.Weapons[thing] == 'undefined' && typeof Room.Craftables[thing] == 'undefined';
- },
-
- getMaxHealth: function() {
- if($SM.get('stores["s armour"]', true) > 0) {
- return World.BASE_HEALTH + 35;
- } else if($SM.get('stores["i armour"]', true) > 0) {
- return World.BASE_HEALTH + 15;
- } else if($SM.get('stores["l armour"]', true) > 0) {
- return World.BASE_HEALTH + 5;
- }
- return World.BASE_HEALTH;
- },
-
- getHitChance: function() {
- if($SM.hasPerk('precise')) {
- return World.BASE_HIT_CHANCE + 0.1;
- }
- return World.BASE_HIT_CHANCE;
- },
-
- getMaxWater: function() {
- if($SM.get('stores["water tank"]', true) > 0) {
- return World.BASE_WATER + 50;
- } else if($SM.get('stores.cask', true) > 0) {
- return World.BASE_WATER + 20;
- } else if($SM.get('stores.waterskin', true) > 0) {
- return World.BASE_WATER + 10;
- }
- return World.BASE_WATER;
- },
-
- outpostUsed: function(x, y) {
- x = typeof x == 'number' ? x : World.curPos[0];
- y = typeof y == 'number' ? y : World.curPos[1];
- var used = World.usedOutposts[x + ',' + y];
- return typeof used != 'undefined' && used === true;
- },
-
- useOutpost: function() {
- Notifications.notify(null, _('water replenished'));
- World.setWater(World.getMaxWater());
- // Mark this outpost as used
- World.usedOutposts[World.curPos[0] + ',' + World.curPos[1]] = true;
- },
-
- 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, {}, $SM.get('game.world'));
- World.setWater(World.getMaxWater());
- World.setHp(World.getMaxHealth());
- World.foodMove = 0;
- World.waterMove = 0;
- World.starvation = false;
- World.thirst = false;
- World.usedOutposts = {};
- World.curPos = World.copyPos(World.VILLAGE_POS);
- World.drawMap();
- World.setTitle();
- World.dead = false;
- $('div#bagspace-world > div').empty();
- World.updateSupplies();
- $('#bagspace-world').width($('#map').width());
- },
-
- setTitle: function() {
- document.title = _('A Barren World');
- },
-
- copyPos: function(pos) {
- return [pos[0], pos[1]];
- },
-
- handleStateUpdates: function(e){
-
- }
-};
+var World = {
+
+ RADIUS: 30,
+ VILLAGE_POS: [30, 30],
+ TILE: {
+ VILLAGE: 'A',
+ IRON_MINE: 'I',
+ COAL_MINE: 'C',
+ SULPHUR_MINE: 'S',
+ FOREST: ';',
+ FIELD: ',',
+ BARRENS: '.',
+ ROAD: '#',
+ HOUSE: 'H',
+ CAVE: 'V',
+ TOWN: 'O',
+ CITY: 'Y',
+ OUTPOST: 'P',
+ SHIP: 'W',
+ BOREHOLE: 'B',
+ BATTLEFIELD: 'F',
+ SWAMP: 'M',
+ CACHE: 'U'
+ },
+ TILE_PROBS: {},
+ LANDMARKS: {},
+ STICKINESS: 0.5, // 0 <= x <= 1
+ LIGHT_RADIUS: 2,
+ BASE_WATER: 10,
+ MOVES_PER_FOOD: 2,
+ MOVES_PER_WATER: 1,
+ DEATH_COOLDOWN: 120,
+ FIGHT_CHANCE: 0.20,
+ BASE_HEALTH: 10,
+ BASE_HIT_CHANCE: 0.8,
+ MEAT_HEAL: 8,
+ MEDS_HEAL: 20,
+ FIGHT_DELAY: 3, // At least three moves between fights
+ NORTH: [ 0, -1],
+ SOUTH: [ 0, 1],
+ WEST: [-1, 0],
+ EAST: [ 1, 0],
+
+ Weapons: {
+ 'fists': {
+ verb: _('punch'),
+ type: 'unarmed',
+ damage: 1,
+ cooldown: 2
+ },
+ 'bone spear': {
+ verb: _('stab'),
+ type: 'melee',
+ damage: 2,
+ cooldown: 2
+ },
+ 'iron sword': {
+ verb: _('swing'),
+ type: 'melee',
+ damage: 4,
+ cooldown: 2
+ },
+ 'steel sword': {
+ verb: _('slash'),
+ type: 'melee',
+ damage: 6,
+ cooldown: 2
+ },
+ 'bayonet': {
+ verb: _('thrust'),
+ type: 'melee',
+ damage: 8,
+ cooldown: 2
+ },
+ 'rifle': {
+ verb: _('shoot'),
+ type: 'ranged',
+ damage: 5,
+ cooldown: 1,
+ cost: { 'bullets': 1 }
+ },
+ 'laser rifle': {
+ verb: _('blast'),
+ type: 'ranged',
+ damage: 8,
+ cooldown: 1,
+ cost: { 'energy cell': 1 }
+ },
+ 'grenade': {
+ verb: _('lob'),
+ type: 'ranged',
+ damage: 15,
+ cooldown: 5,
+ cost: { 'grenade': 1 }
+ },
+ 'bolas': {
+ verb: _('tangle'),
+ type: 'ranged',
+ damage: 'stun',
+ cooldown: 15,
+ cost: { 'bolas': 1 }
+ }
+ },
+
+ name: 'World',
+ options: {}, // Nothing for now
+ init: function(options) {
+ this.options = $.extend(
+ this.options,
+ options
+ );
+
+ // Setup probabilities. Sum must equal 1.
+ World.TILE_PROBS[World.TILE.FOREST] = 0.15;
+ World.TILE_PROBS[World.TILE.FIELD] = 0.35;
+ World.TILE_PROBS[World.TILE.BARRENS] = 0.5;
+
+ // Setpiece definitions
+ World.LANDMARKS[World.TILE.OUTPOST] = { num: 0, minRadius: 0, maxRadius: 0, scene: 'outpost', label: _('An Outpost') };
+ World.LANDMARKS[World.TILE.IRON_MINE] = { num: 1, minRadius: 5, maxRadius: 5, scene: 'ironmine', label: _('Iron Mine') };
+ World.LANDMARKS[World.TILE.COAL_MINE] = { num: 1, minRadius: 10, maxRadius: 10, scene: 'coalmine', label: _('Coal Mine') };
+ World.LANDMARKS[World.TILE.SULPHUR_MINE] = { num: 1, minRadius: 20, maxRadius: 20, scene: 'sulphurmine', label: _('Sulphur Mine') };
+ World.LANDMARKS[World.TILE.HOUSE] = { num: 10, minRadius: 0, maxRadius: World.RADIUS * 1.5, scene: 'house', label: _('An Old House') };
+ World.LANDMARKS[World.TILE.CAVE] = { num: 5, minRadius: 3, maxRadius: 10, scene: 'cave', label: _('A Damp Cave') };
+ World.LANDMARKS[World.TILE.TOWN] = { num: 10, minRadius: 10, maxRadius: 20, scene: 'town', label: _('An Abandoned Town') };
+ World.LANDMARKS[World.TILE.CITY] = { num: 20, minRadius: 20, maxRadius: World.RADIUS * 1.5, scene: 'city', label: _('A Ruined City') };
+ World.LANDMARKS[World.TILE.SHIP] = { num: 1, minRadius: 28, maxRadius: 28, scene: 'ship', label: _('A Crashed Starship')};
+ World.LANDMARKS[World.TILE.BOREHOLE] = { num: 10, minRadius: 15, maxRadius: World.RADIUS * 1.5, scene: 'borehole', label: _('A Borehole')};
+ 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')};
+
+ // Only add the cache if there is prestige data
+ if($SM.get('previous.stores')) {
+ World.LANDMARKS[World.TILE.CACHE] = { num: 1, minRadius: 10, maxRadius: World.RADIUS * 1.5, scene: 'cache', label: _('A Destroyed Village')};
+ }
+
+ 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
+ this.panel = $('
').attr('id', "worldPanel").addClass('location').appendTo('#outerSlider');
+
+ // Create the shrink wrapper
+ var outer = $('
').attr('id', 'worldOuter').appendTo(this.panel);
+
+ // Create the bag panel
+ $('
').attr('id', 'bagspace-world').append($('
')).appendTo(outer);
+ $('