').addClass('clear').appendTo(healBtns);
Events.setHeal(healBtns);
-
+
// Set up the enemy attack timer
Events._enemyAttackTimer = Engine.setInterval(Events.enemyAttack, scene.attackDelay * 1000);
},
@@ -340,10 +339,12 @@ var Events = {
eatMeat: function(btn) {
Events.doHeal('cured meat', World.meatHeal(), btn);
+ AudioEngine.playSound(AudioLibrary.EAT_MEAT);
},
useMeds: function(btn) {
Events.doHeal('medicine', World.medsHeal(), btn);
+ AudioEngine.playSound(AudioLibrary.USE_MEDS);
},
useWeapon: function(btn) {
@@ -416,8 +417,23 @@ var Events = {
}
}
}
-
+
var attackFn = weapon.type == 'ranged' ? Events.animateRanged : Events.animateMelee;
+
+ // play variation audio for weapon type
+ var r = Math.floor(Math.random() * 2) + 1;
+ switch (weapon.type) {
+ case 'unarmed':
+ AudioEngine.playSound(AudioLibrary['WEAPON_UNARMED_' + r]);
+ break;
+ case 'melee':
+ AudioEngine.playSound(AudioLibrary['WEAPON_MELEE_' + r]);
+ break;
+ case 'ranged':
+ AudioEngine.playSound(AudioLibrary['WEAPON_RANGED_' + r]);
+ break;
+ }
+
attackFn($('#wanderer'), dmg, function() {
if($('#enemy').data('hp') <= 0 && !Events.won) {
// Success!
@@ -427,7 +443,7 @@ var Events = {
}
},
- damage: function(fighter, enemy, dmg) {
+ damage: function(fighter, enemy, dmg, type) {
var enemyHp = enemy.data('hp');
var msg = "";
if(typeof dmg == 'number') {
@@ -443,6 +459,20 @@ var Events = {
Events.setHeal();
}
Events.updateFighterDiv(enemy);
+
+ // play variation audio for weapon type
+ var r = Math.floor(Math.random() * 2) + 1;
+ switch (type) {
+ case 'unarmed':
+ AudioEngine.playSound(AudioLibrary['WEAPON_UNARMED_' + r]);
+ break;
+ case 'melee':
+ AudioEngine.playSound(AudioLibrary['WEAPON_MELEE_' + r]);
+ break;
+ case 'ranged':
+ AudioEngine.playSound(AudioLibrary['WEAPON_RANGED_' + r]);
+ break;
+ }
}
} else {
if(dmg == 'stun') {
@@ -468,7 +498,7 @@ var Events = {
fighter.stop(true, true).animate(start, Events._FIGHT_SPEED, function() {
- Events.damage(fighter, enemy, dmg);
+ Events.damage(fighter, enemy, dmg, 'melee');
$(this).animate(end, Events._FIGHT_SPEED, callback);
});
@@ -489,7 +519,7 @@ var Events = {
$('
').css(start).addClass('bullet').text('o').appendTo('#description')
.animate(end, Events._FIGHT_SPEED * 2, 'linear', function() {
- Events.damage(fighter, enemy, dmg);
+ Events.damage(fighter, enemy, dmg, 'ranged');
$(this).remove();
if(typeof callback == 'function') {
@@ -519,6 +549,7 @@ var Events = {
clearTimeout(Events._enemyAttackTimer);
Events.endEvent();
World.die();
+ AudioEngine.playSound(AudioLibrary.LOSE_FIGHT);
}
});
}
@@ -536,6 +567,7 @@ var Events = {
return;
}
Events.endFight();
+ // AudioEngine.playSound(AudioLibrary.WIN_FIGHT);
$('#enemy').animate({opacity: 0}, 300, 'linear', function() {
Engine.setTimeout(function() {
var scene = Events.activeEvent().scenes[Events.activeScene];
@@ -1018,6 +1050,7 @@ var Events = {
} else {
var r = Math.floor(Math.random()*(possibleEvents.length));
Events.startEvent(possibleEvents[r]);
+ AudioEngine.playEventMusic(possibleEvents[r].audio);
}
}
@@ -1035,6 +1068,20 @@ var Events = {
var r = Math.floor(Math.random()*(possibleFights.length));
Events.startEvent(possibleFights[r]);
+
+ // play audio only when fight is possible
+ if (possibleFights.length > 0) {
+ if (World.getDistance() > 20) {
+ // Tier 3
+ AudioEngine.playEventMusic(AudioLibrary.ENCOUNTER_TIER_3);
+ } else if (World.getDistance() > 10) {
+ // Tier 2
+ AudioEngine.playEventMusic(AudioLibrary.ENCOUNTER_TIER_2);
+ } else {
+ // Tier 1
+ AudioEngine.playEventMusic(AudioLibrary.ENCOUNTER_TIER_1);
+ }
+ }
},
activeEvent: function() {
@@ -1080,6 +1127,7 @@ var Events = {
},
endEvent: function() {
+ AudioEngine.stopEventMusic();
Events.eventPanel().animate({opacity:0}, Events._PANEL_FADE, 'linear', function() {
Events.eventPanel().remove();
Events.activeEvent().eventPanel = null;
diff --git a/script/events/global.js b/script/events/global.js
index ff6e662..8cefbf8 100644
--- a/script/events/global.js
+++ b/script/events/global.js
@@ -61,6 +61,7 @@ Events.Global = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_THIEF
}
];
diff --git a/script/events/outside.js b/script/events/outside.js
index 1a6e763..b0b5b15 100644
--- a/script/events/outside.js
+++ b/script/events/outside.js
@@ -63,7 +63,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_RUINED_TRAP
},
{ /* Hut fire */
title: _('Fire'),
@@ -89,7 +90,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_HUT_FIRE
},
{ /* Sickness */
title: _('Sickness'),
@@ -146,7 +148,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_SICKNESS
},
{ /* Plague */
@@ -217,7 +220,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_PLAGUE
},
{ /* Beast attack */
@@ -251,7 +255,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_BEAST_ATTACK
},
{ /* Soldier attack */
@@ -285,7 +290,8 @@ Events.Outside = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_SOLDIER_ATTACK
}
];
diff --git a/script/events/room.js b/script/events/room.js
index 1e70a3e..6879458 100644
--- a/script/events/room.js
+++ b/script/events/room.js
@@ -47,7 +47,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_NOMAD
},
{ /* Noises Outside -- gain wood/fur */
title: _('Noises'),
@@ -98,7 +99,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_NOISES_OUTSIDE
},
{ /* Noises Inside -- trade wood for better good */
title: _('Noises'),
@@ -184,7 +186,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_NOISES_INSIDE
},
{ /* The Beggar -- trade fur for better good */
title: _('The Beggar'),
@@ -255,7 +258,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_BEGGAR
},
{/* The Shady Builder */
title: _('The Shady Builder'),
@@ -311,7 +315,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_SHADY_BUILDER
},
{ /* Mysterious Wanderer -- wood gambling */
@@ -390,7 +395,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_MYSTERIOUS_WANDERER
},
{ /* Mysterious Wanderer -- fur gambling */
@@ -469,7 +475,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_MYSTERIOUS_WANDERER
},
{ /* The Scout -- Map Merchant */
@@ -511,7 +518,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_SCOUT
},
{ /* The Wandering Master */
@@ -584,7 +592,8 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_WANDERING_MASTER
},
{ /* The Sick Man */
@@ -672,6 +681,7 @@ Events.Room = [
}
}
}
- }
+ },
+ audio: AudioLibrary.EVENT_SICK_MAN
}
];
diff --git a/script/events/setpieces.js b/script/events/setpieces.js
index 9f4012b..dadf91e 100644
--- a/script/events/setpieces.js
+++ b/script/events/setpieces.js
@@ -28,7 +28,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_FRIENDLY_OUTPOST
},
"swamp": { /* Swamp */
title: _('A Murky Swamp'),
@@ -85,7 +86,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_SWAMP
},
"cave": { /* Cave */
title: _('A Damp Cave'),
@@ -516,7 +518,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_CAVE
},
"town": { /* Town */
title: _('A Deserted Town'),
@@ -1233,7 +1236,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_TOWN
},
"city": { /* City */
title: _('A Ruined City'),
@@ -2928,7 +2932,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_CITY
},
"house": { /* Abandoned House */
title: _('An Old House'),
@@ -3045,7 +3050,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_HOUSE
},
"battlefield": { /* Discovering an old battlefield */
title: _('A Forgotten Battlefield'),
@@ -3098,7 +3104,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_BATTLEFIELD
},
"borehole": { /* Admiring a huge borehole */
title: _('A Huge Borehole'),
@@ -3127,7 +3134,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_BOREHOLE
},
"ship": { /* Finding a way off this rock */
title: _('A Crashed Ship'),
@@ -3150,7 +3158,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_CRASHED_SHIP
},
"sulphurmine": { /* Clearing the Sulphur Mine */
title: _('The Sulphur Mine'),
@@ -3299,7 +3308,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_SULPHUR_MINE
},
"coalmine": { /* Clearing the Coal Mine */
title: _('The Coal Mine'),
@@ -3441,7 +3451,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_COAL_MINE
},
"ironmine": { /* Clearing the Iron Mine */
title: _('The Iron Mine'),
@@ -3517,7 +3528,8 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_IRON_MINE
},
"cache": { /* Cache - contains some of supplies from previous game */
@@ -3569,6 +3581,7 @@ Events.Setpieces = {
}
}
}
- }
+ },
+ audio: AudioLibrary.LANDMARK_DESTROYED_VILLAGE
}
};
diff --git a/script/outside.js b/script/outside.js
index 881bc43..ef3f1a8 100644
--- a/script/outside.js
+++ b/script/outside.js
@@ -94,7 +94,6 @@ var Outside = {
}
}
},
-
TrapDrops: [
{
rollUnder: 0.5,
@@ -588,12 +587,29 @@ var Outside = {
Outside.updateVillage(true);
Engine.moveStoresView($('#village'), transition_diff);
+
+ // set music
+ var numberOfHuts = $SM.get('game.buildings["hut"]', true);
+ if(numberOfHuts === 0) {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_SILENT_FOREST);
+ } else if(numberOfHuts == 1) {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_LONELY_HUT);
+ } else if(numberOfHuts <= 4) {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_TINY_VILLAGE);
+ } else if(numberOfHuts <= 8) {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_MODEST_VILLAGE);
+ } else if(numberOfHuts <= 14) {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_LARGE_VILLAGE);
+ } else {
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_RAUCOUS_VILLAGE);
+ }
},
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);
+ AudioEngine.playSound(AudioLibrary.GATHER_WOOD);
},
checkTraps: function() {
@@ -634,6 +650,7 @@ var Outside = {
Notifications.notify(Outside, s);
$SM.addM('stores', drops);
+ AudioEngine.playSound(AudioLibrary.CHECK_TRAPS);
},
handleStateUpdates: function(e){
diff --git a/script/path.js b/script/path.js
index 250b9ea..8ee517d 100644
--- a/script/path.js
+++ b/script/path.js
@@ -1,5 +1,4 @@
var Path = {
-
DEFAULT_BAG_SPACE: 10,
_STORES_OFFSET: 0,
// Everything not in this list weighs 1
@@ -304,6 +303,8 @@ var Path = {
Path.setTitle();
Path.updateOutfitting();
Path.updatePerks(true);
+
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_DUSTY_PATH);
Engine.moveStoresView($('#perks'), transition_diff);
},
@@ -319,6 +320,7 @@ var Path = {
World.onArrival();
$('#outerSlider').animate({left: '-700px'}, 300);
Engine.activeModule = World;
+ AudioEngine.playSound(AudioLibrary.EMBARK);
},
handleStateUpdates: function(e){
diff --git a/script/room.js b/script/room.js
index 7705994..5567ce7 100644
--- a/script/room.js
+++ b/script/room.js
@@ -8,9 +8,7 @@ var Room = {
_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:{},
-
+ buttons: {},
Craftables: {
'trap': {
name: _('trap'),
@@ -20,12 +18,13 @@ var Room = {
buildMsg: _('more traps to catch more creatures'),
maxMsg: _("more traps won't help now"),
type: 'building',
- cost: function() {
+ cost: function () {
var n = $SM.get('game.buildings["trap"]', true);
return {
- 'wood': 10 + (n*10)
+ 'wood': 10 + (n * 10)
};
- }
+ },
+ audio: AudioLibrary.BUILD_TRAP
},
'cart': {
name: _('cart'),
@@ -34,11 +33,12 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 30
};
- }
+ },
+ audio: AudioLibrary.BUILD_CART
},
'hut': {
name: _('hut'),
@@ -48,12 +48,13 @@ var Room = {
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() {
+ cost: function () {
var n = $SM.get('game.buildings["hut"]', true);
return {
- 'wood': 100 + (n*50)
+ 'wood': 100 + (n * 50)
};
- }
+ },
+ audio: AudioLibrary.BUILD_HUT
},
'lodge': {
name: _('lodge'),
@@ -62,13 +63,14 @@ var Room = {
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() {
+ cost: function () {
return {
wood: 200,
fur: 10,
meat: 5
};
- }
+ },
+ audio: AudioLibrary.BUILD_LODGE
},
'trading post': {
name: _('trading post'),
@@ -77,12 +79,13 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 400,
'fur': 100
};
- }
+ },
+ audio: AudioLibrary.BUILD_TRADING_POST
},
'tannery': {
name: _('tannery'),
@@ -91,12 +94,13 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 500,
'fur': 50
};
- }
+ },
+ audio: AudioLibrary.BUILD_TANNERY
},
'smokehouse': {
name: _('smokehouse'),
@@ -105,12 +109,13 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 600,
'meat': 50
};
- }
+ },
+ audio: AudioLibrary.BUILD_SMOKEHOUSE
},
'workshop': {
name: _('workshop'),
@@ -119,13 +124,14 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 800,
'leather': 100,
'scales': 10
};
- }
+ },
+ audio: AudioLibrary.BUILD_WORKSHOP
},
'steelworks': {
name: _('steelworks'),
@@ -134,13 +140,14 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 1500,
'iron': 100,
'coal': 100
};
- }
+ },
+ audio: AudioLibrary.BUILD_STEELWORKS
},
'armoury': {
name: _('armoury'),
@@ -149,25 +156,27 @@ var Room = {
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() {
+ cost: function () {
return {
'wood': 3000,
'steel': 100,
'sulphur': 50
};
- }
+ },
+ audio: AudioLibrary.BUILD_ARMOURY
},
'torch': {
name: _('torch'),
button: null,
type: 'tool',
buildMsg: _('a torch to keep the dark away'),
- cost: function() {
+ cost: function () {
return {
'wood': 1,
'cloth': 1
};
- }
+ },
+ audio: AudioLibrary.CRAFT_TORCH
},
'waterskin': {
name: _('waterskin'),
@@ -175,11 +184,12 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('this waterskin\'ll hold a bit of water, at least'),
- cost: function() {
+ cost: function () {
return {
'leather': 50
};
- }
+ },
+ audio: AudioLibrary.CRAFT_WATERSKIN
},
'cask': {
name: _('cask'),
@@ -187,12 +197,13 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('the cask holds enough water for longer expeditions'),
- cost: function() {
+ cost: function () {
return {
'leather': 100,
'iron': 20
};
- }
+ },
+ audio: AudioLibrary.CRAFT_CASK
},
'water tank': {
name: _('water tank'),
@@ -200,24 +211,26 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('never go thirsty again'),
- cost: function() {
+ cost: function () {
return {
'iron': 100,
'steel': 50
};
- }
+ },
+ audio: AudioLibrary.CRAFT_WATER_TANK
},
'bone spear': {
name: _('bone spear'),
button: null,
type: 'weapon',
buildMsg: _("this spear's not elegant, but it's pretty good at stabbing"),
- cost: function() {
+ cost: function () {
return {
'wood': 100,
'teeth': 5
};
- }
+ },
+ audio: AudioLibrary.CRAFT_BONE_SPEAR
},
'rucksack': {
name: _('rucksack'),
@@ -225,11 +238,12 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('carrying more means longer expeditions to the wilds'),
- cost: function() {
+ cost: function () {
return {
'leather': 200
};
- }
+ },
+ audio: AudioLibrary.CRAFT_RUCKSACK
},
'wagon': {
name: _('wagon'),
@@ -237,12 +251,13 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('the wagon can carry a lot of supplies'),
- cost: function() {
+ cost: function () {
return {
'wood': 500,
'iron': 100
};
- }
+ },
+ audio: AudioLibrary.CRAFT_WAGON
},
'convoy': {
name: _('convoy'),
@@ -250,248 +265,268 @@ var Room = {
type: 'upgrade',
maximum: 1,
buildMsg: _('the convoy can haul mostly everything'),
- cost: function() {
+ cost: function () {
return {
'wood': 1000,
'iron': 200,
'steel': 100
};
- }
+ },
+ audio: AudioLibrary.CRAFT_CONVOY
},
'l armour': {
name: _('l armour'),
type: 'upgrade',
maximum: 1,
buildMsg: _("leather's not strong. better than rags, though."),
- cost: function() {
+ cost: function () {
return {
'leather': 200,
'scales': 20
};
- }
+ },
+ audio: AudioLibrary.CRAFT_LEATHER_ARMOUR
},
'i armour': {
name: _('i armour'),
type: 'upgrade',
maximum: 1,
buildMsg: _("iron's stronger than leather"),
- cost: function() {
+ cost: function () {
return {
'leather': 200,
'iron': 100
};
- }
+ },
+ audio: AudioLibrary.CRAFT_IRON_ARMOUR
},
's armour': {
name: _('s armour'),
type: 'upgrade',
maximum: 1,
buildMsg: _("steel's stronger than iron"),
- cost: function() {
+ cost: function () {
return {
'leather': 200,
'steel': 100
};
- }
+ },
+ audio: AudioLibrary.CRAFT_STEEL_ARMOUR
},
'iron sword': {
name: _('iron sword'),
button: null,
type: 'weapon',
buildMsg: _("sword is sharp. good protection out in the wilds."),
- cost: function() {
+ cost: function () {
return {
'wood': 200,
'leather': 50,
'iron': 20
};
- }
+ },
+ audio: AudioLibrary.CRAFT_IRON_SWORD
},
'steel sword': {
name: _('steel sword'),
button: null,
type: 'weapon',
buildMsg: _("the steel is strong, and the blade true."),
- cost: function() {
+ cost: function () {
return {
'wood': 500,
'leather': 100,
'steel': 20
};
- }
+ },
+ audio: AudioLibrary.CRAFT_STEEL_SWORD
},
'rifle': {
name: _('rifle'),
type: 'weapon',
buildMsg: _("black powder and bullets, like the old days."),
- cost: function() {
+ cost: function () {
return {
'wood': 200,
'steel': 50,
'sulphur': 50
};
- }
+ },
+ audio: AudioLibrary.CRAFT_RIFLE
}
},
-
+
TradeGoods: {
'scales': {
type: 'good',
- cost: function() {
+ cost: function () {
return { fur: 150 };
- }
+ },
+ audio: AudioLibrary.BUY_SCALES
},
'teeth': {
type: 'good',
- cost: function() {
+ cost: function () {
return { fur: 300 };
- }
+ },
+ audio: AudioLibrary.BUY_TEETH
},
'iron': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'fur': 150,
'scales': 50
};
- }
+ },
+ audio: AudioLibrary.BUY_IRON
},
'coal': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'fur': 200,
'teeth': 50
};
- }
+ },
+ audio: AudioLibrary.BUY_COAL
},
'steel': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'fur': 300,
'scales': 50,
'teeth': 50
};
- }
+ },
+ audio: AudioLibrary.BUY_STEEL
},
'medicine': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'scales': 50, 'teeth': 30
};
- }
+ },
+ audio: AudioLibrary.BUY_MEDICINE
},
'bullets': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'scales': 10
};
- }
+ },
+ audio: AudioLibrary.BUY_BULLETS
},
'energy cell': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'scales': 10,
'teeth': 10
};
- }
+ },
+ audio: AudioLibrary.BUY_ENERGY_CELL
},
'bolas': {
type: 'weapon',
- cost: function() {
+ cost: function () {
return {
'teeth': 10
};
- }
+ },
+ audio: AudioLibrary.BUY_BOLAS
},
'grenade': {
type: 'weapon',
- cost: function() {
+ cost: function () {
return {
'scales': 100,
'teeth': 50
};
- }
+ },
+ audio: AudioLibrary.BUY_GRENADES
},
'bayonet': {
type: 'weapon',
- cost: function() {
+ cost: function () {
return {
'scales': 500,
'teeth': 250
};
- }
+ },
+ audio: AudioLibrary.BUY_BAYONET
},
'alien alloy': {
type: 'good',
- cost: function() {
+ cost: function () {
return {
'fur': 1500,
'scales': 750,
'teeth': 300
};
- }
+ },
+ audio: AudioLibrary.BUY_ALIEN_ALLOY
},
'compass': {
type: 'special',
maximum: 1,
- cost: function() {
- return {
- fur: 400,
- scales: 20,
- teeth: 10
+ cost: function () {
+ return {
+ fur: 400,
+ scales: 20,
+ teeth: 10
};
- }
+ },
+ audio: AudioLibrary.BUY_COMPASS
}
},
-
+
MiscItems: {
'laser rifle': {
type: 'weapon'
}
},
-
+
name: _("Room"),
- init: function(options) {
+ init: function (options) {
this.options = $.extend(
this.options,
options
);
-
+
Room.pathDiscovery = Boolean($SM.get('stores["compass"]'));
- if(Engine._debug) {
+ 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') {
+
+ 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'));
-
+ $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',
@@ -499,9 +534,9 @@ var Room = {
click: Room.lightFire,
cooldown: Room._STOKE_COOLDOWN,
width: '80px',
- cost: {'wood': 5}
+ cost: { 'wood': 5 }
}).appendTo('div#roomPanel');
-
+
// Create the stoke button
new Button.Button({
id: 'stokeButton',
@@ -509,23 +544,23 @@ var Room = {
click: Room.stokeFire,
cooldown: Room._STOKE_COOLDOWN,
width: '80px',
- cost: {'wood': 1}
+ cost: { 'wood': 1 }
}).appendTo('div#roomPanel');
-
+
// Create the stores container
$('
').attr('id', 'storesContainer').prependTo('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
@@ -534,10 +569,10 @@ var Room = {
* 3 - Sleeping
* 4 - Helping
*/
- if($SM.get('game.builder.level') >= 0 && $SM.get('game.builder.level') < 3) {
+ 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) {
+ 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);
@@ -545,33 +580,35 @@ var Room = {
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) {
+
+ onArrival: function (transition_diff) {
Room.setTitle();
- if(Room.changed) {
+ 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) {
+ if ($SM.get('game.builder.level') == 3) {
$SM.add('game.builder.level', 1);
$SM.setIncome('builder', {
delay: 10,
- stores: {'wood' : 2 }
+ 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);
+
+ Room.setMusic();
},
-
+
TempEnum: {
- fromInt: function(value) {
- for(var k in this) {
- if(typeof this[k].value != 'undefined' && this[k].value == value) {
+ fromInt: function (value) {
+ for (var k in this) {
+ if (typeof this[k].value != 'undefined' && this[k].value == value) {
return this[k];
}
}
@@ -583,11 +620,11 @@ var Room = {
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) {
+ fromInt: function (value) {
+ for (var k in this) {
+ if (typeof this[k].value != 'undefined' && this[k].value == value) {
return this[k];
}
}
@@ -599,33 +636,33 @@ var Room = {
Burning: { value: 3, text: _('burning') },
Roaring: { value: 4, text: _('roaring') }
},
-
- setTitle: function() {
+
+ setTitle: function () {
var title = $SM.get('game.fire.value') < 2 ? _("A Dark Room") : _("A Firelit Room");
- if(Engine.activeModule == this) {
+ if (Engine.activeModule == this) {
document.title = title;
}
$('div#location_room').text(title);
},
-
- updateButton: function() {
+
+ updateButton: function () {
var light = $('#lightButton.button');
var stoke = $('#stokeButton.button');
- if($SM.get('game.fire.value') == Room.FireEnum.Dead.value && stoke.css('display') != 'none') {
+ if ($SM.get('game.fire.value') == Room.FireEnum.Dead.value && stoke.css('display') != 'none') {
stoke.hide();
light.show();
- if(stoke.hasClass('disabled')) {
+ if (stoke.hasClass('disabled')) {
Button.cooldown(light);
}
- } else if(light.css('display') != 'none') {
+ } else if (light.css('display') != 'none') {
stoke.show();
light.hide();
- if(light.hasClass('disabled')) {
+ if (light.hasClass('disabled')) {
Button.cooldown(stoke);
}
}
-
- if(!$SM.get('stores.wood')) {
+
+ if (!$SM.get('stores.wood')) {
light.addClass('free');
stoke.addClass('free');
} else {
@@ -633,215 +670,222 @@ var Room = {
stoke.removeClass('free');
}
},
-
+
_fireTimer: null,
_tempTimer: null,
- lightFire: function() {
+ lightFire: function () {
var wood = $SM.get('stores.wood');
- if(wood < 5) {
+ if (wood < 5) {
Notifications.notify(Room, _("not enough wood to get the fire going"));
Button.clearCooldown($('#lightButton.button'));
return;
- } else if(wood > 4) {
+ } else if (wood > 4) {
$SM.set('stores.wood', wood - 5);
}
$SM.set('game.fire', Room.FireEnum.Burning);
+ AudioEngine.playSound(AudioLibrary.LIGHT_FIRE);
Room.onFireChange();
},
-
- stokeFire: function() {
+
+ stokeFire: function () {
var wood = $SM.get('stores.wood');
- if(wood === 0) {
+ if (wood === 0) {
Notifications.notify(Room, _("the wood has run out"));
Button.clearCooldown($('#stokeButton.button'));
return;
}
- if(wood > 0) {
+ if (wood > 0) {
$SM.set('stores.wood', wood - 1);
}
- if($SM.get('game.fire.value') < 4) {
+ if ($SM.get('game.fire.value') < 4) {
$SM.set('game.fire', Room.FireEnum.fromInt($SM.get('game.fire.value') + 1));
}
+ AudioEngine.playSound(AudioLibrary.STOKE_FIRE);
Room.onFireChange();
},
-
- onFireChange: function() {
- if(Engine.activeModule != Room) {
+
+ 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) {
+ 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();
+
+ // only update music if in the room
+ if (Engine.activeModule == Room) {
+ Room.setMusic();
+ }
},
-
- coolFire: function() {
+
+ coolFire: function () {
var wood = $SM.get('stores.wood');
- if($SM.get('game.fire.value') <= Room.FireEnum.Flickering.value &&
+ 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));
+ $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));
+ 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() {
+
+ 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') > 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')) {
+ 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);
+ Notifications.notify(Room, _("the room is {0}", Room.TempEnum.fromInt($SM.get('game.temperature.value')).text), true);
}
- if($SM.get('game.temperature.value') != old) {
+ if ($SM.get('game.temperature.value') != old) {
Room.changed = true;
}
Room._tempTimer = Engine.setTimeout(Room.adjustTemp, Room._ROOM_WARM_DELAY);
},
-
- unlockForest: function() {
+
+ 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() {
+
+ updateBuilderState: function () {
var lBuilder = $SM.get('game.builder.level');
- if(lBuilder === 0) {
+ 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) {
+ }
+ 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;
+ 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) {
+ if (lBuilder < 3) {
lBuilder = $SM.setget('game.builder.level', lBuilder + 1);
}
}
- if(lBuilder < 3) {
+ if (lBuilder < 3) {
Engine.setTimeout(Room.updateBuilderState, Room._BUILDER_STATE_DELAY);
}
Engine.saveGame();
},
-
- updateStoresView: function() {
+
+ updateStoresView: function () {
var stores = $('div#stores');
var resources = $('div#resources');
var special = $('div#special');
var weapons = $('div#weapons');
var needsAppend = false, rNeedsAppend = false, sNeedsAppend = false, wNeedsAppend = false, newRow = false;
- if(stores.length === 0) {
+ if (stores.length === 0) {
stores = $('
').attr({
'id': 'stores',
'data-legend': _('stores')
}).css('opacity', 0);
needsAppend = true;
}
- if(resources.length === 0) {
+ if (resources.length === 0) {
resources = $('
').attr({
id: 'resources'
}).css('opacity', 0);
rNeedsAppend = true;
}
- if(special.length === 0) {
+ if (special.length === 0) {
special = $('
').attr({
id: 'special'
}).css('opacity', 0);
sNeedsAppend = true;
}
- if(weapons.length === 0) {
+ if (weapons.length === 0) {
weapons = $('
').attr({
'id': 'weapons',
'data-legend': _('weapons')
}).css('opacity', 0);
wNeedsAppend = true;
}
- for(var k in $SM.get('stores')) {
-
+ for (var k in $SM.get('stores')) {
+
var type = null;
- if(Room.Craftables[k]) {
+ if (Room.Craftables[k]) {
type = Room.Craftables[k].type;
- } else if(Room.TradeGoods[k]) {
+ } 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 'building':
- // Don't display buildings either
- continue;
- case 'weapon':
- location = weapons;
- break;
- case 'special':
- location = special;
- break;
- default:
- location = resources;
- break;
+ switch (type) {
+ case 'upgrade':
+ // Don't display upgrades on the Room screen
+ continue;
+ case 'building':
+ // Don't display buildings either
+ continue;
+ case 'weapon':
+ location = weapons;
+ break;
+ case 'special':
+ location = special;
+ break;
+ default:
+ location = resources;
+ break;
}
-
+
var id = "row_" + k.replace(' ', '-');
var row = $('div#' + id, location);
- var num = $SM.get('stores["'+k+'"]');
-
- if(typeof num != 'number' || isNaN(num)) {
+ 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);
+ $SM.set('stores["' + k + '"]', 0);
}
-
+
var lk = _(k);
-
+
// thieves?
- if(typeof $SM.get('game.thieves') == 'undefined' && num > 5000 && $SM.get('features.location.world')) {
+ if (typeof $SM.get('game.thieves') == 'undefined' && num > 5000 && $SM.get('features.location.world')) {
$SM.startThieves();
}
-
- if(row.length === 0) {
+
+ if (row.length === 0) {
row = $('
').attr('id', id).addClass('storeRow');
$('
').addClass('row_key').text(lk).appendTo(row);
$('
').addClass('row_val').text(Math.floor(num)).appendTo(row);
$('
').addClass('clear').appendTo(row);
var curPrev = null;
- location.children().each(function(i) {
+ location.children().each(function (i) {
var child = $(this);
var cName = child.children('.row_key').text();
- if(cName < lk) {
+ if (cName < lk) {
curPrev = child.attr('id');
}
});
- if(curPrev == null) {
+ if (curPrev == null) {
row.prependTo(location);
} else {
row.insertAfter(location.find('#' + curPrev));
@@ -851,55 +895,55 @@ var Room = {
$('div#' + row.attr('id') + ' > div.row_val', location).text(Math.floor(num));
}
}
-
- if(rNeedsAppend && resources.children().length > 0) {
+
+ if (rNeedsAppend && resources.children().length > 0) {
resources.prependTo(stores);
- resources.animate({opacity: 1}, 300, 'linear');
+ resources.animate({ opacity: 1 }, 300, 'linear');
}
-
- if(sNeedsAppend && special.children().length > 0) {
+
+ if (sNeedsAppend && special.children().length > 0) {
special.appendTo(stores);
- special.animate({opacity: 1}, 300, 'linear');
+ special.animate({ opacity: 1 }, 300, 'linear');
}
-
- if(needsAppend && stores.find('div.storeRow').length > 0) {
+
+ if (needsAppend && stores.find('div.storeRow').length > 0) {
stores.appendTo('div#storesContainer');
- stores.animate({opacity: 1}, 300, 'linear');
+ stores.animate({ opacity: 1 }, 300, 'linear');
}
-
- if(wNeedsAppend && weapons.children().length > 0) {
+
+ if (wNeedsAppend && weapons.children().length > 0) {
weapons.appendTo('div#storesContainer');
- weapons.animate({opacity: 1}, 300, 'linear');
+ weapons.animate({ opacity: 1 }, 300, 'linear');
}
-
- if(newRow) {
+
+ if (newRow) {
Room.updateIncomeView();
}
- if($("div#outsidePanel").length) {
+ if ($("div#outsidePanel").length) {
Outside.updateVillage();
}
- if($SM.get('stores.compass') && !Room.pathDiscovery){
+ if ($SM.get('stores.compass') && !Room.pathDiscovery) {
Room.pathDiscovery = true;
Path.openPath();
}
},
-
- updateIncomeView: function() {
+
+ updateIncomeView: function () {
var stores = $('div#resources');
var totalIncome = {};
- if(stores.length === 0 || typeof $SM.get('income') == 'undefined') return;
- $('div.storeRow', stores).each(function(index, el) {
+ if (stores.length === 0 || typeof $SM.get('income') == 'undefined') return;
+ $('div.storeRow', stores).each(function (index, el) {
el = $(el);
$('div.tooltip', el).remove();
var ttPos = index > 10 ? 'top right' : 'bottom right';
var tt = $('
').addClass('tooltip ' + ttPos);
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) {
+ 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')
@@ -913,7 +957,7 @@ var Room = {
}
}
}
- if(tt.children().length > 0) {
+ if (tt.children().length > 0) {
var total = totalIncome[storeName].income;
$('
').addClass('total row_key').text(_('total')).appendTo(tt);
$('
').addClass('total row_val').text(Engine.getIncomeMsg(total, totalIncome[storeName].delay)).appendTo(tt);
@@ -921,21 +965,21 @@ var Room = {
}
});
},
-
- buy: function(buyBtn) {
+
+ 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) {
+ 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]) {
+ 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 {
@@ -943,141 +987,156 @@ var Room = {
}
}
$SM.setM('stores', storeMod);
-
+
Notifications.notify(Room, good.buildMsg);
-
- $SM.add('stores["'+thing+'"]', 1);
+
+ $SM.add('stores["' + thing + '"]', 1);
+
+ // audio
+ AudioEngine.playSound(AudioLibrary.BUY);
},
-
- build: function(buildBtn) {
+
+ build: function (buildBtn) {
var thing = $(buildBtn).attr('buildThing');
- if($SM.get('game.temperature.value') <= Room.TempEnum.Cold.value) {
+ 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;
+
+ 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) {
+
+ 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));
+ 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;
- }
+
+ 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;
+ }
+
+ // audio
+ switch (craftable.type) {
+ case 'weapon':
+ case 'upgrade':
+ case 'tool':
+ AudioEngine.playSound(AudioLibrary.CRAFT);
+ break;
+ case 'building':
+ AudioEngine.playSound(AudioLibrary.BUILD);
+ break;
+ }
},
-
- needsWorkshop: function(type) {
- return type == 'weapon' || type == 'upgrade' || type =='tool';
+
+ needsWorkshop: function (type) {
+ return type == 'weapon' || type == 'upgrade' || type == 'tool';
},
-
- craftUnlocked: function(thing) {
- if(Room.buttons[thing]) {
+
+ craftUnlocked: function (thing) {
+ if (Room.buttons[thing]) {
return true;
}
- if($SM.get('game.builder.level') < 4) return false;
+ 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;
+ 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){
+ 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) {
+ if ($SM.get('stores.wood', true) < cost['wood'] * 0.5) {
return false;
}
- for(var c in cost) {
- if(!$SM.get('stores["'+c+'"]')) {
+ 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+'"]')){
+ if (!$SM.get('game.buildings["' + thing + '"]')) {
Notifications.notify(Room, craftable.availableMsg);
}
return true;
},
-
- buyUnlocked: function(thing) {
- if(Room.buttons[thing]) {
+
+ 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') {
+ } 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() {
+
+ updateBuildButtons: function () {
var buildSection = $('#buildBtns');
var needsAppend = false;
- if(buildSection.length === 0) {
- buildSection = $('
').attr({'id': 'buildBtns', 'data-legend': _('build:')}).css('opacity', 0);
+ if (buildSection.length === 0) {
+ buildSection = $('
').attr({ 'id': 'buildBtns', 'data-legend': _('build:') }).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', 'data-legend': _('craft:')}).css('opacity', 0);
+ if (craftSection.length === 0 && $SM.get('game.buildings["workshop"]', true) > 0) {
+ craftSection = $('
').attr({ 'id': 'craftBtns', 'data-legend': _('craft:') }).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', 'data-legend': _('buy:')}).css('opacity', 0);
+ if (buySection.length === 0 && $SM.get('game.buildings["trading post"]', true) > 0) {
+ buySection = $('
').attr({ 'id': 'buyBtns', 'data-legend': _('buy:') }).css('opacity', 0);
bNeedsAppend = true;
}
-
- for(var k in Room.Craftables) {
+
+ 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)) {
+ if (craftable.button == null) {
+ if (Room.craftUnlocked(k)) {
var loc = Room.needsWorkshop(craftable.type) ? craftSection : buildSection;
craftable.button = new Button.Button({
id: 'build_' + k,
@@ -1086,33 +1145,33 @@ var Room = {
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');
+ }).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 c in cost) {
+ for (var c in cost) {
$("
").addClass('row_key').text(_(c)).appendTo(costTooltip);
$("
").addClass('row_val').text(cost[c]).appendTo(costTooltip);
}
- if(max && !craftable.button.hasClass('disabled')) {
+ if (max && !craftable.button.hasClass('disabled')) {
Notifications.notify(Room, craftable.maxMsg);
}
}
- if(max) {
+ if (max) {
Button.setDisabled(craftable.button, true);
} else {
Button.setDisabled(craftable.button, false);
}
}
-
- for(var g in Room.TradeGoods) {
+
+ for (var g in Room.TradeGoods) {
good = Room.TradeGoods[g];
var goodsMax = $SM.num(g, good) + 1 > good.maximum;
- if(good.button == null) {
- if(Room.buyUnlocked(g)) {
+ if (good.button == null) {
+ if (Room.buyUnlocked(g)) {
good.button = new Button.Button({
id: 'build_' + g,
cost: good.cost(),
@@ -1120,55 +1179,77 @@ var Room = {
click: Room.buy,
width: '80px',
ttPos: buySection.children().length > 10 ? 'top right' : 'bottom right'
- }).css('opacity', 0).attr('buildThing', g).appendTo(buySection).animate({opacity:1}, 300, 'linear');
+ }).css('opacity', 0).attr('buildThing', g).appendTo(buySection).animate({ opacity: 1 }, 300, 'linear');
}
} else {
// refresh the tooltip
var goodsCostTooltip = $('.tooltip', good.button);
goodsCostTooltip.empty();
var goodCost = good.cost();
- for(var gc in goodCost) {
+ for (var gc in goodCost) {
$("
").addClass('row_key').text(_(gc)).appendTo(goodsCostTooltip);
$("
").addClass('row_val').text(goodCost[gc]).appendTo(goodsCostTooltip);
}
- if(goodsMax && !good.button.hasClass('disabled')) {
+ if (goodsMax && !good.button.hasClass('disabled')) {
Notifications.notify(Room, good.maxMsg);
}
}
- if(goodsMax) {
+ if (goodsMax) {
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 (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 (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');
+ if (bNeedsAppend && buildSection.children().length > 0) {
+ buySection.appendTo('div#roomPanel').animate({ opacity: 1 }, 300, 'linear');
}
},
-
- compassTooltip: function(direction){
+
+ compassTooltip: function (direction) {
var ttPos = $('div#resources').children().length > 10 ? 'top right' : 'bottom right';
var tt = $('
').addClass('tooltip ' + ttPos);
- $('
').addClass('row_key').text(_('the compass points '+ direction)).appendTo(tt);
+ $('
').addClass('row_key').text(_('the compass points ' + direction)).appendTo(tt);
tt.appendTo($('#row_compass'));
},
-
- handleStateUpdates: function(e){
- if(e.category == 'stores'){
+
+ handleStateUpdates: function (e) {
+ if (e.category == 'stores') {
Room.updateStoresView();
Room.updateBuildButtons();
- } else if(e.category == 'income'){
+ } else if (e.category == 'income') {
Room.updateStoresView();
Room.updateIncomeView();
- } else if(e.stateName.indexOf('game.buildings') === 0){
+ } else if (e.stateName.indexOf('game.buildings') === 0) {
Room.updateBuildButtons();
}
+ },
+
+ setMusic() {
+ // set music based on fire level
+ var fireValue = $SM.get('game.fire.value');
+ switch (fireValue) {
+ case 0:
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_FIRE_DEAD);
+ break;
+ case 1:
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_FIRE_SMOLDERING);
+ break;
+ case 2:
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_FIRE_FLICKERING);
+ break;
+ case 3:
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_FIRE_BURNING);
+ break;
+ case 4:
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_FIRE_ROARING);
+ break;
+ }
}
};
diff --git a/script/ship.js b/script/ship.js
index a513f9d..3cfd1bc 100644
--- a/script/ship.js
+++ b/script/ship.js
@@ -7,7 +7,6 @@ var Ship = {
ALLOY_PER_THRUSTER: 1,
BASE_HULL: 0,
BASE_THRUSTERS: 1,
-
name: _("Ship"),
init: function(options) {
this.options = $.extend(
@@ -91,6 +90,7 @@ var Ship = {
Notifications.notify(Ship, _('somewhere above the debris cloud, the wanderer fleet hovers. been on this rock too long.'));
$SM.set('game.spaceShip.seenShip', true);
}
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_SHIP);
Engine.moveStoresView(null, transition_diff);
},
@@ -112,6 +112,7 @@ var Ship = {
Button.setDisabled($('#liftoffButton', Ship.panel), false);
}
$('#hullRow .row_val', Ship.panel).text($SM.get('game.spaceShip.hull'));
+ AudioEngine.playSound(AudioLibrary.REINFORCE_HULL);
},
upgradeEngine: function() {
@@ -122,6 +123,7 @@ var Ship = {
$SM.add('stores["alien alloy"]', -Ship.ALLOY_PER_THRUSTER);
$SM.add('game.spaceShip.thrusters', 1);
$('#engineRow .row_val', Ship.panel).text($SM.get('game.spaceShip.thrusters'));
+ AudioEngine.playSound(AudioLibrary.UPGRADE_ENGINE);
},
getMaxHull: function() {
@@ -166,6 +168,7 @@ var Ship = {
$('#outerSlider').animate({top: '700px'}, 300);
Space.onArrival();
Engine.activeModule = Space;
+ AudioEngine.playSound(AudioLibrary.LIFT_OFF);
},
handleStateUpdates: function(e){
diff --git a/script/space.js b/script/space.js
index 0c4c235..eb109c0 100644
--- a/script/space.js
+++ b/script/space.js
@@ -11,7 +11,6 @@ var Space = {
NUM_STARS: 200,
STAR_SPEED: 60000,
FRAME_DELAY: 100,
-
stars: null,
backStars: null,
ship: null,
@@ -54,6 +53,7 @@ var Space = {
Space.hull = Ship.getMaxHull();
Space.altitude = 0;
Space.setTitle();
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_SPACE);
Space.updateHull();
Space.up =
@@ -67,6 +67,8 @@ var Space = {
});
Space.startAscent();
Space._shipTimer = setInterval(Space.moveShip, 33);
+ Space._volumeTimer = setInterval(Space.lowerVolume, 1000);
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_SPACE);
},
setTitle: function() {
@@ -136,6 +138,21 @@ var Space = {
t.remove();
Space.hull--;
Space.updateHull();
+
+ // play audio on asteroid hit
+ // higher altitudes play higher frequency hits
+ var r = Math.floor(Math.random() * 2);
+ if(Space.altitude > 40) {
+ r += 6;
+ AudioEngine.playSound(AudioLibrary['ASTEROID_HIT_' + r]);
+ } else if(Space.altitude > 20) {
+ r += 4;
+ AudioEngine.playSound(AudioLibrary['ASTEROID_HIT_' + r]);
+ } else {
+ r += 1;
+ AudioEngine.playSound(AudioLibrary['ASTEROID_HIT_' + r]);
+ }
+
if(Space.hull === 0) {
Space.crash();
}
@@ -221,7 +238,7 @@ var Space = {
left: x + 'px',
top: y + 'px'
});
-
+
Space.lastMove = Date.now();
},
@@ -325,6 +342,7 @@ var Space = {
Space.done = true;
clearInterval(Space._timer);
clearInterval(Space._shipTimer);
+ clearInterval(Space._volumeTimer);
clearTimeout(Space._panelTimeout);
var body_color;
if (Engine.isLightsOff())
@@ -358,6 +376,7 @@ var Space = {
Ship.onArrival();
Button.cooldown($('#liftoffButton'));
Engine.event('progress', 'crash');
+ AudioEngine.playSound(AudioLibrary.CRASH);
},
endGame: function() {
@@ -366,6 +385,7 @@ var Space = {
Space.done = true;
clearInterval(Space._timer);
clearInterval(Space._shipTimer);
+ clearInterval(Space._volumeTimer);
clearTimeout(Engine._saveTimer);
clearTimeout(Outside._popTimeout);
clearTimeout(Engine._incomeTimeout);
@@ -380,6 +400,8 @@ var Space = {
}
delete Outside._popTimeout;
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_ENDING);
+
$('#hullRemaining', Space.panel).animate({opacity: 0}, 500, 'linear');
Space.ship.animate({
top: '350px',
@@ -532,5 +554,14 @@ var Space = {
handleStateUpdates: function(e){
+ },
+
+ lowerVolume: function () {
+ if (Space.done) return;
+
+ // lower audio as ship gets further into space
+ var progress = Space.altitude / 60;
+ var newVolume = 1.0 - progress;
+ AudioEngine.setBackgroundMusicVolume(newVolume, 0.3);
}
};
diff --git a/script/world.js b/script/world.js
index 12b1950..f6dc6d5 100644
--- a/script/world.js
+++ b/script/world.js
@@ -1,5 +1,4 @@
var World = {
-
RADIUS: 30,
VILLAGE_POS: [30, 30],
TILE: {
@@ -347,6 +346,11 @@ var World = {
World.lightMap(World.curPos[0], World.curPos[1], World.state.mask);
World.drawMap();
World.doSpace();
+
+ // play random footstep
+ var randomFootstep = Math.floor(Math.random() * 5) + 1;
+ AudioEngine.playSound(AudioLibrary['FOOTSTEPS_' + randomFootstep]);
+
if(World.checkDanger()) {
if(World.danger) {
Notifications.notify(World, _('dangerous to be this far from the village without proper protection'));
@@ -534,6 +538,7 @@ var World = {
} else if(typeof World.LANDMARKS[curTile] != 'undefined') {
if(curTile != World.TILE.OUTPOST || !World.outpostUsed()) {
Events.startEvent(Events.Setpieces[World.LANDMARKS[curTile].scene]);
+ AudioEngine.playEventMusic(Events.Setpieces[World.LANDMARKS[curTile].scene].audio);
}
} else {
if(World.useSupplies()) {
@@ -883,6 +888,7 @@ var World = {
World.state = null;
Path.outfit = {};
$SM.remove('outfit');
+ AudioEngine.playSound(AudioLibrary.DEATH);
$('#outerSlider').animate({opacity: '0'}, 600, 'linear', function() {
$('#outerSlider').css('left', '0px');
$('#locationSlider').css('left', '0px');
@@ -1006,6 +1012,7 @@ var World = {
World.curPos = World.copyPos(World.VILLAGE_POS);
World.drawMap();
World.setTitle();
+ AudioEngine.playBackgroundMusic(AudioLibrary.MUSIC_WORLD);
World.dead = false;
$('div#bagspace-world > div').empty();
World.updateSupplies();
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..a2134bf
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,368 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+accepts@~1.3.7:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+ integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+ dependencies:
+ mime-types "~2.1.24"
+ negotiator "0.6.2"
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+
+body-parser@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
+ integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
+ dependencies:
+ bytes "3.1.0"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "~1.1.2"
+ http-errors "1.7.2"
+ iconv-lite "0.4.24"
+ on-finished "~2.3.0"
+ qs "6.7.0"
+ raw-body "2.4.0"
+ type-is "~1.6.17"
+
+bytes@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
+ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
+
+content-disposition@0.5.3:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
+ integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
+ dependencies:
+ safe-buffer "5.1.2"
+
+content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+
+cookie@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
+ integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
+
+debug@2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+
+express@^4.17.1:
+ version "4.17.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
+ integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
+ dependencies:
+ accepts "~1.3.7"
+ array-flatten "1.1.1"
+ body-parser "1.19.0"
+ content-disposition "0.5.3"
+ content-type "~1.0.4"
+ cookie "0.4.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "~1.1.2"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "~1.1.2"
+ fresh "0.5.2"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.5"
+ qs "6.7.0"
+ range-parser "~1.2.1"
+ safe-buffer "5.1.2"
+ send "0.17.1"
+ serve-static "1.14.1"
+ setprototypeof "1.1.1"
+ statuses "~1.5.0"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+finalhandler@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.3"
+ statuses "~1.5.0"
+ unpipe "~1.0.0"
+
+forwarded@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+ integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+
+http-errors@1.7.2:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
+ integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.1"
+ statuses ">= 1.5.0 < 2"
+ toidentifier "1.0.0"
+
+http-errors@~1.7.2:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
+ integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.4"
+ setprototypeof "1.1.1"
+ statuses ">= 1.5.0 < 2"
+ toidentifier "1.0.0"
+
+iconv-lite@0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
+inherits@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ipaddr.js@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
+
+mime-db@1.44.0:
+ version "1.44.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
+ integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
+
+mime-types@~2.1.24:
+ version "2.1.27"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
+ integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
+ dependencies:
+ mime-db "1.44.0"
+
+mime@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+negotiator@0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
+ integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
+ dependencies:
+ ee-first "1.1.1"
+
+parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+
+proxy-addr@~2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
+ integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
+ dependencies:
+ forwarded "~0.1.2"
+ ipaddr.js "1.9.1"
+
+qs@6.7.0:
+ version "6.7.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
+ integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
+
+range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
+ integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
+ dependencies:
+ bytes "3.1.0"
+ http-errors "1.7.2"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+safe-buffer@5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+send@0.17.1:
+ version "0.17.1"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
+ integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
+ dependencies:
+ debug "2.6.9"
+ depd "~1.1.2"
+ destroy "~1.0.4"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "~1.7.2"
+ mime "1.6.0"
+ ms "2.1.1"
+ on-finished "~2.3.0"
+ range-parser "~1.2.1"
+ statuses "~1.5.0"
+
+serve-static@1.14.1:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
+ integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.17.1"
+
+setprototypeof@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
+ integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
+
+"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+
+toidentifier@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
+ integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+
+type-is@~1.6.17, type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=