connect majority actions to sound effects;add more placeholder loops and effects

This commit is contained in:
jorsi
2020-05-30 19:48:44 -04:00
parent 71786c3671
commit 1d84e5f85c
20 changed files with 202 additions and 119 deletions
+97 -38
View File
@@ -2,30 +2,28 @@
* Module that takes care of audio playback
*/
var AudioEngine = {
canPlayAudio: false,
FADE_TIME: 1,
AUDIO_BUFFER_CACHE: {},
audioContext: null,
master: null,
// Tracks for playing music and sound effects
// 0 - Background music
// 1 - Background music
// 2 - Event music
// 3 - Sound effects
tracks: null,
currentBackgroundChannel: 0,
currentTrack: null,
tracks: {
'bg1': null,
'bg2': null,
'events': null,
'sfx': null
},
currentBackgroundChannel: 'bg1',
currentBackgroundAudio: null,
currentEventAudio: null,
init: function(options) {
// for legacy browsers
AudioEngine.audioContext = new (window.AudioContext || window.webkitAudioContext);
audioLog('starting audio engine');
console.log(AudioEngine.audioContext);
audioLog('state: ' + AudioEngine.audioContext.state);
if (AudioEngine.audioContext.state === 'suspended') {
AudioEngine.audioContext.resume().then(function () {
AudioEngine.createChannels();
AudioEngine.canPlayAudio = true;
});
} else {
AudioEngine.createChannels();
@@ -34,72 +32,133 @@ var AudioEngine = {
createChannels() {
// create master
AudioEngine.master = AudioEngine.audioContext.createGain();
AudioEngine.master.gain.setValueAtTime(1.0, AudioEngine.audioContext.currentTime);
AudioEngine.master.connect(AudioEngine.audioContext.destination);
// create 4 tracks to output to master
AudioEngine.tracks = [];
for (var i = 0; i < 4; i++) {
AudioEngine.tracks[i] = AudioEngine.audioContext.createGain();
AudioEngine.tracks[i].connect(AudioEngine.master);
}
AudioEngine.tracks['bg1'] = AudioEngine.audioContext.createGain();
AudioEngine.tracks['bg1'].connect(AudioEngine.master);
AudioEngine.tracks['bg1'].gain.setValueAtTime(1.0, AudioEngine.audioContext.currentTime);
AudioEngine.tracks['bg2'] = AudioEngine.audioContext.createGain();
AudioEngine.tracks['bg2'].connect(AudioEngine.master);
AudioEngine.tracks['bg2'].gain.setValueAtTime(1.0, AudioEngine.audioContext.currentTime);
AudioEngine.tracks['events'] = AudioEngine.audioContext.createGain();
AudioEngine.tracks['events'].connect(AudioEngine.master);
AudioEngine.tracks['events'].gain.setValueAtTime(1.0, AudioEngine.audioContext.currentTime);
AudioEngine.tracks['sfx'] = AudioEngine.audioContext.createGain();
AudioEngine.tracks['sfx'].connect(AudioEngine.master);
AudioEngine.tracks['sfx'].gain.setValueAtTime(1.0, AudioEngine.audioContext.currentTime);
},
options: {}, // Nothing for now,
_canPlayAudio: function() {
if (AudioEngine.audioContext.state === 'suspended') {
audioLog('can\'t play audio');
return false;
}
return true;
},
options: {}, // Nothing for now
_playSound: function(buffer) {
if (!AudioEngine.canPlayAudio) return;
if (!AudioEngine._canPlayAudio()) return;
var source = AudioEngine.audioContext.createBufferSource();
source.buffer = buffer;
source.connect(AudioEngine.tracks[1]);
source.connect(AudioEngine.tracks['sfx']);
source.start(AudioEngine.audioContext.currentTime);
},
_fadeTrack: function(buffer) {
if (!AudioEngine.canPlayAudio) return;
if (!AudioEngine._canPlayAudio()) return;
var newTrack = AudioEngine.audioContext.createBufferSource();
newTrack.buffer = buffer;
newTrack.loop = true;
audioLog('_fadeMusic');
console.log(buffer);
var bufferSource = AudioEngine.audioContext.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.loop = true;
// figure out which background track to start on
// in order to do crossfade
var nextBackgroundChannel;
if (AudioEngine.currentBackgroundChannel === 0) {
nextBackgroundChannel = 1;
if (AudioEngine.currentBackgroundChannel === 'bg1') {
nextBackgroundChannel = 'bg2';
} else {
nextBackgroundChannel = 0;
nextBackgroundChannel = 'bg1';
}
// fade in new track
var fadeTime = AudioEngine.audioContext.currentTime + 2.0;
newTrack.connect(AudioEngine.tracks[nextBackgroundChannel]);
newTrack.start(0);
var fadeTime = AudioEngine.audioContext.currentTime + AudioEngine.FADE_TIME;
bufferSource.connect(AudioEngine.tracks[nextBackgroundChannel]);
bufferSource.start(AudioEngine.audioContext.currentTime);
AudioEngine.tracks[nextBackgroundChannel].gain.setValueAtTime(0.0, AudioEngine.audioContext.currentTime);
AudioEngine.tracks[nextBackgroundChannel].gain.linearRampToValueAtTime(.1, fadeTime);
AudioEngine.tracks[nextBackgroundChannel].gain.linearRampToValueAtTime(1.0, fadeTime);
// fade out old track
AudioEngine.tracks[AudioEngine.currentBackgroundChannel].gain.linearRampToValueAtTime(0.0, fadeTime);
if (AudioEngine.currentTrack) {
AudioEngine.currentTrack.stop(fadeTime + 0.3); // make sure fade has completed
if (AudioEngine.currentBackgroundAudio) {
AudioEngine.currentBackgroundAudio.stop(fadeTime + 0.3); // make sure fade has completed
}
// switch background track
AudioEngine.currentBackgroundChannel = nextBackgroundChannel;
AudioEngine.currentTrack = newTrack;
AudioEngine.currentBackgroundAudio = bufferSource;
},
_playEvent: function(buffer) {
if (!AudioEngine._canPlayAudio()) return;
var bufferSource = AudioEngine.audioContext.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.loop = true;
var fadeTime = AudioEngine.audioContext.currentTime + AudioEngine.FADE_TIME * 2;
// turn down background music
AudioEngine.tracks['bg1'].gain.linearRampToValueAtTime(0.2, fadeTime);
AudioEngine.tracks['bg2'].gain.linearRampToValueAtTime(0.2, fadeTime);
// fade in event music
bufferSource.connect(AudioEngine.tracks['events']);
bufferSource.start(0);
AudioEngine.currentEventAudio = bufferSource;
AudioEngine.tracks['events'].gain.setValueAtTime(0.0, AudioEngine.audioContext.currentTime);
AudioEngine.tracks['events'].gain.linearRampToValueAtTime(1.0, fadeTime);
},
_stopEventMusic: function() {
var fadeTime = AudioEngine.audioContext.currentTime + AudioEngine.FADE_TIME * 2;
// fade out event music and stop
AudioEngine.tracks['events'].gain.linearRampToValueAtTime(0.0, fadeTime);
if (AudioEngine.currentEventAudio) {
AudioEngine.currentEventAudio.stop(fadeTime + 1); // make sure fade has completed
AudioEngine.currentEventAudio = null;
}
// turn up background music
AudioEngine.tracks[AudioEngine.currentBackgroundChannel].gain.linearRampToValueAtTime(1.0, fadeTime);
},
changeMusic: function(src) {
AudioEngine.loadAudioFile(src)
.then(function (buffer) {
audioLog('changeMusic: ' + src);
AudioEngine._fadeTrack(buffer);
});
audioLog('change music: ' + src);
audioLog('audio engine status: ' + AudioEngine.audioContext.state);
},
playEventMusic: function(src) {
AudioEngine.loadAudioFile(src)
.then(function (buffer) {
audioLog('playEventMusic: ' + src);
AudioEngine._playEvent(buffer);
});
},
stopEventMusic: function() {
audioLog('stopEventMusic');
AudioEngine._stopEventMusic();
},
playSound: function(src) {
AudioEngine.loadAudioFile(src)
.then(function (buffer) {
audioLog('playSound: ' + src);
AudioEngine._playSound(buffer);
});
audioLog('play sound: ' + src);
audioLog('audio engine status: ' + AudioEngine.audioContext.state);
},
loadAudioFile(src) {
if (AudioEngine.AUDIO_BUFFER_CACHE[src]) {
+3 -2
View File
@@ -540,7 +540,6 @@ var Events = {
clearTimeout(Events._enemyAttackTimer);
Events.endEvent();
World.die();
AudioEngine.playSound(Events.SOUNDS['lose-fight']);
}
});
@@ -1044,7 +1043,7 @@ var Events = {
Events.startEvent(possibleEvents[r]);
console.log('event', possibleEvents[r].audio);
AudioEngine.playSound(Events.SOUNDS['trigger-event']);
AudioEngine.changeMusic(possibleEvents[r].audio);
AudioEngine.playEventMusic(possibleEvents[r].audio);
}
}
@@ -1066,6 +1065,7 @@ var Events = {
// play audio only when fight is possible
if (possibleFights.length > 0) {
AudioEngine.playSound(Events.SOUNDS['trigger-fight']);
AudioEngine.playEventMusic(possibleFights[r].audio);
}
},
@@ -1112,6 +1112,7 @@ var Events = {
},
endEvent: function() {
AudioEngine.stopEventMusic();
Events.eventPanel().animate({opacity:0}, Events._PANEL_FADE, 'linear', function() {
Events.eventPanel().remove();
Events.activeEvent().eventPanel = null;
+2
View File
@@ -607,6 +607,7 @@ var Outside = {
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(Outside.SOUNDS['gather-wood']);
},
checkTraps: function() {
@@ -647,6 +648,7 @@ var Outside = {
Notifications.notify(Outside, s);
$SM.addM('stores', drops);
AudioEngine.playSound(Outside.SOUNDS['check-traps']);
},
handleStateUpdates: function(e){
+1
View File
@@ -327,6 +327,7 @@ var Path = {
World.onArrival();
$('#outerSlider').animate({left: '-700px'}, 300);
Engine.activeModule = World;
AudioEngine.playSound(Path.SOUNDS['embark']);
},
handleStateUpdates: function(e){
+77 -74
View File
@@ -18,43 +18,7 @@ var Room = {
},
SOUNDS: {
'light-fire': '/audio/light-fire.wav',
'stoke-fire': '/audio/stoke-fire.wav',
'build-trap': '/audio/build-trap.wav',
'build-cart': '/audio/build-cart.wav',
'build-hut': '/audio/build-hut.wav',
'build-lodge': '/audio/build-lodge.wav',
'build-trading-post': '/audio/build-trading-post.wav',
'build-tannery': '/audio/build-tannery.wav',
'build-smokehouse': '/audio/build-smokehouse.wav',
'build-workshop': '/audio/build-workshop.wav',
'build-steelworks': '/audio/build-steelworks.wav',
'build-armoury': '/audio/build-armoury.wav',
'craft-torch': '/audio/craft-torch.wav',
'craft-waterskin': '/audio/craft-waterskin.wav',
'craft-bone-spear': '/audio/craft-bone-spear.wav',
'craft-rucksack': '/audio/craft-rucksack.wav',
'craft-cask': '/audio/craft-cask.wav',
'craft-leather-armour': '/audio/craft-leather-armour.wav',
'craft-wagon': '/audio/craft-wagon.wav',
'craft-iron-armour': '/audio/craft-iron-armour.wav',
'craft-iron-sword': '/audio/craft-iron-sword.wav',
'craft-water-tank': '/audio/craft-water-tank.wav',
'craft-convoy': '/audio/craft-convoy.wav',
'craft-steel-armour': '/audio/craft-steel-armour.wav',
'craft-steel-sword': '/audio/craft-steel-sword.wav',
'craft-rifle': '/audio/craft-rifle.wav',
'buy-scales': '/audio/buy-scales.wav',
'buy-teeth': '/audio/buy-teeth.wav',
'buy-compass': '/audio/buy-compass.wav',
'buy-iron': '/audio/buy-iron.wav',
'buy-steel': '/audio/buy-steel.wav',
'buy-bolas': '/audio/buy-bolas.wav',
'buy-bullets': '/audio/buy-bullets.wav',
'buy-bayonet': '/audio/buy-bayonet.wav',
'buy-alien-alloy': '/audio/buy-alien-alloy.wav',
'buy-energy-cell': '/audio/buy-energy-cell.wav',
'buy-grenade': '/audio/buy-grenade.wav',
'buy-coal': '/audio/buy-coal.wav',
'stoke-fire': '/audio/stoke-fire.wav'
},
buttons: {},
Craftables: {
@@ -71,7 +35,8 @@ var Room = {
return {
'wood': 10 + (n * 10)
};
}
},
audio: '/audio/build-trap.wav'
},
'cart': {
name: _('cart'),
@@ -84,7 +49,8 @@ var Room = {
return {
'wood': 30
};
}
},
audio: '/audio/build-cart.wav'
},
'hut': {
name: _('hut'),
@@ -99,7 +65,8 @@ var Room = {
return {
'wood': 100 + (n * 50)
};
}
},
audio: '/audio/build-hut.wav'
},
'lodge': {
name: _('lodge'),
@@ -114,7 +81,8 @@ var Room = {
fur: 10,
meat: 5
};
}
},
audio: '/audio/build-lodge.wav'
},
'trading post': {
name: _('trading post'),
@@ -128,7 +96,8 @@ var Room = {
'wood': 400,
'fur': 100
};
}
},
audio: '/audio/build-trading-post.wav'
},
'tannery': {
name: _('tannery'),
@@ -142,7 +111,8 @@ var Room = {
'wood': 500,
'fur': 50
};
}
},
audio: '/audio/build-tannery.wav'
},
'smokehouse': {
name: _('smokehouse'),
@@ -156,7 +126,8 @@ var Room = {
'wood': 600,
'meat': 50
};
}
},
audio: '/audio/build-smokehouse.wav'
},
'workshop': {
name: _('workshop'),
@@ -171,7 +142,8 @@ var Room = {
'leather': 100,
'scales': 10
};
}
},
audio: '/audio/build-workshop.wav'
},
'steelworks': {
name: _('steelworks'),
@@ -186,7 +158,8 @@ var Room = {
'iron': 100,
'coal': 100
};
}
},
audio: '/audio/build-steelworks.wav'
},
'armoury': {
name: _('armoury'),
@@ -201,7 +174,8 @@ var Room = {
'steel': 100,
'sulphur': 50
};
}
},
audio: '/audio/build-armoury.wav'
},
'torch': {
name: _('torch'),
@@ -213,7 +187,8 @@ var Room = {
'wood': 1,
'cloth': 1
};
}
},
audio: '/audio/craft-torch.wav'
},
'waterskin': {
name: _('waterskin'),
@@ -225,7 +200,8 @@ var Room = {
return {
'leather': 50
};
}
},
audio: '/audio/craft-waterskin.wav'
},
'cask': {
name: _('cask'),
@@ -238,7 +214,8 @@ var Room = {
'leather': 100,
'iron': 20
};
}
},
audio: '/audio/craft-cask.wav'
},
'water tank': {
name: _('water tank'),
@@ -251,7 +228,8 @@ var Room = {
'iron': 100,
'steel': 50
};
}
},
audio: '/audio/craft-water-tank.wav'
},
'bone spear': {
name: _('bone spear'),
@@ -263,7 +241,8 @@ var Room = {
'wood': 100,
'teeth': 5
};
}
},
audio: '/audio/craft-bone-spear.wav'
},
'rucksack': {
name: _('rucksack'),
@@ -275,7 +254,8 @@ var Room = {
return {
'leather': 200
};
}
},
audio: '/audio/craft-rucksack.wav'
},
'wagon': {
name: _('wagon'),
@@ -288,7 +268,8 @@ var Room = {
'wood': 500,
'iron': 100
};
}
},
audio: '/audio/craft-wagon.wav'
},
'convoy': {
name: _('convoy'),
@@ -302,7 +283,8 @@ var Room = {
'iron': 200,
'steel': 100
};
}
},
audio: '/audio/craft-convoy.wav'
},
'l armour': {
name: _('l armour'),
@@ -314,7 +296,8 @@ var Room = {
'leather': 200,
'scales': 20
};
}
},
audio: '/audio/craft-leather-armour.wav'
},
'i armour': {
name: _('i armour'),
@@ -326,7 +309,8 @@ var Room = {
'leather': 200,
'iron': 100
};
}
},
audio: '/audio/craft-iron-armour.wav'
},
's armour': {
name: _('s armour'),
@@ -338,7 +322,8 @@ var Room = {
'leather': 200,
'steel': 100
};
}
},
audio: '/audio/craft-steel-armour.wav'
},
'iron sword': {
name: _('iron sword'),
@@ -351,7 +336,8 @@ var Room = {
'leather': 50,
'iron': 20
};
}
},
audio: '/audio/craft-iron-sword.wav'
},
'steel sword': {
name: _('steel sword'),
@@ -364,7 +350,8 @@ var Room = {
'leather': 100,
'steel': 20
};
}
},
audio: '/audio/craft-steel-sword.wav'
},
'rifle': {
name: _('rifle'),
@@ -376,7 +363,8 @@ var Room = {
'steel': 50,
'sulphur': 50
};
}
},
audio: '/audio/craft-rifle.wav'
}
},
@@ -385,13 +373,15 @@ var Room = {
type: 'good',
cost: function () {
return { fur: 150 };
}
},
audio: '/audio/buy-scales.wav'
},
'teeth': {
type: 'good',
cost: function () {
return { fur: 300 };
}
},
audio: '/audio/buy-teeth.wav'
},
'iron': {
type: 'good',
@@ -400,7 +390,8 @@ var Room = {
'fur': 150,
'scales': 50
};
}
},
audio: '/audio/buy-iron.wav'
},
'coal': {
type: 'good',
@@ -409,7 +400,8 @@ var Room = {
'fur': 200,
'teeth': 50
};
}
},
audio: '/audio/buy-coal.wav'
},
'steel': {
type: 'good',
@@ -419,7 +411,8 @@ var Room = {
'scales': 50,
'teeth': 50
};
}
},
audio: '/audio/buy-steel.wav'
},
'medicine': {
type: 'good',
@@ -427,7 +420,8 @@ var Room = {
return {
'scales': 50, 'teeth': 30
};
}
},
audio: '/audio/buy-medicine.wav'
},
'bullets': {
type: 'good',
@@ -435,7 +429,8 @@ var Room = {
return {
'scales': 10
};
}
},
audio: '/audio/buy-bullets.wav'
},
'energy cell': {
type: 'good',
@@ -444,7 +439,8 @@ var Room = {
'scales': 10,
'teeth': 10
};
}
},
audio: '/audio/buy-energy-cell.wav'
},
'bolas': {
type: 'weapon',
@@ -452,7 +448,8 @@ var Room = {
return {
'teeth': 10
};
}
},
audio: '/audio/buy-bolas.wav'
},
'grenade': {
type: 'weapon',
@@ -461,7 +458,8 @@ var Room = {
'scales': 100,
'teeth': 50
};
}
},
audio: '/audio/buy-grenade.wav'
},
'bayonet': {
type: 'weapon',
@@ -470,7 +468,8 @@ var Room = {
'scales': 500,
'teeth': 250
};
}
},
audio: '/audio/buy-bayonet.wav'
},
'alien alloy': {
type: 'good',
@@ -480,7 +479,8 @@ var Room = {
'scales': 750,
'teeth': 300
};
}
},
audio: '/audio/buy-alien-alloy.wav'
},
'compass': {
type: 'special',
@@ -491,7 +491,8 @@ var Room = {
scales: 20,
teeth: 10
};
}
},
audio: '/audio/buy-compass.wav'
}
},
@@ -1000,6 +1001,7 @@ var Room = {
Notifications.notify(Room, good.buildMsg);
$SM.add('stores["' + thing + '"]', 1);
AudioEngine.playSound(good.audio);
},
build: function (buildBtn) {
@@ -1054,6 +1056,7 @@ var Room = {
$SM.add('game.buildings["' + thing + '"]', 1);
break;
}
AudioEngine.playSound(craftable.audio);
},
needsWorkshop: function (type) {
+3
View File
@@ -121,6 +121,7 @@ var Ship = {
Button.setDisabled($('#liftoffButton', Ship.panel), false);
}
$('#hullRow .row_val', Ship.panel).text($SM.get('game.spaceShip.hull'));
AudioEngine.playSound(Ship.SOUNDS['reinforce-hull']);
},
upgradeEngine: function() {
@@ -131,6 +132,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(Ship.SOUNDS['upgrade-engine']);
},
getMaxHull: function() {
@@ -175,6 +177,7 @@ var Ship = {
$('#outerSlider').animate({top: '700px'}, 300);
Space.onArrival();
Engine.activeModule = Space;
AudioEngine.playSound(Ship.SOUNDS['lift-off']);
},
handleStateUpdates: function(e){
+15 -5
View File
@@ -25,6 +25,7 @@ var Space = {
'asteroid-hit-1': '/audio/asteroid-hit-1.wav',
'asteroid-hit-2': '/audio/asteroid-hit-2.wav',
'asteroid-hit-3': '/audio/asteroid-hit-3.wav',
'crash': '/audio/crash.wav',
},
stars: null,
backStars: null,
@@ -68,6 +69,7 @@ var Space = {
Space.hull = Ship.getMaxHull();
Space.altitude = 0;
Space.setTitle();
AudioEngine.changeMusic(Space.MUSIC[0]);
Space.updateHull();
Space.up =
@@ -81,7 +83,6 @@ var Space = {
});
Space.startAscent();
Space._shipTimer = setInterval(Space.moveShip, 33);
Space.setMusic();
},
setTitle: function() {
@@ -89,16 +90,22 @@ var Space = {
var t;
if(Space.altitude < 10) {
t = _("Troposphere");
AudioEngine.changeMusic(Space.MUSIC[1]);
} else if(Space.altitude < 20) {
t = _("Stratosphere");
AudioEngine.changeMusic(Space.MUSIC[2]);
} else if(Space.altitude < 30) {
t = _("Mesosphere");
AudioEngine.changeMusic(Space.MUSIC[3]);
} else if(Space.altitude < 45) {
t = _("Thermosphere");
AudioEngine.changeMusic(Space.MUSIC[4]);
} else if(Space.altitude < 60){
t = _("Exosphere");
AudioEngine.changeMusic(Space.MUSIC[5]);
} else {
t = _("Space");
AudioEngine.changeMusic(Space.MUSIC[0]);
}
document.title = t;
}
@@ -151,6 +158,11 @@ var Space = {
t.remove();
Space.hull--;
Space.updateHull();
// play random asteroid hit
var r = Math.floor(Math.random() * 2) + 1;
AudioEngine.playSound(Space.SOUNDS['asteroid-hit-' + r]);
if(Space.hull === 0) {
Space.crash();
}
@@ -373,6 +385,7 @@ var Space = {
Ship.onArrival();
Button.cooldown($('#liftoffButton'));
Engine.event('progress', 'crash');
AudioEngine.playSound(Space.SOUNDS['crash']);
},
endGame: function() {
@@ -395,6 +408,7 @@ var Space = {
}
delete Outside._popTimeout;
AudioEngine.changeMusic(Space.MUSIC[6]);
$('#hullRemaining', Space.panel).animate({opacity: 0}, 500, 'linear');
Space.ship.animate({
top: '350px',
@@ -547,9 +561,5 @@ var Space = {
handleStateUpdates: function(e){
},
setMusic: function () {
AudioEngine.changeMusic(Space.MUSIC[0]);
}
};
+4
View File
@@ -8,6 +8,8 @@ var World = {
'footsteps-1': '/audio/footsteps-1.wav',
'footsteps-2': '/audio/footsteps-2.wav',
'footsteps-3': '/audio/footsteps-3.wav',
'death-starved': '/audio/death-starved.wav',
'death-dehydrated': '/audio/death-dehydrated.wav',
},
RADIUS: 30,
VILLAGE_POS: [30, 30],
@@ -488,6 +490,7 @@ var World = {
$SM.addPerk('slow metabolism');
}
World.die();
AudioEngine.playSound(World.SOUNDS['death-starved']);
return false;
}
} else {
@@ -517,6 +520,7 @@ var World = {
$SM.addPerk('desert rat');
}
World.die();
AudioEngine.playSound(World.SOUNDS['death-dehydrated']);
return false;
}
} else {