mirror of
https://github.com/doublespeakgames/adarkroom.git
synced 2026-05-28 00:01:54 +08:00
dee7cbb9b3
====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)
339 lines
9.9 KiB
JavaScript
339 lines
9.9 KiB
JavaScript
/*
|
|
* Module for handling States
|
|
*
|
|
* All states should be get and set through the StateManager ($SM).
|
|
*
|
|
* The manager is intended to handle all needed checks and error catching.
|
|
* This includes creating the parents of layered/deep states so undefined states
|
|
* do not need to be tested for and created beforehand.
|
|
*
|
|
* When a state is changed, an update event is sent out containing the name of the state
|
|
* changed or in the case of multiple changes (.setM, .addM) the parent class changed.
|
|
* Event: type: 'stateUpdate', stateName: <path of state or parent state>
|
|
*
|
|
* Original file created by: Michael Galusha
|
|
*/
|
|
|
|
var StateManager = {
|
|
|
|
MAX_STORE: 99999999999999,
|
|
|
|
options: {},
|
|
|
|
init: function(options) {
|
|
this.options = $.extend(
|
|
this.options,
|
|
options
|
|
);
|
|
|
|
//create categories
|
|
var cats = [
|
|
'features', //big features like buildings, location availability, unlocks, etc
|
|
'stores', //little stuff, items, weapons, etc
|
|
'character', //this is for player's character stats such as perks
|
|
'income',
|
|
'timers',
|
|
'game', //mostly location related: fire temp, workers, population, world map, etc
|
|
'playStats', //anything play related: play time, loads, etc
|
|
];
|
|
|
|
for(var which in cats) {
|
|
if(!$SM.get(cats[which])) $SM.set(cats[which], {});
|
|
};
|
|
},
|
|
|
|
//create the parent of a given state, recursive as needed
|
|
createParent: function(stateName) {
|
|
var err = 0;
|
|
|
|
//parse path to find last child
|
|
var lastDot = stateName.lastIndexOf('.'); //if ends with a dot, there is a coding bug, not like ending in a bracket, so don't account for it
|
|
if(lastDot == stateName.length) {
|
|
Engine.log('ERROR: '+stateName+' is invalid. Cannot end in a dot.');
|
|
return;
|
|
}
|
|
var lastOB = stateName.lastIndexOf('[');
|
|
//make sure last bracket isn't just end of the line
|
|
var lastCB = stateName.substr(0, stateName.length -1).lastIndexOf(']');
|
|
//account for state[foo][bar] double bracket and state[foo].bar
|
|
if(lastCB == lastOB - 1) lastOB = -1;
|
|
if(lastCB == lastDot -1) lastDot = -1;
|
|
//find last child or return if no more children
|
|
var cutoff = Math.max(lastDot, lastOB, lastCB);
|
|
if(cutoff <= 0) return;
|
|
|
|
var parentPath = $SM.buildPath(stateName.substr(0,cutoff));
|
|
|
|
//try creating the parent
|
|
try {
|
|
eval('('+parentPath+') = {}');
|
|
} catch (e) {
|
|
//need to go up another level and make parent of parent
|
|
$SM.createParent(stateName.substr(0,cutoff));
|
|
//then it will definitely work if not, something is fubar
|
|
eval('('+parentPath+') = {}');
|
|
}
|
|
},
|
|
|
|
//set single state
|
|
//if noEvent is true, the update event won't trigger, useful for setting multiple states first
|
|
set: function(stateName, value, noEvent) {
|
|
var fullPath = $SM.buildPath(stateName);
|
|
|
|
//make sure the value isn't over the engine maximum
|
|
if(typeof value == 'number' && value > $SM.MAX_STORE) value = $SM.MAX_STORE;
|
|
|
|
try{
|
|
eval('('+fullPath+') = value');
|
|
} catch (e) {
|
|
//parent doesn't exist, so make parent
|
|
$SM.createParent(stateName);
|
|
//now it will definitely work. if not, something is broken
|
|
eval('('+fullPath+') = value');
|
|
}
|
|
|
|
//stores values can not be negative
|
|
if(stateName.indexOf('stores') == 0 && $SM.get(stateName, true) < 0) {
|
|
eval('('+fullPath+') = 0');;
|
|
Engine.log('WARNING: state:' + stateName + ' can not be a negative value. Set to 0 instead.')
|
|
}
|
|
|
|
if(!noEvent) {
|
|
Engine.saveGame();
|
|
$SM.fireUpdate(stateName);
|
|
}
|
|
},
|
|
|
|
//sets a list of states
|
|
setM: function(parentName, list, noEvent) {
|
|
var whichParent = $SM.buildPath(parentName);
|
|
|
|
//make sure the state exists to avoid errors,
|
|
if($SM.get(parentName) == undefined) $SM.set(parentName, {}, true);
|
|
|
|
for(var k in list){
|
|
$SM.set(parentName+'[\''+k+'\']', list[k], true);
|
|
}
|
|
|
|
if(!noEvent) {
|
|
Engine.saveGame();
|
|
$SM.fireUpdate(parentName);
|
|
}
|
|
},
|
|
|
|
//shortcut for altering number values, return 1 if state wasn't a number
|
|
add: function(stateName, value, noEvent) {
|
|
var err = 0;
|
|
//0 if undefined, null (but not {}) should allow adding to new objects
|
|
//could also add in a true = 1 thing, to have something go from existing (true)
|
|
//to be a count, but that might be unwanted behavior (add with loose eval probably will happen anyways)
|
|
var old = $SM.get(stateName, true);
|
|
|
|
//check for NaN (old == old) and non number values
|
|
if(old == old){
|
|
Engine.log('WARNING: '+stateName+' was corrupted (NaN). Resetting to 0.');
|
|
old = 0;
|
|
$SM.set(stateName, old + value, noEvent);//setState handles event and save
|
|
} else if(typeof old != 'number' || typeof value != 'number'){
|
|
Engine.log('WARNING: Can not do math with state:'+stateName+' or value:'+value+' because at least one is not a number.');
|
|
err = 1
|
|
} else {
|
|
$SM.set(stateName, old + value, noEvent); //setState handles event and save
|
|
}
|
|
|
|
return err;
|
|
},
|
|
|
|
//alters multiple number values, return number of fails
|
|
addM: function(parentName, list, noEvent) {
|
|
var err = 0;
|
|
|
|
//make sure the parent exists to avoid errors
|
|
if($SM.get(parentName) == undefined) $SM.set(parentName, {}, true);
|
|
|
|
for(var k in list){
|
|
if(!$SM.add(parentName+'[\''+k+'\']', list[k], true)) err++;
|
|
}
|
|
|
|
if(!noEvent) {
|
|
Engine.saveGame();
|
|
$SM.fireUpdate(parentName);
|
|
}
|
|
return err;
|
|
},
|
|
|
|
//return state, undefined or 0
|
|
get: function(stateName, requestZero) {
|
|
var whichState = null;
|
|
var fullPath = $SM.buildPath(stateName, name);
|
|
|
|
//catch errors if parent of state doesn't exist
|
|
try{
|
|
eval('whichState = ('+fullPath+')');
|
|
} catch (e) {
|
|
whichState = undefined;
|
|
}
|
|
|
|
//prevents repeated if undefined, null, false or {}, then x = 0 situations
|
|
if((!whichState || whichState == {}) && requestZero) return 0;
|
|
else return whichState;
|
|
},
|
|
|
|
remove: function(stateName, noEvent) {
|
|
var whichState = $SM.buildPath(whichState);
|
|
try{
|
|
delete eval(whichState);
|
|
} catch (e) {
|
|
//it didn't exist in the first place
|
|
Engine.log('WARNING: Tried to remove non-existant state \''+stateName+'\'.');
|
|
}
|
|
if(!noEvent){
|
|
Engine.saveGame();
|
|
$SM.fireUpdate(stateName);
|
|
};
|
|
},
|
|
|
|
//creates full reference from input
|
|
//hopefully this won't ever need to be more complicated
|
|
buildPath: function(input){
|
|
var dot = (input.charAt(0) == '[')? '' : '.'; //if it starts with [foo] no dot to join
|
|
return 'State' + dot + input;
|
|
},
|
|
|
|
|
|
|
|
fireUpdate: function(stateName, save){
|
|
if(stateName == undefined) stateName = 'all'; //best if this doesn't happen as it will trigger more stuff
|
|
$.event.trigger({
|
|
'type': 'stateUpdate',
|
|
'stateName': stateName,
|
|
});
|
|
if(save) Engine.saveGame();
|
|
},
|
|
|
|
//Use this function to make old save games compatible with new version
|
|
updateOldState: function(){
|
|
var version = $SM.get('version');
|
|
if(typeof version != 'number') version = 1.0;
|
|
if(version == 1.0) {
|
|
// v1.1 introduced the Lodge, so get rid of lodgeless hunters
|
|
$SM.remove('outside.workers.hunter', true);
|
|
$SM.remove('income.hunter', true);
|
|
Engine.log('upgraded save to v1.1');
|
|
version = 1.1;
|
|
};
|
|
if(version == 1.1) {
|
|
//v1.2 added the Swamp to the map, so add it to already generated maps
|
|
if($SM.get('world')) {
|
|
World.placeLandmark(15, World.RADIUS * 1.5, World.TILE.SWAMP, $SM.get('world.map'));
|
|
}
|
|
Engine.log('upgraded save to v1.2');
|
|
version = 1.2;
|
|
};
|
|
if(version == 1.2) {
|
|
//StateManager added, so move data to new locations
|
|
};
|
|
},
|
|
|
|
/******************************************************************
|
|
* Start of specific state functions
|
|
******************************************************************/
|
|
//PERKS
|
|
addPerk: function(name) {
|
|
$SM.set('character.perks[\''+name+'\']', true);
|
|
Notifications.notify(null, Engine.Perks[name].notify);
|
|
},
|
|
|
|
hasPerk: function(name) {
|
|
return $SM.get('character.perks[\''+name+'\']') == true;
|
|
},
|
|
|
|
//INCOME
|
|
setIncome: function(source, options) {
|
|
var existing = $SM.get('income[\''+source+'\']');
|
|
if(typeof existing != 'undefined') {
|
|
options.timeLeft = existing.timeLeft;
|
|
}
|
|
$SM.set('income[\''+source+'\']', options);
|
|
},
|
|
|
|
getIncome: function(source) {
|
|
var existing = $SM.get('income[\''+source+'\']');
|
|
if(typeof existing != 'undefined') {
|
|
return existing;
|
|
}
|
|
return {};
|
|
},
|
|
|
|
collectIncome: function() {
|
|
if(typeof $SM.get('income') != 'undefined' && Engine.activeModule != Space) {
|
|
for(var source in $SM.get('income')) {
|
|
var income = $SM.get('income[\''+source+'\']');
|
|
if(typeof income.timeLeft != 'number')
|
|
{
|
|
income.timeLeft = 0;
|
|
}
|
|
income.timeLeft--;
|
|
|
|
if(income.timeLeft <= 0) {
|
|
Engine.log('collection income from ' + source);
|
|
if(source == 'thieves') $SM.addStolen(income.stores);
|
|
$SM.addM('stores', income.stores);
|
|
if(typeof income.delay == 'number') {
|
|
income.timeLeft = income.delay;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Engine._incomeTimeout = setTimeout($SM.collectIncome, 1000);
|
|
},
|
|
|
|
//Thieves
|
|
addStolen: function(stores) {
|
|
for(var k in stores) {
|
|
var old = $SM.get('stores[\''+k+'\']', true);
|
|
var short = old - stores[k];
|
|
//if they would steal more than actually owned
|
|
if(short < 0){
|
|
$SM.add('game.stolen[\''+k+'\']', (stores[k] * -1) + short);
|
|
} else {
|
|
$SM.add('game.stolen[\''+k+'\']', stores[k] * -1);
|
|
}
|
|
};
|
|
},
|
|
|
|
startThieves: function() {
|
|
$SM.set('game.thieves', 1);
|
|
$SM.setIncome('thieves', {
|
|
delay: 10,
|
|
stores: {
|
|
'wood': -10,
|
|
'fur': -5,
|
|
'meat': -5
|
|
}
|
|
});
|
|
},
|
|
|
|
//Misc
|
|
num: function(name, craftable) {
|
|
switch(craftable.type) {
|
|
case 'good':
|
|
case 'tool':
|
|
case 'weapon':
|
|
case 'upgrade':
|
|
return $SM.get('stores[\''+name+'\']', true);
|
|
case 'building':
|
|
return Outside.numBuilding(name);
|
|
}
|
|
},
|
|
|
|
handleStateUpdates: function(e){
|
|
|
|
},
|
|
};
|
|
|
|
//alias
|
|
var $SM = StateManager;
|
|
|
|
//listener for StateManager update events
|
|
$(StateManager).on('stateUpdate', $SM.handleStateUpdates); |