Files
adarkroom/script/engine.js
T
LucidCrux dee7cbb9b3 refactor Engine.js for use with $SM
====functions removed====
//I just removed these because most were simpler or at least equal as
	direct $SM get/set/add calls, I realize the store ones are kind of
	subjective since calls were about equal, but oh well. If someone
	really 	feels we need the shortcut/named functions for manipulating
	stores specifically, it shouldn't be crazy to reimplement in $SM 
Engine.setStore >> $SM.set
Engine.setStores >> $SM.setM
Engine.addStore >> $SM.add
Engine.addStores >> $SM.addM
Engine.getStore >> $SM.get(requestZero = true)
Engine.storeAvailable >> $SM.get;
Engine.removeIncome >> $SM.remove //updates moved to handler


====functions moved====
//Any moved function I felt was more directly related to States or
	didn't belong where it was
Engine.addPerk > $SM.addPerk //kept function for now because of notify
	call inside, 'deep' state
Engine.hasPerk > $SM.hasPerk //kept function because of 'deep' state
	name
Engine.setIncome > $SM.setIncome //kept because it has internal logic
**Engine.getIncome > $SM.getIncome //**easily removable with
	Outside.updateVillageIncome refactor
Engine.openPath > Path.openPath //Since I'm refactoring anyways
Engine.addStolen > $SM.addStolen //internal logic
Engine.startThieves > $SM.startThieves //not sure $SM is a better place,
	but Engine should be nice and clean by the end of this, handling
	only engine mechanics
Engine.num > $SM.num //after Outside refacter, this is basically just a
	fancy $SM.get
Engine.upgradeState > $SM.updateOldState


====functions refactored====
$SM.addPerk; //updates moved to event handler, no check/create new perk
$SM.hasPerk; //don't need to check exist and ==true
$SM.collectIncome //removed changed check, update calls now handled by
	'stateUpdate' event listening
$SM.addStolen //fix to set stolen items in case a partial steal happens
$SM.startThieves //updates in handler
$SM.updateOldState //use $SM calls, add placeholder for updating to post
$SM state when more finalized 


====functions affected (by removed)====
Engine.init (Engine.getStore, Engine.storeAvailable)
Engine.collectIncome (Engine.addStores)
Engine.num (Engine.getStore)
Engine.travelTo (Engine.storeAvailable)

Room.init (Engine.getStore)
Room.unlockForest (Engine.setStore)
Room.lightFire (Engine.setStore, Engine.getStore, Engine.storeAvailable)
Room.stokeFire (Engine.setStore, Engine.getStore, Engine.storeAvailable)
Room.coolFire (Engine.setStore)
Room.buy (Engine.setStores, Engine.addStore, Engine.getStore)
Room.build (Engine.setStores, Engine.getStore)
Room.craftUnlocked (Engine.getStore, Engine.storeAvailable)
Room.buyUnlocked (Engine.storeAvailable)
Room.updateButton (Engine.storeAvailable)

Outside.gatherWood (Engine.addStores)
Outside.checkTraps (Engine.addStores, Engine.getStore)
Outside.updateVillage (Engine.getStore)

Path.embark (Engine.addStore)
Path.getCapacity (Engine.getStore)
Path.updateOutfitting (Engine.getStore)
Path.createOutfittingRow (Engine.getStore)
Path.increaseSupply (Engine.getStore)

World.goHome (Engine.addStore)
World.updateSupplies (Engine.getStore)
World.checkDanger (Engine.getStore)
World.getMaxHealth (Engine.getStore)
World.getMaxWater (Engine.getStore)

Ship.reinforceHull (Engine.addStore, Engine.getStore)
Ship.upgradeEngine (Engine.addStore, Engine.getStore)

Events.loadScene (Engine.addStores)
Events.updateButtons (Engine.getStore)
Events.buttonClick (Engine.getStore)

Events.Global (Engine.addStores, Engine.removeIncome)
Events.Room (Engine.addStore, Engine.addStores, Engine.getStore,
Engine.storeAvailable)
2013-07-24 17:41:36 -06:00

395 lines
10 KiB
JavaScript

var Engine = {
/* TODO *** MICHAEL IS A LAZY BASTARD AND DOES NOT WANT TO REFACTOR ***
* Here is what he should be doing:
* - All updating values (store numbers, incomes, etc...) should be objects that can register listeners to
* value-change events. These events should be fired whenever a value (or group of values, I suppose) is updated.
* That would be so elegant and awesome.
*/
SITE_URL: encodeURIComponent("http://adarkroom.doublespeakgames.com"),
VERSION: 1.2;
MAX_STORE: 99999999999999,
SAVE_DISPLAY: 30 * 1000,
Perks: {
'boxer': {
desc: 'punches do more damage',
notify: 'learned to throw punches with purpose'
},
'martial artist': {
desc: 'punches do even more damage.',
notify: 'learned to fight quite effectively without weapons'
},
'unarmed master': {
desc: 'punch twice as fast, and with even more force',
notify: 'learned to strike faster without weapons'
},
'barbarian': {
desc: 'melee weapons deal more damage',
notify: 'learned to swing weapons with force'
},
'slow metabolism': {
desc: 'go twice as far without eating',
notify: 'learned how to ignore the hunger'
},
'desert rat': {
desc: 'go twice as far without drinking',
notify: 'learned to love the dry air'
},
'evasive': {
desc: 'dodge attacks more effectively',
notify: "learned to be where they're not"
},
'precise': {
desc: 'land blows more often',
notify: 'learned to predict their movement'
},
'scout': {
desc: 'see farther',
notify: 'learned to look ahead'
},
'stealthy': {
desc: 'better avoid conflict in the wild',
notify: 'learned how not to be seen'
},
'gastronome': {
desc: 'restore more health when eating',
notify: 'learned to make the most of food'
}
},
options: {
state: null,
debug: true,
log: true
},
init: function(options) {
this.options = $.extend(
this.options,
options
);
this._debug = this.options.debug;
this._log = this.options.log;
// Check for HTML5 support
if(!Engine.browserValid()) {
window.location = 'browserWarning.html';
}
// Check for mobile
if(Engine.isMobile()) {
window.location = 'mobileWarning.html';
}
if(this.options.state != null) {
window.State = this.options.state;
} else {
Engine.loadGame();
}
$('<div>').attr('id', 'locationSlider').appendTo('#main');
$('<span>')
.addClass('deleteSave')
.text('restart.')
.click(Engine.confirmDelete)
.appendTo('body');
$('<div>')
.addClass('share')
.text('share.')
.click(Engine.share)
.appendTo('body');
// Register keypress handlers
$('body').off('keydown').keydown(Engine.keyDown);
$('body').off('keyup').keyup(Engine.keyUp);
// Register swipe handlers
swipeElement = $('#outerSlider');
swipeElement.on('swipeleft', Engine.swipeLeft);
swipeElement.on('swiperight', Engine.swipeRight);
swipeElement.on('swipeup', Engine.swipeUp);
swipeElement.on('swipedown', Engine.swipeDown);
$SM.init();
Notifications.init();
Events.init();
Room.init();
if($SM.get('stores.wood')) {
Outside.init();
}
if($SM.get('stores.compass', true) > 0) {
Path.init();
}
if($SM.get('features.location.spaceShip')) {
Ship.init();
}
Engine.travelTo(Room);
},
browserValid: function() {
return location.search.indexOf('ignorebrowser=true') >= 0 || (
typeof Storage != 'undefined' &&
!oldIE);
},
isMobile: function() {
return location.search.indexOf('ignorebrowser=true') < 0 &&
/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
},
saveGame: function() {
if(typeof Storage != 'undefined' && localStorage) {
if(Engine._saveTimer != null) {
clearTimeout(Engine._saveTimer);
}
if(typeof Engine._lastNotify == 'undefined' || Date.now() - Engine._lastNotify > Engine.SAVE_DISPLAY){
$('#saveNotify').css('opacity', 1).animate({opacity: 0}, 1000, 'linear');
Engine._lastNotify = Date.now();
}
localStorage.gameState = JSON.stringify(State);
}
},
loadGame: function() {
try {
var savedState = JSON.parse(localStorage.gameState);
if(savedState) {
State = savedState;
$SM.updateOldState();
Engine.log("loaded save!");
}
} catch(e) {
$SM.set('verson', Engine.VERSION);
Engine.event('progress', 'new game');
}
},
event: function(cat, act) {
if(typeof ga === 'function') {
ga('send', 'event', cat, act);
}
},
confirmDelete: function() {
Events.startEvent({
title: 'Restart?',
scenes: {
start: {
text: ['restart the game?'],
buttons: {
'yes': {
text: 'yes',
nextScene: 'end',
onChoose: Engine.deleteSave
},
'no': {
text: 'no',
nextScene: 'end'
}
}
}
}
});
},
deleteSave: function() {
if(typeof Storage != 'undefined' && localStorage) {
localStorage.clear();
}
location.reload();
},
share: function() {
Events.startEvent({
title: 'Share',
scenes: {
start: {
text: ['bring your friends.'],
buttons: {
'facebook': {
text: 'facebook',
nextScene: 'end',
onChoose: function() {
window.open('https://www.facebook.com/sharer/sharer.php?u=' + Engine.SITE_URL, 'sharer', 'width=626,height=436,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no');
}
},
'google': {
text:'google+',
nextScene: 'end',
onChoose: function() {
window.open('https://plus.google.com/share?url=' + Engine.SITE_URL, 'sharer', 'width=480,height=436,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no');
}
},
'twitter': {
text: 'twitter',
onChoose: function() {
window.open('https://twitter.com/intent/tweet?text=A%20Dark%20Room&url=' + Engine.SITE_URL, 'sharer', 'width=660,height=260,location=no,menubar=no,resizable=no,scrollbars=yes,status=no,toolbar=no');
},
nextScene: 'end'
},
'reddit': {
text: 'reddit',
onChoose: function() {
window.open('http://www.reddit.com/submit?url=' + Engine.SITE_URL, 'sharer', 'width=960,height=700,location=no,menubar=no,resizable=no,scrollbars=yes,status=no,toolbar=no');
},
nextScene: 'end'
},
'close': {
text: 'close',
nextScene: 'end'
}
}
}
}
}, {width: '400px'});
},
// Gets a guid
getGuid: function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
},
activeModule: null,
travelTo: function(module) {
if(Engine.activeModule != module) {
var currentIndex = Engine.activeModule ? $('.location').index(Engine.activeModule.panel) : 1;
$('div.headerButton').removeClass('selected');
module.tab.addClass('selected');
var slider = $('#locationSlider');
var stores = $('#storesContainer');
var panelIndex = $('.location').index(module.panel);
var diff = Math.abs(panelIndex - currentIndex);
slider.animate({left: -(panelIndex * 700) + 'px'}, 300 * diff);
if($SM.get('stores.wood')) {
// FIXME Why does this work if there's an animation queue...?
stores.animate({right: -(panelIndex * 700) + 'px'}, 300 * diff);
}
module.onArrival(diff);
if(Engine.activeModule == Room || Engine.activeModule == Path) {
// Don't fade out the weapons if we're switching to a module
// where we're going to keep showing them anyway.
if (module != Room && module != Path) {
$('div#weapons').animate({opacity: 0}, 300);
}
}
if(module == Room || module == Path) {
$('div#weapons').animate({opacity: 1}, 300);
}
Engine.activeModule = module;
Notifications.printQueue(module);
}
},
// Move the stores panel beneath top_container (or to top: 0px if top_container
// either hasn't been filled in or is null) using transition_diff to sync with
// the animation in Engine.travelTo().
moveStoresView: function(top_container, transition_diff) {
var stores = $('#storesContainer');
// If we don't have a storesContainer yet, leave.
if(typeof(stores) === 'undefined') return;
if(typeof(transition_diff) === 'undefined') transition_diff = 1;
if(top_container === null) {
stores.animate({top: '0px'}, {queue: false, duration: 300 * transition_diff});
}
else if(!top_container.length) {
stores.animate({top: '0px'}, {queue: false, duration: 300 * transition_diff});
}
else {
stores.animate({top: top_container.height() + 26 + 'px'},
{queue: false, duration: 300 * transition_diff});
}
},
log: function(msg) {
if(this._log) {
console.log(msg);
}
},
updateSlider: function() {
var slider = $('#locationSlider');
slider.width((slider.children().length * 700) + 'px');
},
updateOuterSlider: function() {
var slider = $('#outerSlider');
slider.width((slider.children().length * 700) + 'px');
},
getIncomeMsg: function(num, delay) {
return (num > 0 ? "+" : "") + num + " per " + delay + "s";
},
keyDown: function(e) {
if(!Engine.keyPressed && !Engine.keyLock) {
Engine.pressed = true;
if(Engine.activeModule.keyDown) {
Engine.activeModule.keyDown(e);
}
}
return false;
},
keyUp: function(e) {
Engine.pressed = false;
if(Engine.activeModule.keyUp) {
Engine.activeModule.keyUp(e);
}
return false;
},
swipeLeft: function(e) {
if(Engine.activeModule.swipeLeft) {
Engine.activeModule.swipeLeft(e);
}
},
swipeRight: function(e) {
if(Engine.activeModule.swipeRight) {
Engine.activeModule.swipeRight(e);
}
},
swipeUp: function(e) {
if(Engine.activeModule.swipeUp) {
Engine.activeModule.swipeUp(e);
}
},
swipeDown: function(e) {
if(Engine.activeModule.swipeDown) {
Engine.activeModule.swipeDown(e);
}
},
handleStateUpdates: function(e){
},
};
//listener for StateManager update events
$(Engine).on('stateUpdate', Engine.handleStateUpdates);
$(function() {
Engine.init();
});