function playSFX(track){
	//Don't play if audio is turned off
	
}

document.body.style.cursor = 'none';

try{
	var gui = require('nw.gui');
}catch (e){
	
}

//global audio muted check
if(gameData.load('audioIsMuted') == 'yes'){
	var audioIsMuted = true;
}else{
	var audioIsMuted = false;
}
var CRTMode = true;
var ScreenTransitionState = false;
var ScreenTransitionStart = false;
var TextFont = '8x8Apple2';
//var TextFont = '8x8PressStartP2';
var TextFontShadowed = '8x8Apple2';
var TextFontGray = '8x8Apple2Gray';
var TextFontRed = '8x8Apple2Red';

/* ---------------------
Gamepad Support
----------------------*/

var GamePadHelperEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		this.isPersistent = true;
		this.updateWhenPaused = true;
		//Gamepad Controls
		this.actionPressed = this.cloakPressed = this.rightPressed = this.leftPressed = false;
		
		//Menu Controls
		this.upPressed = this.downPressed = this.leftPressed = this.rightPressed = this.startPressed = this.selectPressed = this.aPressed = this.bPressed = false;
		
		this.gamepadSupportAvailable = !!navigator.webkitGetGamepads || !!navigator.webkitGamepads;
		
		//
		console.log('GamePad Support Available? ' + this.gamepadSupportAvailable);
		
		this.lastKeyPressed;
		
		this.usingGamePad = false;
		
	},
	update: function(){
		//Chrome
		if(this.gamepadSupportAvailable){			
			//var gamepad = navigator.webkitGetGamepads()[0];
			
			if(navigator.webkitGetGamepads()[0] !== undefined){
				var gamepad = navigator.webkitGetGamepads()[0];
			}else if(navigator.webkitGetGamepads()[1] !== undefined){
				var gamepad = navigator.webkitGetGamepads()[1];
			}	
			
			if(gamepad !== undefined) {
				if(!this.usingGamePad){
					this.usingGamePad = true;
					me.gamestat.setValue("usingGamePad", 'yes');
				}
				//console.log('GamePad Connected');
				//console.log(gamepad);
				//Button Down
				
				//Button Up 
				
				var buttons = gamepad.buttons;
				var axes = gamepad.axes;

				//Test
				if(buttons){
					//WINDOWS BINDINGS
					//TEST SEPARATELY ON MAC AND LINUX
					
					//this.startPressed = false; 
					//this.actionPressed = false; 
					
					/*
						Need to somehow manually track button up/down
						if on a new screen, we don't want an action to happen if the button was being held down from the previous screen
						
					*/
					
					//if setForGameplay
					if(InputControls.mode == 'game'){
					
						if( (buttons[0] || buttons[3])){ //X
							if(this.actionWasPressed){
								me.input.triggerKeyEvent(me.input.KEY.SPACE, false); //Start/Jump/Action
							}else{
								//console.log('x!');
								me.input.triggerKeyEvent(me.input.KEY.SPACE, true); //Start/Jump/Action
								this.actionPressed = true; 
								this.actionWasPressed = true; 
							}
						}else if(this.actionWasPressed){
							this.actionWasPressed = false;
							
						}
						
						if(buttons[1] || buttons[2] ){ //O
							this.cloakPressed = true;
							me.input.triggerKeyEvent(me.input.KEY.S, true); //Cloak
						}else if(this.cloakPressed){
							this.cloakPressed = false;
							me.input.triggerKeyEvent(me.input.KEY.S, false); //Cloak
						}
						
						if( buttons[1] || buttons[2] ){ //B OR X
							if(this.bPressed){
								me.input.triggerKeyEvent(me.input.KEY.S, false); //Cloak
							}else{
								me.input.triggerKeyEvent(me.input.KEY.S, true); //Cloak
								this.bPressed = true;  
							}
						}else if(this.bPressed){
							this.bPressed = false;
						}
						
						
						if(buttons[15] || axes[0] > .25){ //right
							this.rightPressed = true;
							me.input.triggerKeyEvent(me.input.KEY.D, true); //Move Right
						}else if(this.rightPressed){
							this.rightPressed = false;
							me.input.triggerKeyEvent(me.input.KEY.D, false); //Move Right
						}
						
						if(buttons[14] || axes[0] < -.25){ //left
							this.leftPressed = true;
							me.input.triggerKeyEvent(me.input.KEY.A, true); //Move Left
						}else if(this.leftPressed){
							this.leftPressed = false;
							me.input.triggerKeyEvent(me.input.KEY.A, false); //Move Left
						}
						
						/*
						if( buttons[9] ){ // START (PAUSE)
							me.input.triggerKeyEvent(me.input.KEY.ESC, true); 
							this.startPressed = true; 
							console.log('start!');
						}else if(this.startPressed){
							this.startPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.ESC, false); 
						}
						*/
						
						if( buttons[9] ){ // START (PAUSE)
							if(this.startPressed){
								me.input.triggerKeyEvent(me.input.KEY.ESC, false); 
							}else{
								//console.log('x!');
								me.input.triggerKeyEvent(me.input.KEY.ESC, true); 
								this.startPressed = true; 
							}
						}else if(this.startPressed){
							this.startPressed = false;
						}
					
					}else if(InputControls.mode == 'menu'){
						//left		14
						//right		15
						//up		12
						//down		13
						//start		9
						//select	8
						//a/y		0/3
						//x/b		1/2
						//console.log('menu!');
						/*
						if( buttons[0]){ //A OR START
							me.input.triggerKeyEvent(me.input.KEY.ENTER, true); 
							this.actionPressed = true; 
							
						}else if(this.actionPressed){
							this.actionPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.ENTER, false); 
						} */
						
						if( buttons[0]){ //X or Start
							if(this.actionWasPressed){
								me.input.triggerKeyEvent(me.input.KEY.ENTER, false); //Start/Jump/Action
							}else{
								//console.log('x!');
								me.input.triggerKeyEvent(me.input.KEY.ENTER, true); //Start/Jump/Action
								this.actionPressed = true; 
								this.actionWasPressed = true; 
							}
						}else if(this.actionWasPressed){
							this.actionWasPressed = false;
							
						}
						
						/*
						if( buttons[1] || buttons[8] ){ //B OR SELECT
							me.input.triggerKeyEvent(me.input.KEY.ESC, true); 
							this.bPressed = true; 
						}else if(this.bPressed){
							this.bPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.ESC, false); 
						}
						*/
						
						if( buttons[1] || buttons[8] ){ //B OR SELECT
							if(this.bPressed){
								me.input.triggerKeyEvent(me.input.KEY.ESC, false); 
							}else{
								me.input.triggerKeyEvent(me.input.KEY.ESC, true); 
								this.bPressed = true;  
							}
						}else if(this.bPressed){
							this.bPressed = false;
						}
						
						
						if( buttons[14] || axes[0] < -.25){ //LEFT
							me.input.triggerKeyEvent(me.input.KEY.LEFT, true); 
							this.leftPressed = true; 
						}else if(this.leftPressed){
							this.leftPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.LEFT, false); 
						}
						
						if( buttons[15] || axes[0] > .25){ //RIGHT
							me.input.triggerKeyEvent(me.input.KEY.RIGHT, true); 
							this.rightPressed = true; 
						}else if(this.rightPressed){
							this.rightPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.RIGHT, false); 
						}
						
						if( buttons[12] || axes[1] < -.25){ //UP
							me.input.triggerKeyEvent(me.input.KEY.UP, true); 
							this.upPressed = true; 
							//console.log('up!');
						}else if(this.upPressed){
							this.upPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.UP, false); 
						}
						
						if( buttons[13] || axes[1] > .25){ //DOWN
							me.input.triggerKeyEvent(me.input.KEY.DOWN, true);
							this.downPressed = true; 
							//console.log('dwon!');
						}else if(this.downPressed){
							this.downPressed = false; 
							me.input.triggerKeyEvent(me.input.KEY.DOWN, false);
						}
						
						//*
						if( buttons[9] ){ // START (PAUSE)
							if(this.startPressed){
								me.input.triggerKeyEvent(me.input.KEY.ESC, false); 
							}else{
								//console.log('x!');
								me.input.triggerKeyEvent(me.input.KEY.ESC, true); 
								this.startPressed = true; 
							}
						}else if(this.startPressed){
							this.startPressed = false;
						} //*/
						
					}
					//if setForMenu
					
					
					//4 - LB
					//5 - RB
					//9 - Start
					//12 - Up
					//13 - Down
					
					//14 right & 13 left on mac
					//15 right & 14 left on win
					
				}
			
			}else{
				//console.log('GamePad Not Connected');
			}
		}
		this.parent(this);
		return true;
	}
});


/* ---------------------
Check Point
----------------------*/
var CheckPointEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 16;
		this.parent(x,y,settings);
		this.gravity = (0);
		this.collision = false;
		this.alwaysUpdate = true;
		this.cpid = settings.cpid;
		//Check to see if we're in Novice mode or not. Also check to see if we're in time trial/level select
		//if(me.gamestat.getItemValue('currentMode') != 'novice'){
		if(gameData.load('currentMode') != 'novice' && gameData.load('currentMode') != 'trueNovice'){
			if(me.gamestat.getItemValue('currentMode') == 'timeAttack' && gameData.load('levelSelectCPDisabled') != 'yes') {
				//Uh...what...
			}else{
				this.renderable.alpha = 0;
			}
			
		}
		//if we are, remove this
		
		this.renderable.addAnimation('dossier', [0,1,2,3]);
		this.renderable.addAnimation('door', [4,4,4,4,4,4,5,6,7],3);
		
		this.checkpointDataLoad = me.gamestat.getItemValue('checkpointData');
		this.checkpointActivated = me.gamestat.getItemValue('checkpointActivated');
		this.checkpointCurrent = me.gamestat.getItemValue('checkpointCurrent');
		
		this.activated = false;
		
		//console.log(this.checkpointActivated);
		//console.log(this.checkpointCurrent);
		
		if(this.checkpointActivated != ''){
						
			var checkpointActivatedR = this.checkpointActivated.split(',');
			//Do an initial check to see if this is the most recent checkpoint
			for(i = 0; i < checkpointActivatedR.length; i++){
				if(checkpointActivatedR[i] == this.cpid){
					this.activated = true;
				}
			}
		}
		
		if(this.activated && this.cpid != this.checkpointCurrent){
			me.game.remove(this);
			this.renderable.setCurrentAnimation('dossier');
		}else if(this.activated && this.cpid == this.checkpointCurrent){
			this.renderable.setCurrentAnimation('door',(function () {
					me.game.remove(this);
				}).bind(this));
		}else{
			this.renderable.setCurrentAnimation('dossier');
		}
				
		
		this.loadCheck = true;
	},
	update: function(){
		if(this.loadCheck){
			if(me.gamestat.getItemValue('currentMode') != 'novice'  && gameData.load('currentMode') != 'trueNovice'){
			//if(gameData.load('currentMode') != 'novice' ){ // Use for direct level testing
				if(me.gamestat.getItemValue('currentMode') == 'timeAttack' && gameData.load('levelSelectCPDisabled') != 'yes') {
					//Uh...what...
				}else{
					me.game.remove(this);
				}
			}
			
			if(this.checkpointCurrent == this.cpid){
				
				//console.log('current checkpoint: ' + this.checkpointCurrent + ' this checkpoint: ' + this.cpid);
				
				if(this.checkpointDataLoad != ''){
					console.log(this.checkpointDataLoad);
					var checkpointDataR1 = this.checkpointDataLoad.split(',');
					
					//remove any dupes - might be better to do this when grabbing a key? check a flag? this works for now though.
					var checkpointDataR = checkpointDataR1.filter(function(elem, pos) {
						return checkpointDataR1.indexOf(elem) == pos;
					  }); 
						
					for(i = 0; i < checkpointDataR.length; i++){
						console.log(checkpointDataR[i]);
						if(checkpointDataR[i] != 0 && checkpointDataR[i] != ''){
							//console.log('Checkpoint Found');
							var cpitem = me.game.getEntityByProp('cpid',checkpointDataR[i]);
							//console.log('checkpoint data: ' + checkpointDataR[i]);
							cpitem[0].checkpointClear();
							
						}					
					}
				}			
				
				this.loadCheck = false;
			
			}else if(this.activated && this.cpid != this.checkpointCurrent){
				me.game.remove(this);
			}
			
			
			//Check data to see if this checkpoint is in the list and if it's the newest
			//if newest, update Spy's position to this x,y
				//Activate all keycards in list
				//Activate all hackable computers/doors in list
			//if in list, remove
			//this.checkpointDataLoad = me.gamestat.getItemValue('checkpointData');
			/*
			if(this.checkpointDataLoad != ''){
				//console.log(checkpointDataLoad);
				var checkpointDataR = this.checkpointDataLoad.split(',');
					
				for(i = 0; i < checkpointDataR.length; i++){
					//console.log(checkpointDataR[i]);
					if(checkpointDataR[i] == this.cpid){
						//console.log('Checkpoint Found');
						spy.pos.x = this.pos.x;
						spy.pos.y = this.pos.y;
						me.game.remove(this);
					}
				}
			} */
			
			if(this.activated){
				//spy.pos.x = this.pos.x;
				//spy.pos.y = this.pos.y;
				//me.game.remove(this);
			}
			this.loadCheck = false;
		}
		
		//check for collision with spy
		//var res = me.game.collide(this);
		//if(res && res.obj.type == me.game.SPY && spy.alive && !this.activated){
		if(spy.alive && !this.activated && this.colOverlaps(spy.collisionBox)){
			//console.log('checkpoints');
			//console.log(me.gamestat.getItemValue('checkpointData'));
			//console.log(me.gamestat.getItemValue('checkpointDataTemp'));
			
			var checkpointData = me.gamestat.getItemValue('checkpointData') + ',' + me.gamestat.getItemValue('checkpointDataTemp');
			//var checkpointData = me.gamestat.getItemValue('checkpointData');
			//checkpointData.concat(me.gamestat.getItemValue('checkpointDataTemp').toString());
			me.gamestat.setValue('checkpointData',checkpointData);
			
			//console.log('Checkpoint set ' +  checkpointData );
			
			spy.getKey();
			
			//Collided, update checkpointData with Check Point's Name  
			var checkpointActivated = me.gamestat.getItemValue('checkpointActivated') + ',' + this.cpid;
			me.gamestat.setValue('checkpointActivated',checkpointActivated);
			me.gamestat.setValue('checkpointCurrent',this.cpid);
			this.activated = true;
			me.audio.play('dossier');
			//console.log('Checkpoint set ' +  me.gamestat.getItemValue('checkpointData') );
			me.game.remove(this);
			
		}
		
		this.parent(this);
		return true;
	}
});

/* ---------------------
a spy entity
----------------------*/

var SpyEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spriteheight = 32;
		if(settings.image == 'vr_spy'){
			this.vr = true;
		}else{
			this.vr = false;

			if(me.gamestat.getItemValue('currentMode') == 'ghost'){
				settings.image = 'spy_ghost';
			}
		}
		
		
		//checkpoint code
		//if(me.gamestat.getItemValue('currentMode') == 'novice'){
		if(gameData.load('currentMode') == 'novice' || gameData.load('currentMode') == 'trueNovice' || (me.gamestat.getItemValue('currentMode') == 'timeAttack' && gameData.load('levelSelectCPDisabled') != 'yes') ){
			if(me.gamestat.getItemValue('checkpointCurrent') != ''){
				if(me.gamestat.getItemValue('checkpointCurrent') == 'galehdoor1'){
					x = 128;
					y = 256;		
				}else{
					var checkPoint = me.game.getEntityByProp('cpid',me.gamestat.getItemValue('checkpointCurrent'));
						x = checkPoint[0].pos.x;
						y = checkPoint[0].pos.y;
				}
			}
		}else if(me.gamestat.getItemValue('checkpointCurrent') != ''){ 
				if(me.gamestat.getItemValue('checkpointCurrent') == 'galehdoor1'){ //We still need this to work.
					x = 128;
					y = 256;		
				}
		}
		
		this.parent(x,y,settings);
		this.type = me.game.SPY;
		this.alwaysUpdate = true;
		//Let's reduce gravity a bit		
		this.setVelocity(1.5,7.5);
		this.setMaxVelocity(1.5,7.5);
		this.initialGravity = this.gravity = (0.41);
		this.initialGravity = this.initialGravity / 2;
		this.cloakedVelx = (this.maxVel.x * .5);
		this.cloakedVely = (this.maxVel.y * .5);
		this.cloakedAccel = this.cloakedVel;
		this.collidable = true;
		if(me.gamestat.getItemValue('stealthState') === 1){
			this.stealthOn = true;
			this.stealthOn = false;
		}else{
			this.stealthOn = false;
		}
		this.hasKey = false;
		this.wasFalling = false;
		this.alive = true;
		this.isCaught = false;
		this.moving = false;
		this.toggledCloak = false;
		this.onPlatform = false;
		//this.caught = false;
		this.updateColRect(6,12,8,24);
		this.flipX(true);
		this.gotKey = false;
		this.flipJumpCol = false;
		this.stopX = false;
		this.stopXBarrier = false;
		this.hacking = false;
		this.wasHacking = false;
		this.caughtMode = '';
		this.jumping = false;
		this.dJumping = false;
		//add animations
		//jump - 5
		//land - 6
		//cloaking - 7 8 9
		//cloak walk 11 12
		//cloak stand 10
		//c jump 13
		//c land 14
		//caught 15
		//c caught 16
		
		//add animations
		//stand 0
		//walk - 1,2,3,4
		//jump - 5,6
		//flip - 7,8,9
		//fall - 10,11
		//land - 12
		//cloaking - 13,14,15
		//cloaking walking - 13,15
		//uncloaking - 15,14,13
		//jump cloak - 16
		//jump uncloak - 16
		//uncloaking walking - 15,13
		//Cloak stand 27,28,29,30,31,32,33,34
		//cloak walk 35,36,37,38
		//c jump 39,40
		//c fall 41,42
		//caught 15
		//c caught 16
		//exit 18,19
		//exit cloaked 20,21
		
		this.renderable.addAnimation('stand', [0]);
		this.renderable.addAnimation('walk', [1,2,3,4]);
		this.renderable.addAnimation('jump', [5,6]);
		this.renderable.addAnimation('fall', [10,11]);
		this.renderable.addAnimation('land', [12],12);
		this.renderable.addAnimation('caught', [22]);
		this.renderable.addAnimation('keyGet', [17],12);
		this.renderable.addAnimation('cloaking', [13,14,15]);
		this.renderable.addAnimation('walkingCloak', [13,15]);
		this.renderable.addAnimation('jumpingCloak', [16]);
		this.renderable.addAnimation('uncloaking', [15,14,13]);
		this.renderable.addAnimation('walkingUncloak', [15,13]);
		this.renderable.addAnimation('cloakWalk', [34,35,36,37]);
		this.renderable.addAnimation('cloakStand', [26,27,28,29,30,31,32,33]);
		this.renderable.addAnimation('cloakJump', [38,39]);
		this.renderable.addAnimation('cloakFall', [40,41]);
		this.renderable.addAnimation('cloakLand', [42],12);
		this.renderable.addAnimation('cloakCaught', [23]);
		this.renderable.addAnimation('cloakKeyGet', [43],12);
		
		
		this.renderable.addAnimation('hack', [44,45],6);
		this.renderable.addAnimation('cloakHack', [46,47],6);
		
		
		this.renderable.addAnimation('cloakExitDoor', [20,21]);
		this.renderable.addAnimation('exitDoor', [18,19]);
		
		this.renderable.addAnimation('cloakEnterDoor', [21,20]);
		this.renderable.addAnimation('enterDoor', [19,18]);
		
		this.renderable.addAnimation('flip', [7,8,9],3);
		
		this.tranCounter = 0;
		
		//1 = Right, 0 = Left
		this.currentDirection = true;
		//this.renderable.setCurrentAnimation('stand');
		//Enter the level
		this.transitioning = true;
		if(this.stealthOn){
			this.renderable.setCurrentAnimation('cloakExitDoor','cloakStand');
		}else{
			this.renderable.setCurrentAnimation('exitDoor','stand');
		}
		
		
		//bad code here
		
		controlHandler = new ControlHandlerEntity(0,0);
		me.game.add(controlHandler,this.z);
		
		camera = new CameraEntity(0,0);
		var camera = me.entityPool.newInstanceOf("camera",0, 0);
		me.game.add(camera,this.z);
		
		//check for current game mode
		//Darkness Mode
		if(me.gamestat.getItemValue('currentMode') == 'darkness'){
			//darkmode = new DarkModeEntity(0, 0, {image:'darkmode', spritewidth:680});
			var darkmode = me.entityPool.newInstanceOf("darkmode",0, 0, {image:'darkmode', spritewidth:680});
			me.game.add(darkmode,30);
			//me.game.sort();	
		}
		
		spy = this;		
		
		//me.game.viewport.fadeIn('#000000',1,function(){ me.game.viewport.fadeOut('#000000',300); });
		//me.game.viewport.fadeOut('#000000',300);
		//Transition
		//leveltransition = new LevelTransitionEntity(this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'in' });
		var leveltransition = me.entityPool.newInstanceOf("leveltransition",this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'in' });
		me.game.add(leveltransition,60);
		//me.game.sort();	
		
		//console.log('Spy Start X: ' + this.pos.x);
		
		//REMOVE ALL THIS STUFF BEFORE RELEASING
		/*
		this.now = this.last = Date.now();
			// reset delta counting variables
			this.framedelta = 0;
			this.framecount = 0;
			htmlCounter = document.getElementById("framecounter");
		//*/
	},
	update: function(){
	
		//REMOVE ALL THIS STUFF BEFORE RELEASING
		/*
		this.last = this.now;
		this.now = Date.now();

		this.delta = (this.now - this.last);

		// only draw the FPS on in the HTML page 
		
			this.framecount++;
			this.framedelta += this.delta;
			if (this.framecount % 10 == 0) {
				//this.fps = (~~((1000 * this.framecount) / this.framedelta)).clamp(0, me.sys.fps);
				this.fps = (~~((1000 * this.framecount) / this.framedelta));
				this.framedelta = 0;
				this.framecount = 0;
			}
			// set the element in the HTML
			if (htmlCounter !== null) {
				htmlCounter.replaceChild(document.createTextNode("(" + this.fps + "/"
					+ me.sys.fps + " fps)"), htmlCounter.firstChild);
			}
		
		//*/
		//
		
		
		if(this.exiting){
			//When Spy hits the door, he should stop momentum and slide in
			//check for: spy below door (coming up through platform)
			//spy above door/spy jumping
			//test with guards and stuff
			
			//position the spy
			if(this.currentDirection && this.pos.x < this.doorX - 4){
				this.pos.x += 1.5;
				//console.log(this.pos.x + ' ' + this.doorX);
			
			}else if(!this.currentDirection && this.pos.x > this.doorX - 4){
				this.pos.x -= 1.5;
			
			}else{
				if(this.stealthOn){
					this.renderable.setCurrentAnimation('cloakEnterDoor', function(){ this.renderable.alpha = 0; }.bind(this));
				}else{
					this.renderable.setCurrentAnimation('enterDoor', function(){ this.renderable.alpha = 0; }.bind(this));
				}
			
			}
			this.parent(this);
			return true;
		}
		
		//If caught, we want to finish any previous movements  from jumping/falling
		if(!this.alive){			
			//Update Movement
			if(this.falling || this.jumping){
				this.updateMovement();
			}
			if(this.dJumping){
				this.updateColRect(6,12,8,24);
				this.dJumping = false;
			}
			//Don't update Animation
			return false;			
		}
		
		//When Entering Level, let's take away control briefly to play entrance animation
		if(this.transitioning){
			//this.tranCounter += me.timer.tick;
			this.tranCounter += 1;
			if(this.tranCounter < 30){	//Half Second Pause
				this.parent(this);
				return true;
				//console.log(this.tranCounter);
			}else{
				this.tranCounter = 0;				
				this.transitioning = false;
			}
		}
		
			
		//Player Controls
				
		//Flash
		if(me.input.isKeyPressed('flash')){
			this.renderable.setCurrentAnimation('cloaking');
			this.moving = true;
		}
		
		//Toggle Invisibility
		if(me.input.isKeyPressed('stealth')) this.toggleCloak();
		
		//Movement
		if(me.input.isKeyPressed('left')){
			//me.gamestat.updateValue("stepCountTemp", me.timer.tick);
			this.moving = true;
			this.currentDirection = false;
			//Will have to check for jumping later on
			if(this.stealthOn){
				if(!this.jumping){					
					if(this.toggledCloak){
						this.renderable.setCurrentAnimation('walkingCloak','cloakWalk');
					}else if(!this.renderable.isCurrentAnimation('cloakWalk') && !this.renderable.isCurrentAnimation('walkingCloak')){
						this.renderable.setCurrentAnimation('cloakWalk');
					}
				}
			
				this.vel.x = -this.cloakedVelx * me.timer.tick;
			}else{
				if(!this.jumping){
					if(this.maxVel.x != 1.5){
						this.setMaxVelocity(1.5,7.5);
					}
					
					if(this.toggledCloak){
						this.renderable.setCurrentAnimation('walkingUncloak','walk');
					}else if(!this.renderable.isCurrentAnimation('walk') && !this.renderable.isCurrentAnimation('walkingUncloak')){
						this.renderable.setCurrentAnimation('walk');
					}
					
					this.vel.x -= this.accel.x * me.timer.tick;
				}else{
					if(this.maxVel.x != 2.25){
						this.setMaxVelocity(2.25,7.5);
					}
					this.vel.x -= this.accel.x * me.timer.tick;
					
					if(this.dJumping){
						this.vel.y = this.gravity * -1;
					}
				}		
			}	
		}else if(me.input.isKeyPressed('right')){
			//me.gamestat.updateValue("stepCountTemp", me.timer.tick);
			this.moving = true;
			this.currentDirection = true;
			if(this.stealthOn){
				if(this.toggledCloak){
					this.renderable.setCurrentAnimation('walkingCloak','cloakWalk');
				}else if(!this.renderable.isCurrentAnimation('cloakWalk') && !this.renderable.isCurrentAnimation('walkingCloak')){
					this.renderable.setCurrentAnimation('cloakWalk');
				}
			
				if(this.jumping){
					this.vel.x = this.cloakedVelx * me.timer.tick;
				}else{
					this.vel.x = this.cloakedVelx * me.timer.tick;
				}
			}else{
				if(!this.jumping){
					if(this.maxVel.x != 1.5){
						this.setMaxVelocity(1.5,7.5);
					}
					
					if(this.toggledCloak){
						this.renderable.setCurrentAnimation('walkingUncloak','walk');
					}else if(!this.renderable.isCurrentAnimation('walk') && !this.renderable.isCurrentAnimation('walkingUncloak')){
						this.renderable.setCurrentAnimation('walk');
					}
					this.vel.x += this.accel.x * me.timer.tick;	
				}else{
					if(this.maxVel.x != 2.25){
						this.setMaxVelocity(2.25,7.5);
					}
					this.vel.x += this.accel.x * me.timer.tick;	
					
					if(this.dJumping){
						this.vel.y = this.gravity * -1;
					}
				}					
			}			
		}else{			
			this.moving = false;
			this.vel.x = 0;	

			//Can I optimize this?
			/*
			if(!this.renderable.isCurrentAnimation('cloaking') && !this.renderable.isCurrentAnimation('uncloaking') && !this.renderable.isCurrentAnimation('cloakLand') && !this.renderable.isCurrentAnimation('land') && !this.renderable.isCurrentAnimation('walkingUncloak') && !this.renderable.isCurrentAnimation('walkingCloak')  && !this.renderable.isCurrentAnimation('jump')  && !this.renderable.isCurrentAnimation('cloakJump') && !this.renderable.isCurrentAnimation('cloakFall') && !this.renderable.isCurrentAnimation('fall') && !this.renderable.isCurrentAnimation('flip')){
				if(this.stealthOn){
					this.renderable.setCurrentAnimation('cloakStand');
				}else{
					this.renderable.setCurrentAnimation('stand');
				}	
			}			
			*/
			//only check cloakWalk, walk? Wow, that's much simpler.
			if(this.renderable.isCurrentAnimation('cloakWalk') || this.renderable.isCurrentAnimation('walk')){
				if(this.stealthOn){
					this.renderable.setCurrentAnimation('cloakStand');
				}else{
					this.renderable.setCurrentAnimation('stand');
				}	
			}
		}
		
		//jump
		if(me.input.isKeyPressed('jump')){
			if(!this.jumping && !this.falling){
				//me.gamestat.updateValue("jumpCountTemp", 1);
				//set current vel to the maximum defined value
				//gravity will then do all the rest
				this.vel.y = -this.maxVel.y * me.timer.tick;
				//set the jumping flag
				this.jumping = true;
				this.wasJumping = true;
				this.moving = true;
				//adudio
				me.audio.play("jump");
				this.jumpDust();
			
				if(this.stealthOn){				
					this.renderable.setCurrentAnimation('cloakJump');
				}else{
					this.renderable.setCurrentAnimation('jump');
				}
			}else if(this.wasJumping && !this.dJumping && !this.stealthOn){ //Subtle Jump Stop
				this.vel.y = this.gravity * -1;
				this.dJumping = true;
				this.updateColRect(6,12,8,16);
				this.renderable.setCurrentAnimation('flip','fall');
				me.audio.play("jump");
			}
		}
		
		if(this.jumping && this.toggledCloak){
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('jumpingCloak','cloakJump');	
			}else{	
				this.renderable.setCurrentAnimation('jumpingCloak','jump');	
			}
		}
		
		if(this.falling && this.toggledCloak){
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('jumpingCloak','cloakFall');	
			}else{	
				this.renderable.setCurrentAnimation('jumpingCloak','fall');	
			}
		}
		
		
		if(this.renderable.isCurrentAnimation('flip')){
			this.dJumping = true;
		}else{
			if(this.dJumping){
				this.updateColRect(6,12,8,24);
			}
			this.dJumping = false;			
		}		
		//*
		//Set an animation if landing or falling
		if(this.wasFalling && !this.falling && !this.dJumping && !this.wasJumping){
			this.wasFalling = false;
			this.wasJumping = false;
			//this.animationspeed = 100;
			this.jumpDust();
			me.audio.play("land");
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('cloakLand','cloakStand');
			}else{
				this.renderable.setCurrentAnimation('land','stand');
			}
		} else if(this.falling){
			this.wasJumping = false;
			this.moving = true;
			//this.dJumping = false;
			this.wasFalling = true;
			if(this.stealthOn){				
				this.renderable.setCurrentAnimation('cloakFall');
			}else{
				if(!this.renderable.isCurrentAnimation('flip')){
					this.renderable.setCurrentAnimation('fall');
				}
			}
		}
		
		//*/
		if(this.gotKey == true){
			if(!this.renderable.isCurrentAnimation('flip')){
				if(this.stealthOn){
					this.renderable.setCurrentAnimation('cloakKeyGet', function(){ this.gotKey = false; this.renderable.setCurrentAnimation('cloakStand'); }.bind(this));
				}else{
					this.renderable.setCurrentAnimation('keyGet', function(){ this.gotKey = false; this.renderable.setCurrentAnimation('stand'); }.bind(this));
				}
			}else{
				this.gotKey = false;
			}
		}
		
		this.flipX(this.currentDirection);
		
		if(this.stopX){
			this.vel.x = 0;
		}
		
		//Special Collision Cases
		
		// check for collision
		//var res = me.game.collide(this);
		
		//test to see if this is a performance hog
		//*
		
		var colres = this.collide(true)
		if(this.jumping || colres.length == 0){ 
			this.onPlatform = false; 
		}else{			
			for (i = 0; i < colres.length; ++i) {
				res = colres[i];
				//Trap Door
				if (res && res.obj.type == 'TRAPDOOR' && !res.obj.isOpened && (res.y>0)){
					this.falling = false;
					this.vel.y = 0;
					this.pos.y = ~~(res.obj.pos.y - this.height);	
					this.onPlatform = true;
					//console.log('on platform');
				} else{
					if( res.obj.type == 'TRAPDOOR' ){
						//console.log('not on platform ' + res.obj.type);
						this.onPlatform = false;
					}
					//console.log('not on platform ' + res.obj.type);
					//this.onPlatform = false;
				}
			
			}
		}
		
		if(this.boostUp){
			this.boostUp = false;
			this.vel.y -= .4;
		}
		//*/
		//Update Movement
		this.updateMovement();
		
		//console.log(this.pos.y);
		/*
		//Colliding with trap door
		res = this.collide();

		// check if we collide with an enemy :
		if (!this.jumping && res && (res.obj.type == 'TRAPDOOR'))
		{
			if(this.wasFalling && this.falling){
				//console.log('both falling');
				//this.vel.y =  30;	
			}else if(this.wasFalling){
				console.log('was falling');
			}else if (this.falling){
					console.log('falling');
			}
			//this.pos.y = ~~this.pos.y;
			this.pos.y = res.obj.pos.y - this.height; 
			//this.vel.y = (this.falling) ? res.obj.pos.y - this.collisionBox.bottom: 0 ;			
			this.vel.y = 0;
			//console.log(this.vel.y);
			//this.falling = false;			
			//this.onPlatform = true;
			//this.gravity = 0;
			console.log('yes');
		}else{
			console.log('no');
			this.gravity = this.initialGravity;
				this.onPlatform = false;
		}
		
		if(this.onPlatform){
			this.falling = false;
		}
		
		*/
		
		/*
		if (res && (res.obj.type == 'TRAPDOOR') && res.y > 0 && (this.collisionBox.bottom - 1 <= res.obj.pos.y))
		{
			console.log('trap door');
			//this.pos.y = ~~this.pos.y;
			this.pos.y = res.obj.pos.y - this.height; 
			this.vel.y = (this.falling) ? res.obj.pos.y - this.collisionBox.bottom: 0 ;
			
			this.falling = false;
		}
		*/
		
		
		
		//Set some stuff
		this.toggledCloak = false;
		
		if(this.hacking){
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('cloakHack');
			}else{
				this.renderable.setCurrentAnimation('hack');
			}
		}else if(this.wasHacking){
			this.wasHacking = false;
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('cloakStand');
			}else{
				this.renderable.setCurrentAnimation('stand');
			}
		}
		
		//Update Animation
		this.parent(this);
		return true;
		
	},
	toggleCloak: function(){
		this.toggledCloak = true;
		//me.gamestat.updateValue("steathCountTemp", 1);
		if(this.stealthOn){ //Turn Stealth Off
			//Will have to check for jumping & moving later on
			this.renderable.setCurrentAnimation('uncloaking','stand');
			this.stealthOn = false;
			me.audio.play('uncloak');
		}else{ //Turn it on
			//this.renderable.setCurrentAnimation('cloaking');
			this.renderable.setCurrentAnimation('cloaking','cloakStand');
			this.stealthOn = true;				
			me.audio.play('cloak');			
		}	
	},
	caught: function(){
		if(me.gamestat.getItemValue('currentMode') != 'ghost'){
		me.gamestat.setValue('checkpointDataTemp','');
		if(this.vr){
			this.caughtVR();
		}else{
			if(this.djump){
				this.updateColRect(6,12,8,24);
			}
			//Reset the current level
			if(this.stealthOn){
				this.renderable.setCurrentAnimation('cloakCaught');
			}else{
				this.renderable.setCurrentAnimation('caught');
			}
			this.caughtMode = 'normal';
			this.alive = false;
			this.isCaught = true;
			me.audio.play('caught');

			me.gamestat.updateValue("timesCaught", 1);			
			if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
				me.gamestat.updateValue("currentTimeAttackLevelCaught", 1);	
			}else{
				this.saveCurrentLevelStats();
			}			
			
			me.gamestat.setValue("stealthState", 0);
			
			//pause, give option "PRESS R TO RESTART"	
			me.game.add(new YouLostMSGEntity(me.game.viewport.pos.x,me.game.viewport.pos.y),this.z);
			me.game.sort();
			//me.levelDirector.reloadLevel();
		}
		}        
	},
	caughtKnockedDown: function(direction){
		if(me.gamestat.getItemValue('currentMode') != 'ghost'){
		me.gamestat.setValue('checkpointDataTemp','');
		if(this.vr){
			this.caughtVR();
		}else{
			//Reset the current level
			if(this.stealthOn){
				var cloaked = 'Cloaked';
			}else{
				var cloaked = '';
			}
			
			if(direction == 'left'){
				var flipX = true;
			}else{
				var flipX = false;
			}
			
			if(gameData.load('screenshakeDisabled') != 'yes'){
				me.game.viewport.shake(10,100, me.game.viewport.AXIS.BOTH);
			}
			
					
			
			//var spycaught = new SpyCaughtEntity(this.pos.x-8, this.pos.y, {image:'spycaught', spritewidth:32, spriteheight: 32, cloaked: cloaked, flipX: flipX});
			var spycaught = me.entityPool.newInstanceOf("spycaught",this.pos.x-8, this.pos.y, {image:'spycaught', spritewidth:32, spriteheight: 32, cloaked: cloaked, flipX: flipX});
				me.game.add(spycaught,this.z);
				//me.game.sort();
			
			this.renderable.setOpacity(0);
				
			this.alive = false;
			this.isCaught = true;
			this.caughtMode = 'knockedDown';
			me.audio.play('caught');

			me.gamestat.updateValue("timesCaught", 1);
			if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
				me.gamestat.updateValue("currentTimeAttackLevelCaught", 1);	
			}else{
				this.saveCurrentLevelStats();
			}
			me.gamestat.setValue("stealthState", 0);
			
			//pause, give option "PRESS R TO RESTART"	
			me.game.add(new YouLostMSGEntity(me.game.viewport.pos.x,me.game.viewport.pos.y),this.z);
			me.game.sort();
			//me.levelDirector.reloadLevel();
		}
		}
	},
	caughtBeam: function(direction,type){
		if(me.gamestat.getItemValue('currentMode') != 'ghost'){
		me.gamestat.setValue('checkpointDataTemp','');
		if(this.vr){
			this.caughtVR();
		}else{
			//Reset the current level
			if(this.stealthOn){
				var cloaked = 'Cloaked';
			}else{
				var cloaked = '';
			}
			
			if(direction == 'left'){
				var flipX = true;
			}else{
				var flipX = false;
			}
			
			if(type == 'shocked'){
				var spriteImage = 'spyshocked';
			}else if(type == 'burning'){
				var spriteImage = 'spyburning';
			}else{
				var spriteImage = 'spybeamed';
			}
			
			
			if(gameData.load('screenshakeDisabled') != 'yes'){
				me.game.viewport.shake(10,100, me.game.viewport.AXIS.BOTH);
			}		
					
			//var spycaught = new SpyBeamedEntity(this.pos.x, this.pos.y, {image:spriteImage, spritewidth:24, spriteheight: 32, cloaked: cloaked, flipX: flipX});
			var spycaught = me.entityPool.newInstanceOf("spybeamed",this.pos.x, this.pos.y, {image:spriteImage, spritewidth:24, spriteheight: 32, cloaked: cloaked, flipX: flipX});
				me.game.add(spycaught,this.z);
				//me.game.sort();
			
			this.renderable.setOpacity(0);
				
			this.alive = false;
			this.isCaught = true;
			this.caughtMode = 'knockedDown';
			me.audio.play('caught');

			me.gamestat.updateValue("timesCaught", 1);
			if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
				me.gamestat.updateValue("currentTimeAttackLevelCaught", 1);	
			}else{
				this.saveCurrentLevelStats();
			}
			me.gamestat.setValue("stealthState", 0);
			
			//pause, give option "PRESS R TO RESTART"	
			me.game.add(new YouLostMSGEntity(me.game.viewport.pos.x,me.game.viewport.pos.y),this.z);
			me.game.sort();
			//me.levelDirector.reloadLevel();
		}
		}
	},
	caughtVR: function(){
		if(me.gamestat.getItemValue('currentMode') != 'ghost'){
		//Reset the current level
			
		
		
		if(gameData.load('screenshakeDisabled') != 'yes'){
			me.game.viewport.shake(10,100, me.game.viewport.AXIS.BOTH);
		}
				
		
		//var spycaught = new SpyVRDeathEntity(this.pos.x-8, this.pos.y, {image:'vr_spydeath', spritewidth:24, spriteheight: 32});
		var spycaught = me.entityPool.newInstanceOf("spyvrdeath",this.pos.x-8, this.pos.y, {image:'vr_spydeath', spritewidth:24, spriteheight: 32});
			me.game.add(spycaught,this.z);
			//me.game.sort();
		
		this.renderable.setOpacity(0);
			
		this.alive = false;
		this.isCaught = true;
		this.caughtMode = 'knockedDown';
		me.audio.play('caught');

		//me.gamestat.updateValue("timesCaught", 1);
		//me.gamestat.setValue("stealthState", 0);
		
		if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
				me.gamestat.updateValue("currentTimeAttackLevelCaught", 1);	
				me.game.add(new YouLostMSGEntity(me.game.viewport.pos.x,me.game.viewport.pos.y),this.z);
				me.game.sort();
		}
		//pause, give option "PRESS R TO RESTART"	
		//me.game.add(new YouLostMSGEntity(me.game.viewport.pos.x,me.game.viewport.pos.y),this.z);
		//me.game.sort();
		//me.levelDirector.reloadLevel();
		}
	},
	jumpDust: function(){
		if(!this.vr){
		//jumpdust = new JumpDustEntity(this.pos.x + 4, this.pos.y + 24, {image:'jumpdust', spritewidth:16, spriteheight: 8 });
		var jumpdust = me.entityPool.newInstanceOf("jumpdust", this.pos.x + 4, this.pos.y + 24, {image:'jumpdust', spritewidth:16, spriteheight: 8 });
			me.game.add(jumpdust,this.z + 1);
			//me.game.sort();
		}
	},
	exitLevel: function(doorX){
		//make the spy
		this.doorX = doorX;
		this.exiting = true;
		this.alive = false;
	},
	getKey: function(){
		this.gotKey = true;
	},
	saveCurrentLevelStats:function(){
		me.gamestat.updateValue('current_level_caught',1);
		me.gamestat.updateValue('current_mission_caught',1);
		me.gamestat.updateValue('current_game_caught',1);
		
		gameData.save('current_mission_time',me.gamestat.getItemValue('current_mission_time'));
		gameData.save('current_mission_caught',me.gamestat.getItemValue('current_mission_caught'));
		
		gameData.save('current_level_time',me.gamestat.getItemValue('current_level_time'));
		gameData.save('current_level_caught',me.gamestat.getItemValue('current_level_caught'));
		
		gameData.save('current_game_time',me.gamestat.getItemValue('current_game_time'));
		gameData.save('current_game_caught',me.gamestat.getItemValue('current_game_caught'));
	}
});


/* ---------------------
a spy caught entity
----------------------*/

var SpyCaughtEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);	
		this.collidable = true;
		this.gravity = (0.41);
		this.setVelocity(2,2);
		//this.setMaxVelocity(4,2);
		
		this.updateColRect(16, 8, 16, 16);
		
		
		//console.log(this.collisionBox);

		if(settings.image == 'spycaughtbeamed'){
			this.beamed = true;
			this.renderable.addAnimation('knockedDown', [0,3]);
			this.renderable.addAnimation('knockedDownFall', [1,2]);
			this.renderable.addAnimation('knockedDown2', [3]);			

		}else if(settings.image == 'spycaughtburning' ){
			this.beamed = true;
			this.renderable.addAnimation('knockedDown', [0,3]);
			this.renderable.addAnimation('knockedDownFall', [1,2]);
			this.renderable.addAnimation('knockedDown2', [3]);			

		}else{
			this.beamed = false;
			this.renderable.addAnimation('knockedDown', [0]);
			this.renderable.addAnimation('knockedDownFall', [1]);
			this.renderable.addAnimation('knockedDownFallCloaked', [3]);
			this.renderable.addAnimation('knockedDownCloaked', [2]);
		}
		
		this.flippedX = settings.flipX;
		this.flipX(this.flippedX);
		this.cloaked = settings.cloaked;
		//Will check for more conditions probably
		this.renderable.setCurrentAnimation("knockedDown"+this.cloaked);
		
		//TODO: make spy bounce off the ground a little
		this.startPosX = x;
		this.bouncePosX = x + 16;
		this.bounce1 = true;
		this.bounce2 = true;
		this.xDistance = 0;
		this.xDistanceLimit1 = 48;
		
		spyCaught = this;
	},
	update: function(){
		
		if(this.falling){
			this.bouncing = false;
			//TODO: falling animation
			this.renderable.setCurrentAnimation("knockedDownFall"+this.cloaked);
		}
		
		if(this.bouncing){
			//TODO: falling animation
			this.renderable.setCurrentAnimation("knockedDownFall"+this.cloaked);
		}
		
		//make spy bounce off the ground a little
		if(!this.bounce1 && !this.bounce2 && !this.falling  && !this.bouncing ){
			this.renderable.setCurrentAnimation("knockedDown"+this.cloaked);
			this.vel.x = 0;
		}else if(!this.bounce1 && !this.falling && this.bounce2 && !this.bouncing){
			//console.log('bounce2');
			this.vel.x = (this.flippedX) ?  1 * me.timer.tick :  -1 * me.timer.tick;
			
			this.vel.y -= 3 * me.timer.tick;
			this.bounce2 = false;
			this.bouncing = true;
			
			this.renderable.setCurrentAnimation("knockedDown"+this.cloaked);
			
			this.jumpDust();
		}else if(this.bounce1){
			//console.log('bounce1');
			this.vel.x = (this.flippedX) ? 2 * me.timer.tick : -2 * me.timer.tick;
			
			this.vel.y -= 6 * me.timer.tick;
			this.bounce1 = false;
			this.bouncing = true;
			
			this.jumpDust();
		}else{
			/*this.vel.x=0;
			if(this.xDistance >= this.xDistanceLimit1){
				this.vel.x = 0;
			}
			*/
			//if x velocity isn't zero, we need to make it follow a parabolic curve
		}
		
		//this.xDistance += Math.abs(this.vel.x);
		//console.log(this.vel.x);
		
		
		
		this.updateMovement();
		
		this.parent(this);
		return true;
	},
	jumpDust: function(){
		
		var jumpdust = me.entityPool.newInstanceOf("jumpdust", this.pos.x + 4, this.pos.y + 24, {image:'jumpdust', spritewidth:16, spriteheight: 8 });
		//var jumpdust = new JumpDustEntity(this.pos.x + 4, this.pos.y + 24, {image:'jumpdust', spritewidth:16, spriteheight: 8 });
			me.game.add(jumpdust,this.z + 1);
			//me.game.sort();
	},
});


/* ---------------------
a spy caught by beam (fried) entity
----------------------*/

var SpyBeamedEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);	
		this.collidable = true;
		this.gravity = (0.41);
		this.setVelocity(2,2);		
		this.renderable.addAnimation('fried', [0,1,2,3],3);
		
		this.flippedX = settings.flipX
		this.flipX(this.flippedX);
		//Will check for more conditions probably
		this.renderable.setCurrentAnimation("fried", function(){ this.knockeddown(settings.image) }.bind(this));
		
		spyCaught = this;
		
	},
	update: function(){
		
		this.parent(this);
		return true;
	},
	knockeddown: function(image){
		if(image == 'spyshocked'){
			var spriteImage = 'spycaughtshocked';
		}else if(image == 'spyburning'){
			var spriteImage = 'spycaughtburning';
		}else{
			var spriteImage = 'spycaughtbeamed';
		}
		//var spycaught = new SpyCaughtEntity(this.pos.x, this.pos.y, {image:spriteImage, spritewidth:32, spriteheight: 32, cloaked: '', flipX: this.flippedX});
		var spycaught = me.entityPool.newInstanceOf("spycaught",this.pos.x, this.pos.y, {image:spriteImage, spritewidth:32, spriteheight: 32, cloaked: '', flipX: this.flippedX});
			me.game.add(spycaught,this.z);
			//me.game.sort();
		
		this.renderable.setOpacity(0);
		me.game.remove(this);
	}
});

/* ---------------------
a spy caught by beam (fried) entity
----------------------*/

var SpyVRDeathEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);	
		this.collidable = true;
		this.nextLevel = me.game.getEntityByName("exitdoor")[0].nextLevel;
		//console.log(this.nextLevel);
		this.renderable.addAnimation('fried', [0,1,2,3,2,3,4,5],3);
		
		this.renderable.setCurrentAnimation("fried", function(){ this.glitchOut(); }.bind(this));
		
		spyCaught = this;
		
	},
	update: function(){
		
		this.parent(this);
		return true;
	},
	glitchOut: function(){
		
		this.renderable.setOpacity(0);
		//We should be loading the level you came from if in normal game mode		
		if(me.gamestat.getItemValue('currentMode') != 'timeAttack'){
			//leveltransition = new LevelTransitionEntity(spy.pos.x - 320, spy.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
			var leveltransition = me.entityPool.newInstanceOf("leveltransition",spy.pos.x - 320, spy.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
			me.game.add(leveltransition,300);
			//me.game.sort();
			

			
			var whiteNoise = new WhiteNoiseEntity(0,0, {});
			me.game.add(whiteNoise,1000);			
			
			me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel(this.nextLevel); }.bind(this));
		}
		//Will have to do additional checks for time attack
		//me.levelDirector.reloadLevel();
		me.game.remove(this);
	}
});


/* ---------------------
a jumpdust entity
----------------------*/

var JumpDustEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 16;
		this.type = 'JUMPDUST';
		this.collidable = false; 
		this.gravity= (0);
		this.parent(x,y,settings);
		this.renderable.addAnimation('dust', [0,2]);
		
		this.renderable.setCurrentAnimation("dust", (function () {
			this.remove();
			 return false; // do not reset to first frame
		}).bind(this));
	},
	update: function(){
		this.parent(this);
		return true;
	},
	remove: function(){
		this.renderable.alpha = 0;
		me.game.remove(this);
	}
});

/* ---------------------
a hitspy entity
----------------------*/

var HitSpyEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 16;
		this.type = 'HITSPY';
		this.collidable = false; 
		this.gravity= (0);
		this.parent(x,y,settings);
		this.renderable.addAnimation('dust', [0,1,2,3],4);
		
		this.renderable.setCurrentAnimation("dust", (function () {
			this.remove();
			 return false; // do not reset to first frame
		}).bind(this));
	},
	update: function(){
		this.parent(this);
		return true;
	},
	remove: function(){
		this.renderable.alpha = 0;
		me.game.remove(this);
	}
});

/* ---------------------
a keycard entity
----------------------*/
var KeyCardEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false; //TODO: Set to false, do own collision checking
		this.renderable.addAnimation('keycard',[0,0,0,0,0,0,0,0,1,2,3]);
		this.renderable.setCurrentAnimation('keycard');
			
		this.cpid = (settings.cpid) ? settings.cpid : 'kc01';
		
	},
	//check for collision with player, unlock the door
	update: function(){
		//Don't update if not on screen
		if(!this.visible){
			return false;
		}
		
		//TODO: custom collision detection here for multiple collisions
		//var res = me.game.collide(this);
		//if(res && (res.obj.type == me.game.SPY)){
		if(spy.alive && this.overlaps(spy.collisionBox)){
			//audio
		
			//Update the hud

			//make sure it cannot be collected "again" (only allow once collision)
			this.collidable = false;
			spy.getKey();
			
			//save in temp checkpointData for novice mode
			
			var checkpointData = me.gamestat.getItemValue('checkpointDataTemp') + ',' + this.cpid;
			me.gamestat.setValue('checkpointDataTemp',checkpointData);
			
			//remove it
			me.game.remove(this);
			me.audio.play('keycard');
			//Unlock the door
			//TODO: Move this into ExitEntity
			
			me.game.getEntityByName("exitdoor")[0].keys++;
			if(me.game.getEntityByName("exitdoor")[0].keys == 1){
				me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked');
			}else if(me.game.getEntityByName("exitdoor")[0].keys == 2){
				me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked2');
			}else{
				me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked3');
			}
		}			
		this.parent(this);
		return true;		
	},
	checkpointClear:function(){
		me.game.getEntityByName("exitdoor")[0].keys++;
		//console.log(me.game.getEntityByName("exitdoor")[0].keys);
		if(me.game.getEntityByName("exitdoor")[0].keys == 1){
			me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked');
		}else if(me.game.getEntityByName("exitdoor")[0].keys == 2){
			me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked2');
		}else{
			me.game.getEntityByName("exitdoor")[0].renderable.setCurrentAnimation('unlocked3');
		}
		
		me.game.remove(this);
	}
});

/* ---------------------
an exit door entity
----------------------*/
var ExitEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		(settings.nextLevel) ? this.nextLevel = settings.nextLevel : this.nextLevel = false;
		this.locked = true;
		this.collidable = false;
		this.gravity = 0;
		this.alwaysUpdate = true;
		this.keys = 0;
		this.opened = false;
		this.timer = 0;
		
		this.stealthOn = spy.stealthOn;
		
		(settings.keyReq || settings.keyReq === 0) ? this.keyReq = settings.keyReq : this.keyReq = 1;
		
		(settings.toCutscene) ? this.toCutscene = settings.toCutscene : this.toCutscene = false;
		
		
		
		
		//TODO: different animation if keyReq is > 1		
		if( this.keyReq  == 2 ){
			this.renderable.addAnimation('locked',[1]);
			this.renderable.addAnimation('unlocked2',[0]);
			this.renderable.addAnimation('unlocked',[2]);
			this.renderable.addAnimation('open',[3,4]);
			this.renderable.addAnimation('opened',[4]);
			this.renderable.setCurrentAnimation('locked');
		}else if( this.keyReq  == 3 ){
			this.renderable.addAnimation('locked',[1]);
			this.renderable.addAnimation('unlocked3',[0]);
			this.renderable.addAnimation('unlocked2',[3]);
			this.renderable.addAnimation('unlocked',[2]);
			this.renderable.addAnimation('open',[4,5]);
			this.renderable.addAnimation('opened',[5]);
			this.renderable.setCurrentAnimation('locked');
		}else{
			this.renderable.addAnimation('locked',[1]);
			this.renderable.addAnimation('unlocked',[0]);
			this.renderable.addAnimation('open',[3,4,2]);
			this.renderable.addAnimation('opened',[2]);
			this.renderable.setCurrentAnimation('locked');
		}

		
		//this.animationspeed = me.sys.fps / 20;
		
		/*
		if(this.toCutscene){
			//Hide the door
			this.renderable.setOpacity(0);
			console.log('Going to Cutscene');
		}
		*/
		//console.log('Alpha: ' + this.renderable.getOpacity() + ' ' + this.renderable.alpha);
		
		if(this.toCutscene){
			//Expand the door collision area to make bounding box
			//this.updateColRect(0,settings.width,0,settings.height);
			this.updateColRect(1,settings.width-2,0,settings.height);
			this.renderable.setOpacity(0);
			this.renderable.alpha = 0;
		}
		
		var currentMapName = me.levelDirector.getCurrentLevelId();
		var currentLevelName = me.levelDirector.getCurrentLevelId().split('_');
		var currentMission = currentLevelName[1];
		
		if(currentMission == 'vr'){
			this.VR = true;			
		}else{
			this.VR = false;
		}
	},
	update:function(){
		if(this.toCutscene){
			//Hide the door
			//this.renderable.setOpacity(0);			
		}
		if(this.alive){
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY) && this.keys >= this.keyReq  && !this.opened && spy.alive && !spy.falling && !spy.jumping){
			
			if(this.keys >= this.keyReq  && !this.opened && spy.alive && !spy.falling && !spy.jumping && this.colOverlaps(spy.collisionBox)){

				//Don't activate the door if the spy is falling or jumping
				//only work if spy is actually in the door frame
				//if spy.pos.x
				//this.pos.x
				//
				//console.log("Spy: " + spy.pos.x + " Door: " + this.pos.x);
				//Right
				/*
				if((!spy.currentDirection && spy.pos.x > this.pos.x + 8 && spy.pos.x < this.pos.x + 16) || (spy.currentDirection && spy.pos.x > this.pos.x && spy.pos.x < this.pos.x + 8)){
				*/
								
				if(spy.pos.x > this.pos.x - 12 && spy.pos.x < this.pos.x + 8 && !this.toCutscene){
				
					spy.pos.y = this.pos.y;
					
					//audio		
					if(!this.VR){
						me.audio.play('levelclear');
					}
					
					//Spy
					spy.exitLevel(this.pos.x);
					
					//Transition
					//*
					this.startTransition();
					//spy.renderable.setCurrentAnimation('cloakExit');
					//this.toNextLevel()
				}else if(this.toCutscene){
					this.startTransition();
				}
			}
			
			if(this.opened){
				this.timer += me.timer.tick;
				if(this.timer >= 9){
					
					
					//console.log('tst');
					
				}
			}
		}
		
		this.parent(this);
		return true;		
	},
	startTransition: function(){
		//leveltransition = new LevelTransitionEntity(this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
		var leveltransition = me.entityPool.newInstanceOf("leveltransition",this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
		me.game.add(leveltransition,60);
		me.game.sort();
		//*/
		//take me to the next level
		this.renderable.setCurrentAnimation('open', function(){ this.fadeToNextLevel(); }.bind(this));
		//console.log('opening...');
		
		this.opened = true;
	},
	fadeToNextLevel: function(){
		//console.log('opened');
		this.renderable.setCurrentAnimation('opened');
		
		var currentMapName = me.levelDirector.getCurrentLevelId();
		var currentLevelName = me.levelDirector.getCurrentLevelId().split('_');
		var currentMission = currentLevelName[1];
		
		if(this.VR){
			var whiteNoise = new WhiteNoiseEntity(0,0, {});
			me.game.add(whiteNoise,1000);
		}
		
		me.game.viewport.fadeIn('#000000',300, function(){ this.toNextLevel() }.bind(this));
		//spy.alive = false;
		
	},
	toNextLevel:function(){
		
		//Clear Checkpoint Data
		me.gamestat.setValue('checkpointDataTemp','');
		me.gamestat.setValue('checkpointData','');
		me.gamestat.setValue('checkpointActivated','');
		me.gamestat.setValue('checkpointCurrent','');
		
		//Copy temp Stats over
		/*
		me.gamestat.updateValue("stealthCount", me.gamestat.getItemValue('stealthCountTemp'));
		me.gamestat.updateValue("stepCoun", me.gamestat.getItemValue('stepCountTemp'));
		me.gamestat.updateValue("jumpCount", me.gamestat.getItemValue('jumpCountTemp'));
		me.gamestat.updateValue("dangerCount", me.gamestat.getItemValue('dangerCountTemp'));
		
		me.gamestat.setValue("stealthCountTemp", 0);
		me.gamestat.setValue("stepCountTemp", 0);
		me.gamestat.setValue("jumpCountTemp", 0);
		me.gamestat.setValue("dangerCountTemp", 0);
		*/
		//Save current game status
		
		//Need to check current game mode. 
		//Time Attack will take to you level score screen
		var currentMapName = me.levelDirector.getCurrentLevelId();
		var currentLevelName = me.levelDirector.getCurrentLevelId().split('_');
		var currentMission = currentLevelName[1];
		
		var currentLevel = parseInt(currentLevelName[3]);
		//console.log('current level: ' + currentLevel);
		var nextLevel;
		var nextMission;
		
		if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
			//Save stats and stuff
			//Unlock the next level
			
			//Stealth Doesn't carry over here
			this.stealthOn = false;
			
			if(currentMission != 'vr'){
				currentMission = parseInt(currentMission);
			
				if(currentLevel == 10 && currentMission == 5){
					//You win the game.
					//Unlock Darkness Mode
					//Cool.
					nextLevelName = 'return';
				}else if(currentLevel == 10){
					nextLevel = '01';
					currentMission++;
					nextMission = '0' + String(currentMission);	
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;	
					
					//If cheat is enabled, don't save unlocks (but still save times)
					if(me.gamestat.getItemValue('cheatEnabled') != 1){
						//Unlock Next Mission for Time Attack
						gameData.save('m_' + nextMission+'_unlocked',true);
						//Unlock Next Level for Time Attack
						gameData.save(nextLevelName+'_unlocked',true);
					}
					
					//Load intermediary so audio loads
					nextLevelName = 'm_' + nextMission + '_level_load';
					
				}else if(currentLevel == 9){
					currentLevel++;
					nextLevel = String(currentLevel);
					nextMission = '0' + String(currentMission);
					//console.log('next level: ' + nextLevel);
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;

					//If cheat is enabled, don't save unlocks (but still save times)
					if(me.gamestat.getItemValue('cheatEnabled') != 1){
						//Unlock Next Level for Time Attack
						gameData.save(nextLevelName+'_unlocked',true);
					}
				
				}else{
					currentLevel++;
					nextLevel = '0' + String(currentLevel);
					nextMission = '0' + String(currentMission);
					//console.log('next level: ' + nextLevel);
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;

					//If cheat is enabled, don't save unlocks (but still save times)
					if(me.gamestat.getItemValue('cheatEnabled') != 1){
						//Unlock Next Level for Time Attack
						gameData.save(nextLevelName+'_unlocked',true);
					}
				}
				
				me.gamestat.setValue('nextTimeAttackLevel',nextLevelName);
			
			}else{
				me.gamestat.setValue('nextTimeAttackLevel','vr');
			}
			
			
			//Go to intermediary score screen
			me.levelDirector.loadLevel('level_score_screen');
			
		}else{ //Normal and Darkness (story) mode
			//Save, Compare, and Reset Level Stats
			var caughtCount = me.gamestat.getItemValue('current_level_caught');
		
			var levelTime = Math.round(me.gamestat.getItemValue('current_level_time') / .06); //.06 instead of 60, gives me 1/10th ms
			/*
			var levelTimeH = parseInt(levelTime / 36000) % 24;
			var levelTimeM = parseInt(levelTime / 600) % 60;
			var levelTimeS = levelTime % 600;
			var levelTimeMs = levelTime % 600;
			*/
			/*
			var levelTimeH = parseInt( (levelTime / 3600000) % 24);
			var levelTimeM = parseInt( (levelTime / 60000) % 60);
			var levelTimeMAll = parseInt( (levelTime / 60000)); //If we want mintues and no hours
			var levelTimeS = parseInt( (levelTime/1000) % 600);
			var levelTimeMs = parseInt((levelTime%1000)/100);
			
			var levelTimeSTotal = levelTime;
			
			levelTime = (levelTimeH < 10 ? "0" + levelTimeH : levelTimeH) + ":" + (levelTimeM < 10 ? "0" + levelTimeM : levelTimeM) + ":" + (levelTimeS  < 10 ? "0" + levelTimeS : levelTimeS);
			*/
			var bestTime = gameData.load(currentMapName+'_time');
			var bestCaught = gameData.load(currentMapName+'_caught');
			
			//console.log('Level Time: ' + me.gamestat.getItemValue('current_level_time'));
			
			//compare best and current times
			if(isNaN(bestTime) || bestTime === null || bestTime === 0 || levelTime < bestTime ){
				gameData.save(currentMapName+'_time',levelTime);
				gameData.save(currentMapName+'_caught',caughtCount);
				bestTime = levelTime;
				bestCaught = caughtCount;
			}
			
			me.gamestat.setValue('current_level_time',0);
			me.gamestat.setValue('current_level_caught',0);		
			
			gameData.save('current_game_time',me.gamestat.getItemValue('current_game_time'));
			gameData.save('current_game_caught',me.gamestat.getItemValue('current_game_caught'));
			
			gameData.save('current_mission_time',me.gamestat.getItemValue('current_mission_time'));
			gameData.save('current_mission_caught',me.gamestat.getItemValue('current_mission_caught'));
			gameData.save('current_level_time',0);
			gameData.save('current_level_caught',0);
			
			if(currentMission != 'vr'){
				currentMission = parseInt(currentMission);
				//vr check here too?
				if(currentLevel == 10 && currentMission == 5){
					//You win the game.
					//Unlock Darkness Mode (Now done in blind_master cutscene
					//Cool.
					//gameData.save('darknessModeUnlocked','true');
					
					//Stealth Doesn't carry over here
					this.stealthOn = false;
					
					
					//Save stats to temp, 0 out stats
					me.gamestat.setValue('current_mission_time_temp',me.gamestat.getItemValue('current_mission_time'));
					me.gamestat.setValue('current_mission_caught_temp',me.gamestat.getItemValue('current_mission_caught'));	
					
					me.gamestat.setValue('current_mission_time',0);
					me.gamestat.setValue('current_mission_caught',0);		
					
					gameData.save('current_mission_time',me.gamestat.getItemValue('current_mission_time'));
					gameData.save('current_mission_caught',me.gamestat.getItemValue('current_mission_caught'));
										
				}else if(currentLevel == 10){
					//Stealth Doesn't carry over here
					this.stealthOn = false;
					
					nextLevel = '01';
					currentMission++;
					nextMission = '0' + String(currentMission);	
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;
					gameData.save('currentLevel',nextLevelName);
					
					//Unlock Next Mission for Time Attack
					gameData.save('m_' + nextMission+'_unlocked',true);
					//Unlock Next Level for Time Attack
					gameData.save(nextLevelName+'_unlocked',true);
					
					
					//Save stats to temp, 0 out stats
					me.gamestat.setValue('current_mission_time_temp',me.gamestat.getItemValue('current_mission_time'));
					me.gamestat.setValue('current_mission_caught_temp',me.gamestat.getItemValue('current_mission_caught'));	
					
					//console.log('M Caught: ' + me.gamestat.getItemValue('current_mission_caught'));
					//console.log('M Caught Temp: ' + me.gamestat.getItemValue('current_mission_caught_temp'));
					
					me.gamestat.setValue('current_mission_time',0);
					me.gamestat.setValue('current_mission_caught',0);		
					
					gameData.save('current_mission_time',me.gamestat.getItemValue('current_mission_time'));
					gameData.save('current_mission_caught',me.gamestat.getItemValue('current_mission_caught'));
					
				}else if(currentLevel == 9){
					currentLevel++;
					nextLevel = String(currentLevel);
					nextMission = '0' + String(currentMission);
					//console.log('next level: ' + nextLevel);
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;
					gameData.save('currentLevel',nextLevelName);
					
					//Unlock Next Level for Time Attack
					gameData.save(nextLevelName+'_unlocked',true);
					
				}else{
					currentLevel++;
					nextLevel = '0' + String(currentLevel);
					nextMission = '0' + String(currentMission);
					//console.log('next level: ' + nextLevel);
					var nextLevelName = 'm_' + nextMission + '_lvl_' + nextLevel;
					gameData.save('currentLevel',nextLevelName);
					
					//Unlock Next Level for Time Attack
					gameData.save(nextLevelName+'_unlocked',true);
				}
			}else{	//VR Level Here
				
				//Save Unlock
				gameData.save('vr_0'+currentLevel+'_complete',true);
				
				//If it's level 8, check to see if all previous vr levels were cleared
				if(currentLevel == '3'){
					var allVRComplete = true;
					for(vri = 1; vri <= 8;vri++){
						if(!gameData.load('vr_0'+vri+'_complete')){
							allVRComplete = false;
						}
					}
					if(allVRComplete){
						gameData.save('vr_complete',true);
					}
				}
				
			}
			
			if(this.nextLevel){
				if(this.nextLevel == 'GAME_END'){
					//Check For Game End
					//Level 10 for prototype
					me.state.change(me.state.GAME_END);
				}else{
					this.alive = false;
					//me.state.change(me.state.READY, this.nextlevel);
					if(this.stealthOn){
						me.gamestat.setValue('stealthState', 1);
					}else{
						me.gamestat.setValue('stealthState',0);
					}
					//me.game.HUD.setItemValue('LevelName',this.nextLevel);
					me.levelDirector.loadLevel(this.nextLevel);
				}
			}			
		}
	}/*,
	colOverlaps : function(r)	{
		return (this.collisionBox.left < r.right && 
		r.left < this.collisionBox.right && 
		this.top < r.bottom &&
		r.top < this.collisionBox.bottom);
	}*/
	
});



/* ---------------------
a VR Door Entity
----------------------*/
var VRDoorEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		(settings.nextLevel) ? this.nextLevel = settings.nextLevel : this.nextLevel = false;
		this.locked = true;
		this.collidable = false;
		this.gravity = 0;
		this.alwaysUpdate = true;		
		this.opened = false;
		this.timer = 0;
		this.glitchImage = (settings.glitchImage) ? settings.glitchImage : '';			
		//this.animationspeed = me.sys.fps / 20;
		
		/*
		if(this.toCutscene){
			//Hide the door
			this.renderable.setOpacity(0);
			console.log('Going to Cutscene');
		}
		*/
		//console.log('Alpha: ' + this.renderable.getOpacity() + ' ' + this.renderable.alpha);
		
		this.updateColRect(0,settings.width,0,settings.height);
		this.renderable.setOpacity(0);
		this.renderable.alpha = 0;
		
		//Unlock VR Level if not in time attack mode
		//console.log('Current Game Mode: ' + me.gamestat.getItemValue('currentMode'));
		
		if(me.gamestat.getItemValue('currentMode') != 'timeAttack'){
			gameData.save(this.nextLevel+'_unlocked',true);
			gameData.save('m_vr_unlocked',true);
			//console.log('Current Game Mode: Not Time Attack?');
		}else{
			//if it is time attack mode, don't let them play VR this way.
			console.log('Current Game Mode: Time Attack?');
			//Block it off
			
			
		}
		
	},
	update:function(){
		if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){	
			//var barrier = new HackableDoorEntity(this.pos.x-4, this.pos.y, {image:'onewaydoor2', spritewidth:16, hide: true,doorName:'vrdoor' });
			
			var barrier = me.entityPool.newInstanceOf("hackabledoor",this.pos.x-4, this.pos.y, {image:'onewaydoor2', spritewidth:16, hide: true,doorName:'vrdoor' });			
			me.game.add(barrier,this.z + 1);
			
			//var barrier2 = new HackableDoorEntity(this.pos.x+4, this.pos.y, {image:'onewaydoor2', spritewidth:16, hide: true,doorName:'vrdoor' });			
			var barrier2 = me.entityPool.newInstanceOf("hackabledoor",this.pos.x+4, this.pos.y, {image:'onewaydoor2', spritewidth:16, hide: true,doorName:'vrdoor' });			
			me.game.add(barrier2,this.z + 1);
						
			me.game.remove(this);
		}
		
		if(this.alive){
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY) && this.keys >= this.keyReq  && !this.opened && spy.alive && !spy.falling && !spy.jumping){
			
			if(!this.opened && spy.alive && this.colOverlaps(spy.collisionBox)){

				//Don't activate the door if the spy is falling or jumping
				//only work if spy is actually in the door frame
				//if spy.pos.x
				//this.pos.x
				//
				//console.log("Spy: " + spy.pos.x + " Door: " + this.pos.x);
				//Right
				/*
				if((!spy.currentDirection && spy.pos.x > this.pos.x + 8 && spy.pos.x < this.pos.x + 16) || (spy.currentDirection && spy.pos.x > this.pos.x && spy.pos.x < this.pos.x + 8)){
				*/
								
				if(spy.pos.x > this.pos.x - 12 && spy.pos.x < this.pos.x + 8){
				
					spy.pos.y = this.pos.y;
					spy.alive = false;
					//audio		
					//me.audio.play('levelclear'); //NEED A DIFFERENT SOUND HERE
					//me.audio.play('whitenoise');
					//Spy
					//spy.exitLevel(this.pos.x);
					
					
					//Let's make the glitch bgsprite animate now
					var bgsprites = me.game.getEntityByProp('image',this.glitchImage);
					for(var i = 0; i < bgsprites.length; i++){
						//console.log(trapDevices[i]);
						bgsprites[i].glitch();	
						//console.log('found one');
					}	
					
					//Transition
					//*
					this.startTransition();
					//spy.renderable.setCurrentAnimation('cloakExit');
					//this.toNextLevel()
				}
			}
			
			if(this.opened){
				this.timer += me.timer.tick;
				if(this.timer >= 9){
					
					
					//console.log('tst');
					
				}
			}
		}
		
		this.parent(this);
		return true;		
	},
	startTransition: function(){
		//leveltransition = new LevelTransitionEntity(this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
		var leveltransition = me.entityPool.newInstanceOf("leveltransition",this.pos.x - 320, this.pos.y - 240, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
		me.game.add(leveltransition,60);
		//me.game.sort();
		//*/
		//take me to the next level
		//this.renderable.setCurrentAnimation('open', function(){ this.fadeToNextLevel(); }.bind(this));
		this.fadeToNextLevel();
		//console.log('opening...');
		
		this.opened = true;
	},
	fadeToNextLevel: function(){
		//console.log('opened');
		//this.renderable.setCurrentAnimation('opened');
		
		
		var whiteNoise = new WhiteNoiseEntity(0,0, {});
		me.game.add(whiteNoise,1000);
		
		
		
		me.game.viewport.fadeIn('#000000',300, function(){ this.toNextLevel() }.bind(this));
		//spy.alive = false;
		
	},
	toNextLevel:function(){
		
		this.alive = false;
		//me.state.change(me.state.READY, this.nextlevel);
		if(spy.stealthOn){
			me.gamestat.setValue('stealthState', 1);
		}else{
			me.gamestat.setValue('stealthState',0);
		}
		
		//me.game.HUD.setItemValue('LevelName',this.nextLevel);
		me.levelDirector.loadLevel(this.nextLevel);				
	}/*,
	colOverlaps : function(r)	{
		return (this.collisionBox.left < r.right && 
		r.left < this.collisionBox.right && 
		this.top < r.bottom &&
		r.top < this.collisionBox.bottom);
	} */
	
});

var LevelTransitionEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spriteWidth = 640;
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		this.updateWhenPaused = (settings.updateWhenPaused) ? settings.updateWhenPaused : false;	
		this.renderable.addAnimation('trans', [11,10,9,8,7,6,5,4,3,2,1,0], 1);
		this.renderable.addAnimation('end', [0], 1);
		this.renderable.addAnimation('transR', [0,1,2,3,4,5,6,7,8,9,10,11], 1);
		//this.renderable.isPersistent = true;
		
		this.transitionType = settings.transitionType;
		
		this.fadeStarted = false;
		
		(settings.volumeStep) ? this.volumeStep = settings.volumeStep : this.volumeStep = .0025;
		(settings.playSound) ? this.playSound = settings.playSound : this.playSound = false;
		
		this.currentVol = .5;
		this.startVol = .5;
		
		if(this.playSound){
			me.audio.play(this.playSound);
		}
		
		if(settings.transitionType == 'out'){
			this.renderable.setCurrentAnimation('trans', 'end');
			
			//console.log('vol: ' + me.audio.getVolume());
			//me.audio.setVolume(.05);
		}else{
			me.game.viewport.fadeOut('#000000',300);
			this.renderable.setCurrentAnimation('transR', function() {this.remove()}.bind(this));
			//me.audio.setVolume(1);
		}
	},
	update: function(){
		if(me.audio.getCurrentTrack()){
			//this.currentVol = me.audio.getTrackVolume(me.audio.getCurrentTrack());
			//fade back in
			//me.audio.fade(this.currentTrack,.3,.2,30);
		}
		
		if(this.transitionType == 'out'){	
			if(this.fadeStarted){
				this.fadeStarted = true;
				me.audio.fade(this.currentTrack,.4,.2,60);
			}
		}else{
			if(this.fadeStarted){
				this.fadeStarted = true;
				me.audio.fade(this.currentTrack,.2,.4,60);
			}
		}
		
		/*
		if(this.transitionType == 'out'){		
			
			if(me.audio.getCurrentTrack()){
				
				this.currentVol -= this.volumeStep * me.timer.tick;
				//console.log('vol: ' + me.audio.getVolume());
				//me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
			}
		}else{
			if(me.audio.getCurrentTrack() && this.currentVol <= this.startVol){
				this.currentVol += this.volumeStep * me.timer.tick;
				me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
			}
		}
		*/
		this.parent(this);
		return true;
	},
	toNextLevel: function(){
		this.renderable.setCurrentAnimation('transR', function() {this.remove()}.bind(this));		
	},
	remove: function(){
		this.renderable.alpha = 0;
		//me.audio.setTrackVolume(me.audio.getCurrentTrack(), 1);
		me.game.remove(this)
	}
});


/* ---------------------
Audio Toggle 

Plays or Fades In/Out a tracks when initiated
----------------------*/

var AudioToggleEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		//this.isper
		
	},
	update: function(){
		if(me.input.isKeyPressed('audio')){ 
		//console.log('test mute');
			if(audioIsMuted == true){
				me.audio.unmuteAll();
				audioIsMuted = false;
			}else{
				me.audio.muteAll();
				audioIsMuted = true;
			}
		}
		
		this.parent(this);
		return true;
	}
});

/* ---------------------
Audio Controller

Plays or Fades In/Out a tracks when initiated
----------------------*/

var AudioControllerEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		
		//(settings.fade) ? this.fade = settings.fade : this.fade = 'out';
		(settings.fade) ? this.fade = settings.fade : this.fade = 'in';
		(settings.newTrack) ? this.newTrack = settings.newTrack : this.newTrack =  false;
		//Play Track if specified
		
		//Fade Track?
		
		this.startFadeIn = false;
		this.trackStarted = false;
		
		this.fadeTo = settings.fadeTo;
		(settings.fadeStep) ? this.fadeStep = settings.fadeStep : this.fadeStep = .01;

		this.currentVol = .5;
		
	},
	update: function(){
		
		//play track
		//TODO: check for track playing, fade out
		//start new track, fade in
		if(!this.trackStarted && this.fade == 'in'){
			//console.log('track started');
			me.audio.playTrack(this.newTrack,0);
			me.audio.fade(this.newTrack,0,.4,40);
			if(!audioIsMuted){
				//need this		me.audio.unmute(me.audio.getCurrentTrack());
			}
			this.trackStarted = true;
			this.currentVol = 0;
			this.startFadeIn = true;
			
			//console.log(this.currentVol +  ' : ' + this.fadeTo);
		}
		
		
		if(this.startFadeIn){
			
			if(this.currentVol <= this.fadeTo){
				
				this.currentVol += this.fadeStep * me.timer.tick;
				//need this		me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
			}
		}
		
		this.parent(this);
		return true;
	}
});

/* ---------------------
Audio Controller

Plays or Fades In/Out a tracks when colldided with
----------------------*/

var AudioFaderEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		//this.isPersistent = true;
		(settings.fade) ? this.fade = settings.fade : this.fade = 'out';
		//Play Track if specified
		
		//Fade Track?
		
		this.startFade = false;
		this.fadeStarted = false;
		this.fadeTo = settings.fadeTo;
		this.fadeStep = settings.fadeStep;
		if(this.fade == 'in'){
			this.currentVol = 0;
		}else{
			this.currentVol = .5;
		}
		
		//(me.audio.getCurrentTrack()) ? this.currentTrack = me.audio.getCurrentTrack() : this.currentTrack = false;
				
		//console.log('fade: ' + this.fadeTo);
		
	},
	update: function(){
		
		//check for collision with spy
		//var res = me.game.collide(this);
		//if(res && (res.obj.type == me.game.SPY)){
		if(!this.startFade && !this.fadeStarted && this.colOverlaps(spy.collisionBox)){
			this.startFade = true;		
		}
		
		if(this.startFade && !this.fadeStarted){
			//if(me.audio.getCurrentTrack() && this.currentTrack == me.audio.getCurrentTrack()){
				this.fadeStarted = true;
				if(this.fade == 'out'){
					//me.audio.fade(this.currentTrack,.4,0,600);
					me.audio.fade(me.audio.getCurrentTrack(),.4,0,600);
				}else if(this.fade == 'in'){
						//me.audio.fade(this.currentTrack,0,.4,120);
						me.audio.fade(me.audio.getCurrentTrack(),0,.4,120);
				}
				
		
		
				/*
				if(this.fade == 'out'){
					if(this.currentVol >= this.fadeTo){
						this.currentVol -= this.fadeStep * me.timer.tick;
						me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
					}else{
						me.audio.stop(me.audio.getCurrentTrack());
						me.audio.mute(me.audio.getCurrentTrack());
						me.game.remove(this);
					}
				
				}else if(this.fade == 'in'){
					if(this.currentVol <= this.fadeTo){
						this.currentVol += this.fadeStep * me.timer.tick;
						me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
					}
				}
				*/
			//}
		}
		
		this.parent(this);
		return true;
	}
});



/* ---------------------
Audio BGM Player background music

Current level's BGM, Checks to see if already playing, if not, plays it
----------------------*/
var AudioBGMPlayerEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		
		//(settings.fade) ? this.fade = settings.fade : this.fade = 'out';
		(settings.fade) ? this.fade = settings.fade : this.fade = 'in';
		(settings.newTrack) ? this.newTrack = settings.newTrack : this.newTrack =  false;
		//Play Track if specified
		
		this.bgmMuted = false;
		
		//Fade Track?
		
		this.startFadeIn = false;
		this.trackStarted = false;
		
		//this.fadeTo = settings.fadeTo;
		this.fadeTo = (settings.fadeTo) ? settings.fadeTo : .4;	
		
		this.reload = (settings.reload) ? settings.reload : false;	
		
		(settings.fadeStep) ? this.fadeStep = settings.fadeStep : this.fadeStep = .01;

		this.currentVol = .4;
		this.masterVol = .4;
		
		
		//Start Here
		(settings.track) ? this.track = settings.track : this.track =  false;
		
		if(this.track == 'ost_m_02_02'){
			this.track = 'ost_m_02_01';
		}
		if(this.track == 'ost_m_03_02'){
			this.track = 'ost_m_03_01';
		}
		if(this.track == 'ost_m_04_02'){
			this.track = 'ost_m_04_01';
		}
		
		//need this		
		//*
		if(this.reload && this.track != me.audio.getCurrentTrack()){
			//Prep Unload
			if(me.audio.getCurrentTrack()) me.audio.stop(me.audio.getCurrentTrack());
			audioToUnload = [];
			audioToUnload = audioKeepLoaded.slice(0);
			audioKeepLoaded = [];
			//Unload All Marked Audio Files
			for(var i=0,j=audioToUnload.length;i<j;i++){
				me.loader.unload({
					name: audioToUnload[i],
					type: "audio"
				});
			}
			//Load the track
			audioKeepLoaded.push(this.track);
			me.loader.load({ 
				name: this.track,
				type: "audio",
				src: "data/audio/bgm/",
				channel: 1
			},(function () {
				//Play the track
				me.audio.playTrack(this.track.toString(),0);
				me.audio.fade(this.track.toString(),0,.4,40);					
			}).bind(this));
					
		}else if(this.track && this.track != me.audio.getCurrentTrack()){
			//play a new track!
			//this.playNewTrack = true;
			if(me.audio.getCurrentTrack()) me.audio.stop(me.audio.getCurrentTrack());
			if(!this.bgmMuted){
			me.audio.playTrack(this.track.toString(),0);
			me.audio.fade(this.track.toString(),0,.4,40);
			//console.log('track: ' + this.track);
			}
		} //*/
		
		//if(me.audio.getCurrentTrack()) me.audio.stop(me.audio.getCurrentTrack());
		
	},
	update: function(){
		/*
		if(this.playNewTrack){
			//play track
			//TODO: check for track playing, fade out
			//start new track, fade in
			if(!this.trackStarted && this.fade == 'in'){
				//console.log('track started' + this.track);
				if(!this.bgmMuted){
	//need this				me.audio.playTrack(this.track.toString(),0);
				}
				if(!audioIsMuted){
	//need this				me.audio.unmute(me.audio.getCurrentTrack());
				}
				this.trackStarted = true;
				this.currentVol = 0;
				this.startFadeIn = true;
				
				//console.log(this.currentVol +  ' : ' + this.fadeTo);
			}
			
			
			if(this.startFadeIn){
				
				if(this.currentVol <= this.fadeTo){
					
					this.currentVol += this.fadeStep * me.timer.tick;
	//need this				me.audio.setTrackVolume(me.audio.getCurrentTrack(), this.currentVol);
				}
			}
			
			this.parent(this);
			return true;
		}else{
			return false;
		}
		*/
		return false;
	}
});

/* ---------------------
CRT Toggle 

Turns on/off CRT Scanline effect. Just cause.
----------------------*/

var CRTToggleEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 320;
		settings.image = 'crtoverlay';
		this.parent(0,0,settings);
		this.anchorPoint.set(0,0);
		this.floating = true;
		this.isPersistent = true;
		this.alwaysUpdate = true;
		this.alphaFix = true;
		//set up animations
		this.renderable.addAnimation('static',[0,1,2,3],1);
		this.renderable.addAnimation('scanlines',[4,5,6,7],1);
		this.renderable.setCurrentAnimation('scanlines');
		this.transitioning = false;
		
		this.CRTMode = true;
		
		this.updateWhenPaused = true;
	},
	update: function(){
		if(this.alphaFix){
			//this.renderable.setOpacity(0);
			this.alphaFix = false;
		}
		
		if(me.input.isKeyPressed('crt') && !this.transitioning) { 		
			this.transitioning = true;
			me.audio.play('whitenoise');
			if(this.CRTMode == true){ //Turn Off				
				this.CRTMode = false;
				//play sfx
				this.renderable.setCurrentAnimation('static', function(){this.toggleCRTOff()}.bind(this));
								
			}else{ //Turn On
				this.CRTMode = true;
				//play sfx
				this.renderable.setOpacity(1);
				this.renderable.setCurrentAnimation('static',function(){ this.toggleCRTOn() }.bind(this));				
			}
		}
		
		this.parent(this);
		return true;
	},
	toggleCRTOff: function(){
		this.renderable.setOpacity(0);
		this.renderable.setCurrentAnimation('scanlines');
		this.transitioning = false;
	},
	toggleCRTOn: function(){
		this.renderable.setCurrentAnimation('scanlines');
		this.transitioning = false;
	}
});

/* ---------------------
White Noise Effect

Trying white noise on VR transition.
----------------------*/

var WhiteNoiseEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 320;
		settings.image = 'crtoverlay';
		this.parent(0,0,settings);
		this.anchorPoint.set(0,0);
		this.floating = true;
		this.isPersistent = true;
		this.alwaysUpdate = true;
		this.alphaFix = true;
		//set up animations
		this.renderable.addAnimation('static',[0,1,2,3,0,1,2,3,0,1,2,3],1);
		this.renderable.addAnimation('scanlines',[4,5,6,7],1);
		this.renderable.setCurrentAnimation('scanlines');
		this.transitioning = false;
		
		this.CRTMode = false;
		
		this.updateWhenPaused = true;
	},
	update: function(){
		if(this.alphaFix){
			//this.renderable.setOpacity(0);
			this.alphaFix = false;
		}
		
		if(!this.transitioning) { 		
			this.transitioning = true;
			me.audio.play('whitenoise');
			if(this.CRTMode == true){ //Turn Off				
				this.CRTMode = false;
				//play sfx
				this.renderable.setCurrentAnimation('static', function(){this.toggleCRTOff()}.bind(this));
								
			}else{ //Turn On
				this.CRTMode = true;
				//play sfx
				this.renderable.setOpacity(.4);
				this.renderable.setCurrentAnimation('static',function(){ this.toggleCRTOn() }.bind(this));				
			}
		}
		
		this.parent(this);
		return true;
	},
	toggleCRTOff: function(){
		this.renderable.setOpacity(0);
		this.renderable.setCurrentAnimation('scanlines');
		this.transitioning = false;
	},
	toggleCRTOn: function(){
		me.game.remove(this);
		this.transitioning = false;
	}
});


/* ---------------------
DARKNESS MODE
----------------------*/

var DarkModeEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 780;
		settings.spriteheight = 620;
		//settings.image = 'darkmode';
		
		
		this.lightsOnFast = false;
		
		//if it's already darkness mode, we don't want to add it again
		if(me.gamestat.getItemValue('currentMode') == 'darkness'){
			if(settings.onLevel){
				me.game.remove(this);
				this.lightsOnFast = true;
			}
		}
		
		this.darkness = true;
		
		this.width = 780;
		this.height = 620;
		this.parent(0,0,settings);
		this.anchorPoint.set(0,0);
		
		this.alwaysUpdate = true;
		//this.alphaFix = true;
		//set up animations
		//this.renderable.addAnimation('static',[0,1,2,3],1);
		//this.renderable.addAnimation('scanlines',[4,5,6,7],1);
		//this.renderable.setCurrentAnimation('scanlines');
			
		//this.updateWhenPaused = true;
		//this.pos.x = spy.pos.x - 344;
		//this.pos.y = spy.pos.y - 228;
		this.lightsOn = false;
		this.alphaTime = 6;
		this.alphaCounter = 0;
		
		this.counter1 = 0;
		this.counter2 = 0;
		this.counter3 = 0;
		this.counter4 = 0;
		
		if(me.gamestat.getItemValue('currentMode') != 'darkness' && me.gamestat.getItemValue('checkpointCurrent') == 'galehdoor1'){
			this.lightsOnFast = true;
			this.renderable.alpha = 0;	
		}
	},
	update: function(){
		
		if(spy.alive || spy.exiting){
			this.pos.x = spy.pos.x - 378;
			this.pos.y = spy.pos.y - 294;
		}else{	
			if(this.alphaCounter < this.alphaTime){
				++this.alphaCounter;
			}else{
				this.alphaCounter = 0;
				if(this.renderable.alpha === 1){
					this.renderable.alpha = 0.9;
				}else if(this.renderable.alpha === 0.9){
					this.renderable.alpha = 0.8;
				}else{	
					this.renderable.alpha = 1;
				}
			}
			
			if(spy.caughtMode == 'normal'){
				this.pos.x = spy.pos.x - 378;
				this.pos.y = spy.pos.y - 294;
			}else{
				//console.log(spyCaught);
				this.pos.x = spyCaught.pos.x - 378;
				this.pos.y = spyCaught.pos.y - 294;
			}
		}
		
		if(this.lightsOnFast){			
			this.renderable.alpha = 0;		
			me.game.remove(this);
		}
		
		if(this.lightsOn){
			if(this.counter1 < 6){
				this.renderable.alpha = 0;	
				this.counter1++;				
			}else if(this.counter2 < 2){
				this.renderable.alpha = 1;	
				this.counter2++;	
			}else if(this.counter3 < 6){
				this.renderable.alpha = 0;	
				this.counter3++;	
			}else if(this.counter4 < 2){
				this.renderable.alpha = 1;	
				this.counter4++;	
			}else{
				this.renderable.alpha = 0;		
				me.game.remove(this);
			}
		}
		
		this.parent(this);
		return true;
	},
	turnLightsOn: function(){
		//console.log('lights on');
		this.lightsOn = true;
		
		if(gameData.load('screenshakeDisabled') != 'yes'){
			me.game.viewport.shake(10,100, me.game.viewport.AXIS.BOTH);
		}
		
	},
	turnLightsOnNoShake: function(){
		//console.log('lights on');
		this.lightsOn = true;
	},
});
/* ---------------------
DARKNESS MODE SWITCH
----------------------*/

var DarkModeSwitchEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		//settings.spritewidth = 780;
		//settings.spriteheight = 620;
		//settings.image = 'darkmode';
		//this.width = 780;
		//this.height = 620;
		this.parent(x,y,settings);
		//this.alphaFix = true;
		//set up animations
		//this.renderable.addAnimation('static',[0,1,2,3],1);
		//this.renderable.addAnimation('scanlines',[4,5,6,7],1);
		//this.renderable.setCurrentAnimation('scanlines');
			
		//this.updateWhenPaused = true;
		//this.pos.x = spy.pos.x - 344;
		//this.pos.y = spy.pos.y - 228;
		this.cpid = (settings.cpid) ? settings.cpid : 'dm01';
		this.collidable = false;
		
		this.switched = false;
		
		this.darknessOn = false;
		if(me.gamestat.getItemValue('currentMode') == 'darkness'){
			this.darknessOn = true;
		}
	},
	update: function(){
		
		if(!this.switched && !this.darknessOn){
			
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY)){
			if(this.colOverlaps(spy.collisionBox)){
				this.switched = true;
				var darkness = me.game.getEntityByProp('darkness',true);
				for(var i = 0; i < darkness.length; i++){
					darkness[i].turnLightsOn();
				}	

					//save in temp checkpointData for novice mode
					var checkpointData = me.gamestat.getItemValue('checkpointDataTemp') + ',' + this.cpid;
					me.gamestat.setValue('checkpointDataTemp',checkpointData);				
				
			}
		}
		this.parent(this);
		return true;
	},
	checkpointClear:function(){
		console.log('darkness on? ' + this.darknessOn);
		if(!this.darknessOn){
			this.switched = true;
			console.log('turning lights on');
			var darkness = me.game.getEntityByProp('darkness',true);			
			for(var i = 0; i < darkness.length; i++){
				console.log('turning lights on yes');
				darkness[i].lightsOnFast = true;
			}
		}
	}
});

/* ---------------------
a enemy entity

parent entity that controls position reset
----------------------*/
var enemyEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		//need a flag for reset
		this.reset = false;
		this.alwaysUpdate = true;

	},
	update: function(){
		//if(this.resetCheck(this.startPosX,this.startPosY)) return false;
		this.parent(this);
		return true;
	},
	resetCheck: function(x,y,flipX){
		if(!this.inViewport){
			if(!this.reset){
				this.reset = true;
				this.resetPos(x,y,flipX);
				this.alwaysUpdate = false;				
				return false;
			}else{
				return true;
			}
		}else{
			if(this.reset !== false){
			this.reset = false;
			this.alwaysUpdate = true;
			}
			return false;
		}
	},
	resetPos: function(x,y,flipX){
		this.flipX(flipX);
		this.walkLeft = !flipX; //Fixes Issue with guard
		this.pos.x = x;
		if(y) this.pos.y = y;
	}
});


/* ---------------------
a lazy security guard entity
----------------------*/

var LazyGuardEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//set up animations
		this.renderable.addAnimation('stand',[0]);
		
		//New Collision to account for extra pixel
		this.updateColRect(1,14,1,15);

		
		this.image = settings.image;
		
		if(this.image == 'lazyguard3'){
			this.renderable.addAnimation('yawn',[1,2,2,2,3,3],12);
			this.renderable.addAnimation('catch',[4]);
			this.renderable.addAnimation('alarmed',[5,6],60);
			this.animationArray = ['yawn'];
			//set up animation timer
			this.animationCount = 180;
			
		}else{
			this.renderable.addAnimation('scratch',[1,2,1,2],12);
			this.renderable.addAnimation('yawn',[3],40);
			this.renderable.addAnimation('catch',[4]);
			this.renderable.addAnimation('alarmed',[5,6],60);
			this.animationArray = ['scratch','yawn'];
			//set up animation timer
			this.animationCount = 180;
		}
		this.renderable.setCurrentAnimation('stand');
		
		
		this.animationC = 0;
		
		//Position guard
		if(settings.startSide == 'left'){
			this.pos.x = x;
			this.flipX(true);
			this.dangerZoneLeft = this.dangerZoneLeft + 8;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth;
			this.dangerZoneRight = this.dangerZoneRight - 8;
		}

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}

	},
	update: function(){
		if(this.removeImmediately){
			me.game.remove(this);
			
		}
		if(!this.renderable.isCurrentAnimation('catch')){
			if(this.animationCount >= 0){
				this.animationCount -= me.timer.tick;			
			}else{
				if(this.image == 'lazyguard3'){
					this.renderable.setCurrentAnimation('yawn', 'stand');
					this.animationCount = 360;
				}else{
					this.animationC = 1 - this.animationC;
					this.renderable.setCurrentAnimation(this.animationArray[this.animationC], 'stand');
					this.animationCount = 180;
				}
				
			}
		}		
		
		if(!spy.stealthOn && spy.alive){	
			//Is the spy in view of the guard?
			if(!this.renderable.isCurrentAnimation('yawn') && this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .8 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				spy.caught();
				this.renderable.setCurrentAnimation('catch');
				//check side
				/*
				if(this.pos.x > spy.pos.x){
					this.flipX(false);
				}else{
					this.flipX(true);
				}
				*/

				//check side
				if(me.gamestat.getItemValue('currentMode') == 'ghost'){
					if(this.pos.x > spy.pos.x){
						this.flipX(true);
					}else{
						this.flipX(false);
					}
				}else{
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}
				}
			}			
		}
		
		if(spy.alive){
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 20 && spy.pos.x < this.pos.x + 12 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", .05 * me.timer.tick);
			}*/
			
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY)){
			if(this.colOverlaps(spy.collisionBox)){
				//console.log('Caught!');
				this.addHitSpy();
				spy.caught();
				this.renderable.setCurrentAnimation('catch');
				//check side
				/*
				if(this.pos.x > spy.pos.x){
					this.flipX(false);
				}else{
					this.flipX(true);
				}
				*/

				//check side
				if(me.gamestat.getItemValue('currentMode') == 'ghost'){
					if(this.pos.x > spy.pos.x){
						this.flipX(true);
					}else{
						this.flipX(false);
					}
				}else{
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}
				}

			}
		}else if(spy.isCaught){
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
			}
		}
		
		//If spy is in dangerzone and not cloaked, caught!
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
	
});

/* ---------------------
a security guard booth entity
----------------------*/

var GuardBoothEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.collidable = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x + 8;
		this.dangerZoneRight = x + settings.width - 8;
		
		//set up animations
		this.renderable.addAnimation('idle',[0,1,2],12);
		this.renderable.addAnimation('catch',[3,4],2);
		this.renderable.setCurrentAnimation('idle');
		
		
	},
	update: function(){
				
		if(!spy.stealthOn && spy.alive){	
			//Is the spy in view of the guard?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				spy.caught();
				this.renderable.setCurrentAnimation('catch');
			}			
		}		
		
		//If spy is in dangerzone and not cloaked, caught!
		this.parent(this);
		return true;
	}
	
});


/* ---------------------
a security guard entity
----------------------*/

var GuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		//Set Position and walking boundaries
		//Will Check for custom StartX and StopX from Tiled
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;				
		
		//Set up delay at end of walk cycle
		this.doDelay = false;
		this.stillTime = 60;
		this.isStill = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		this.noSFX = ( settings.noSFX ) ? true : false;
		
		//add animation
		this.renderable.addAnimation('walk', [0,1,2,3],7);		
		this.renderable.addAnimation('catch', [4]);
		this.renderable.addAnimation('stand', [3]);
		this.renderable.setCurrentAnimation('walk');
		this.renderable.addAnimation('alarmed',[5,6],60);
		this.animationspeed = me.sys.fps / 6;
		
		//Start on the right and make walk left
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.walkLeft = false;
			this.flipX(true);
			if(settings.startOffset) this.pos.x += settings.startOffset;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.walkLeft = true;
			this.flipX(false);
			if(settings.startOffset) this.pos.x -= settings.startOffset;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
				
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}

	},
	update: function(){
		if(this.removeImmediately){
			me.game.remove(this);
		}
		//var caught = false;
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//console.log(this.inViewport);
		
		if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){		
			if(this.walkLeft && this.pos.x <= this.startX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(true);
					this.walkLeft = false;
				}
			}else if(!this.walkLeft && this.pos.x >= this.endX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(false);
					this.walkLeft = true;
					
				}
			}
			
			//Delay here if set
			if(this.doDelay){
				if(this.isStill && this.stillTime > 0){
					this.stillTime -= 1;
				}else if(this.stillTime === 0){
					this.isStill = false;
					this.stillTime = 60;
					this.renderable.setCurrentAnimation('walk');
					if(this.walkLeft){
						this.flipX(true);
						this.walkLeft = false;
					}else if(!this.walkLeft){
						this.flipX(false);
						this.walkLeft = true;
					}
				}
			}	
		}
		
		if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed') && !this.isStill){
			this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
			if(!this.noSFX && (this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2)) me.audio.play('guardstep', false, null, 0.4);
		}else{
			this.vel.x = 0;
		}
		
		this.updateMovement();
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		if(spy.alive){
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.renderable.setCurrentAnimation('catch');
						//check side 
						/*
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
						*/

						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					//console.log('Caught!');
					this.addHitSpy();
					spy.caught();
					this.renderable.setCurrentAnimation('catch');
					
					//check side
					if(me.gamestat.getItemValue('currentMode') == 'ghost'){
						if(this.pos.x > spy.pos.x){
							this.flipX(true);
						}else{
							this.flipX(false);
						}
					}else{
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
					}

				}
			}
		}else if(spy.isCaught){	
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
			}
		}
		
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
});


/* ---------------------
a security guard entity that stops when under a motion sensor
----------------------*/

var MotionSensorGuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		//Set Position and walking boundaries
		//Will Check for custom StartX and StopX from Tiled
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;				
		
		//Set up delay at end of walk cycle
		this.doDelay = false;
		this.stillTime = 60;
		this.isStill = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		this.noSFX = ( settings.noSFX ) ? true : false;
		
		//add animation
		this.renderable.addAnimation('walk', [0,1,2,3],7);		
		this.renderable.addAnimation('catch', [4]);
		this.renderable.addAnimation('stand', [7]);
		this.renderable.setCurrentAnimation('walk');
		this.renderable.addAnimation('alarmed',[5,6],60);
		this.animationspeed = me.sys.fps / 6;
		
		//Start on the right and make walk left
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.walkLeft = false;
			this.flipX(true);
			if(settings.startOffset) this.pos.x += settings.startOffset;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.walkLeft = true;
			this.flipX(false);
			if(settings.startOffset) this.pos.x -= settings.startOffset;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
		
		//Motion Sensors to Check
		this.gotMotionSensors = false;
		this.motionSensors;
		this.sensorNames = settings.sensorNames;
		this.motionSensorsLength = 0;
	},
	update: function(){
		
		if(!this.gotMotionSensors){
			this.motionSensors = me.game.getEntityByProp('sensorName',this.sensorNames);
			this.gotMotionSensors = true;
			this.motionSensorsLength = this.motionSensors.length;			
		}
			
		//var caught = false;
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//console.log(this.inViewport);
		
		if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){		
			if(this.walkLeft && this.pos.x <= this.startX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(true);
					this.walkLeft = false;
				}
			}else if(!this.walkLeft && this.pos.x >= this.endX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(false);
					this.walkLeft = true;
					
				}
			}
			
			//Delay here if set
			if(this.doDelay){
				if(this.isStill && this.stillTime > 0){
					this.stillTime -= 1;
				}else if(this.stillTime === 0){
					this.isStill = false;
					this.stillTime = 60;
					this.renderable.setCurrentAnimation('walk');
					if(this.walkLeft){
						this.flipX(true);
						this.walkLeft = false;
					}else if(!this.walkLeft){
						this.flipX(false);
						this.walkLeft = true;
					}
				}
			}	
		}
		
		//check for overlap with sensors
		var collidingWithOneMotionSensor = false;
		if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){
			for(var i = 0; i < this.motionSensorsLength; i++){
					
				//if(this.colOverlaps(this.motionSensors[i].collisionBox) && !collidingWithOneMotionSensor){
				if(this.pos.y <= this.motionSensors[i].pos.y + 4){
					collidingWithOneMotionSensor = true;
					//console.log('colliding with a sensor ' + this.motionSensors[i].pos.y + ' g: '  + this.pos.y);
				}else{
					collidingWithOneMotionSensor = false;				
					//console.log('not colliding with a sensor ' + this.motionSensors[i].pos.y + ' g: '  + this.pos.y);
				}
			}
			if(collidingWithOneMotionSensor){
				this.isStill = true;
				this.renderable.setCurrentAnimation('stand');
			}else{
				this.isStill = false;			
				this.renderable.setCurrentAnimation('walk');
			}
		}else{
			this.isStill = true;
		}
		
		if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed') && !this.isStill){
			this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
			if(!this.noSFX && (this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2)) me.audio.play('guardstep', false, null, 0.4);
		}else{
			this.vel.x = 0;
		}
		
		this.updateMovement();
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		if(spy.alive){
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.renderable.setCurrentAnimation('catch');
						//check side
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					//console.log('Caught!');
					this.addHitSpy();
					spy.caught();
					this.renderable.setCurrentAnimation('catch');
					//check side
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}

				}
			}
		}else if(spy.isCaught){	
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
			}
		}
		
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
});

/* ---------------------
a guard dog entity
----------------------*/

var GuardDogEntity = enemyEntity.extend({
	init: function(x,y,settings){
		//console.log('dog');
		this.parent(x,y,settings);
		//Set Collision Rect
		this.updateColRect(7,18,8,24);
		
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.setVelocity(3,7.5);
			this.setMaxVelocity(3,7.5);
		}else{

			this.setVelocity(4,7.5);
			this.setMaxVelocity(4,7.5);
		}
		
		//Set Post Position		
		//Set Run Boundaries
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;		
		
		//Set Danger Zone
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Animations
		this.renderable.addAnimation('catch',[0,1], 8);
		
		this.renderable.addAnimation('lunge',[8], 12);
		
		this.renderable.addAnimation('alarmed',[0,1], 8);
		this.renderable.addAnimation('lookForward',[0,1], 8);
		this.renderable.addAnimation('lookBackward',[2,3], 8);
		this.renderable.addAnimation('chase',[4,5,6,7],2);
		this.renderable.addAnimation('trot',[4,5,6,7],4);
		//Set FlipX
		this.watchCounter = 120;
		this.chaseCounter = 30;
		this.isChasing = false;
		this.returningToPost = false;
		this.atPost = true;
		this.lookForward = true;
		this.bark = false;
		this.caught = false;
		this.renderable.setCurrentAnimation('lookForward');
		
		//check start side
		if(settings.startSide == 'left'){
			this.startPosX = this.startX;
			this.pos.x = this.startPosX;
			this.walkLeft = false;
			this.flipX(true);
		}else{
			this.startPosX = this.endX;
			this.pos.x = this.startPosX;
			this.walkLeft = true;
			this.flipX(false);
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
	},
	update: function(){
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//Dog looks left and right
		
		if(this.watchCounter > 0  && !this.isChasing && !this.returningToPost){
				this.watchCounter -= me.timer.tick;
		}else if(this.watchCounter <= 0 && !this.isChasing && !this.returningToPost){
			this.watchCounter = 120;
			if(this.lookForward){
				this.renderable.setCurrentAnimation('lookBackward');
				this.lookForward = false;
			}else if(!this.lookForward){
				this.renderable.setCurrentAnimation('lookForward');
				this.lookForward = true;
			}
		}
		
		//if spy is in danger zone, run the direction of the spy
		if(spy.alive && !this.caught){
			//is Spy close to the dog?
			/*
			if(spy.pos.x > this.pos.x - 52 && spy.pos.x < this.pos.x + 44 && 
				spy.pos.y > this.pos.y - 20 && spy.pos.y < this.pos.y + 20){
				me.gamestat.updateValue("dangerCountTemp", 2 * me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			//Is the spy in view of the dog?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				//Which way should the dog run?
				if(!this.bark){
					me.audio.play("dogbark",false,null,.3); 
					this.bark = true;
				}
				
				if(spy.pos.x < this.pos.x){
					//Run Left
					this.vel.x -= this.accel.x * me.timer.tick;
					this.flipX(false);
				}else if(spy.pos.x > this.pos.x){
					//Run Right
					this.vel.x += this.accel.x * me.timer.tick;
					this.flipX(true);
				}		
				this.isChasing = true;
				this.renderable.setCurrentAnimation('chase');
				
			}else{
				//Continue chasing for a few more frames if was chasing
				if(this.isChasing){
					if(this.chaseCounter > 0){
						if(this.pos.x < this.dangerZoneLeft || this.pos.x > this.dangerZoneRight){
							this.chaseCounter = 0;
						}else{
							this.chaseCounter -= 1 * me.timer.tick;
						}
					}else{
						this.isChasing = false;
						this.chaseCounter = 30;
						//go back to post
						this.returningToPost = true;
					}					
				}
			}
			
			if(this.returningToPost && !this.isChasing){
				//If x pos not at start position
				this.renderable.setCurrentAnimation('trot');
				if(this.pos.x > this.startPosX + 4){	
					this.vel.x = -1.5 * me.timer.tick;
					this.flipX(false);
				}else if(this.pos.x < this.startPosX - 4){
					this.vel.x = 1.5 * me.timer.tick;
					this.flipX(true);
				}else{
					this.bark = false;
					this.vel.x = 0;
					//Snap to start pos
					this.pos.x = this.startPosX;
					this.returningToPost = false;
					this.renderable.setCurrentAnimation('lookForward');
					this.watchCounter = 120;
				}
			}
		}else if(spy.isCaught || this.caught){	
			//console.log('Dog Dog!');
			if(!this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}
			/*
			if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}else if(this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.vel.x = 0;
				this.isChasing = false;
			}else{
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}
			*/
		}

		this.updateMovement();
		//if spy collides with dog, caught!
		//var res = me.game.collide(this);
		
		//if(res && res.obj.type == me.game.SPY && spy.alive){
		if(spy.alive && this.colOverlaps(spy.collisionBox) && !this.caught){
			//console.log('caught');
			if( !this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('lunge','catch');
			}
			
			this.isChasing = false;
			this.caught = true;
			//spy.caught();
			
			if(this.pos.x + 8 > spy.pos.x){
				var direction = 'right';
			}else{
				var direction = 'left';
			}
			
			spy.caughtKnockedDown(direction);
			
		}
		
		
		this.parent(this);
		return true;
		
	}
});



/* ---------------------
a tiger entity

works like this:
	has start position, end position and direction
	builds up spring tension for a split second)
	pounces (a jump through the air, quicker than dog)
	lands and flip's x
	repeat
	
	idea is that the player will have to trigger the tiger to get to a key the tiger is guarding

	TODO: check the spy's x pos 
	TODO: instead of using startx and endx, use where the spy last was
	
----------------------*/

var TigerEntity = enemyEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		
		this.enemyName = (settings.enemyName) ? settings.enemyName : 'tiger';
		
		//Set Collision Rect
		
		this.updateColRect(16,32,4,28);
		//Customize collision rectangle based of of side the tiger faces.
		
		this.anchorPoint.set(0,0);
		
		

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.setVelocity(6,7.5);
			this.setMaxVelocity(6,7.5);
		}else{
			this.setVelocity(8,7.5);
			this.setMaxVelocity(8,7.5);
		}

		
		
		//Set Post Position		
		//Set Run Boundaries
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;
		
		//Set Danger Zone
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		this.pounceX = 0;
		
		//Animations
		this.renderable.addAnimation('lounge',[0,1,2,1], 12);
		this.renderable.addAnimation('alert',[3,4,5], 8);
		this.renderable.addAnimation('pounce',[9],2);
		this.renderable.addAnimation('charge',[6,7,8],4);

		this.renderable.setCurrentAnimation('lounge');
		
		this.isCharging = false;
		this.isPouncing = false;
		this.isLounging = true;
		this.overshot = false;
		this.roar = false;

		this.caught = false;
		
		this.autoPounce = false;
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.chargeTime = 20;
			this.autoPounce = true;
		}else{
			this.chargeTime = 15;
		}
		this.chargeCounter = 0;
		
		//check start side
		if(settings.startSide == 'left'){
			this.startPosX = this.startX;
			this.pos.x = this.startPosX;
			this.pounceLeft = false;
			this.flipX(true);
		}else{
			this.startPosX = this.endX;
			this.pos.x = this.startPosX;
			this.pounceLeft = true;
			this.flipX(false);
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.pounceLeft;
	},
	update: function(){
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		
		
		//if spy is in danger zone, charge and then pounce in the direction of the spy
		if(spy.alive && !this.caught){

			//Is the spy in view of the tiger?
			if(this.autoPounce){

				if(!this.isCharging && this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
					
					if(this.isLounging){
						this.isCharging = true;
						this.isLounging = false;
					}

					
					
					//
					this.pounceX = spy.pos.x;
					
					//
					if(this.pos.x <= this.pounceX){
						this.pounceLeft = false;
						this.flipX(true);
					}else{
						this.pounceLeft = true;
						this.flipX(false);
					}
					
					
				}

				//Do the charging outside of the initial charge check
				if(this.isCharging){					
					if(this.chargeCounter < this.chargeTime){
						this.renderable.setCurrentAnimation('charge');
						this.chargeCounter += 1 * me.timer.tick;
					}else{
						//console.log(this.chargeCounter);
						this.chargeCounter = 0;
						this.isCharging = false;
						this.isPouncing = true;
					}				
				}

			}else{
			
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
					
					if(this.isLounging){
						this.isCharging = true;
						this.isLounging = false;
					}

					if(this.isCharging){					
						if(this.chargeCounter < this.chargeTime){
							this.renderable.setCurrentAnimation('charge');
							this.chargeCounter += 1 * me.timer.tick;
						}else{
							//console.log(this.chargeCounter);
							this.chargeCounter = 0;
							this.isCharging = false;
							this.isPouncing = true;
						}				
					}
					
					//
					this.pounceX = spy.pos.x;
					
					//
					if(this.pos.x <= this.pounceX){
						this.pounceLeft = false;
						this.flipX(true);
					}else{
						this.pounceLeft = true;
						this.flipX(false);
					}
					
					
				}else{
					if(!this.isPouncing){
						this.isLounging = true;
						this.renderable.setCurrentAnimation('lounge');
					}
				}
			}
			
			//When pouncing, tiger doesn't stop until it reaches it's end pos x
			if(this.isPouncing){
				//console.log('pounce');
				if(!this.roar){
					me.audio.play("tigerroar",false,null,.5); 
					this.roar = true;
				}
				this.renderable.setCurrentAnimation('pounce');
				
				//check start/end x pos, stop pounce there
				if(this.pounceLeft){
					if(this.pos.x <= this.pounceX - 8 || this.overshot){ //overshoot by a little here?
						this.pounceLeft = false;
						this.vel.x = 0;
						this.flipX(true);
						this.renderable.setCurrentAnimation('lounge');
						this.isLounging = true;
						this.isPouncing = false;
						this.overshot = false;
						this.roar = false;
					}else{
						this.vel.x -= this.accel.x * me.timer.tick;
						//this.flipX(false);
						//console.log(this.vel.x);
					}
				}else{
					if(this.pos.x >= this.pounceX + 8 || this.overshot){
						this.pounceLeft = true;
						this.vel.x = 0;
						this.flipX(false);
						this.renderable.setCurrentAnimation('lounge');
						this.isLounging = true;
						this.isPouncing = false;
						this.overshot = false;
						this.roar = false;
					}else{
						this.vel.x += this.accel.x * me.timer.tick;
						//this.flipX(true);						
					}
				}				
			}			
		}else{
			//if(!this.isPouncing){
				this.renderable.setCurrentAnimation('alert');
				this.vel.x = 0;
			//}
		}
		
		//Move and check to see if colliding with wall
		var collision = this.updateMovement();
		if(collision.x && collision.xprop.isSolid){
			this.overshot = true;
		}
		
		
		//Roll my own collision here
		if(spy.alive && this.colOverlaps(spy.collisionBox) && !this.caught){
			//console.log('caught');
			this.renderable.setCurrentAnimation('alert');
			this.vel.x = 0;
			this.isChasing = false;
			
			if(this.pos.x + 16 > spy.pos.x){
				var direction = 'right';
			}else{
				var direction = 'left';
			}
			
			this.caught = true;
			spy.caughtKnockedDown(direction);
		}
		/*
		var res = me.game.collide(this);
		
		if(res && res.obj.type == me.game.SPY && spy.alive){
			console.log('caught');
			this.renderable.setCurrentAnimation('alert');
			this.vel.x = 0;
			this.isChasing = false;
			
			if(this.pos.x + 16 > spy.pos.x){
				var direction = 'right';
			}else{
				var direction = 'left';
			}
			
			spy.caughtKnockedDown(direction);
		}
		
		*/
		this.parent(this);
		return true;
		
	}/*,
	colOverlaps : function(r)	{
		return (this.collisionBox.left < r.right && 
		r.left < this.collisionBox.right && 
		this.top < r.bottom &&
		r.top < this.collisionBox.bottom);
	}*/
});


/* ---------------------
a security camera entity
----------------------*/
var SecurityCameraEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		//position camera
		this.anchorPoint.set(0,0);
		
		this.alwaysUpdate = true;
		
		this.pos.x = (!settings.offSetX) ? x : x + settings.offSetX;
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x + (settings.spritewidth * 2);
		this.dangerZoneRight = x + settings.width;
		
		//Set up delay before turning
		this.doDelay = true;
		this.stillTime = 180;
		this.isStill = false;
		
		this.delayCounter = 1;
		this.delayTime = 180;
		//this.delayTime = 90;
		
		if(settings.startSide == 'right'){
			this.lookLeft = false;
			this.startSide = false;
		}else{
			this.lookLeft = true;
			this.startSide = true;
		}
		this.flipX(this.lookLeft);
		
		//Animations
		this.animationspeed = me.sys.fps / 6;
		this.renderable.addAnimation('stationary',[0],0);
		this.renderable.addAnimation('blink',[0,1],4);
		this.renderable.addAnimation('solid',[1],4);
		this.renderable.addAnimation('rotate',[2],8);
		this.renderable.setCurrentAnimation('stationary');

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update:function(){
		if(this.removeImmediately){
			me.game.remove(this);
		}
		if(ScreenTransitionStart && !this.inViewport){ 
			this.lookLeft = this.startSide;
			this.flipX(this.lookLeft);
			this.delayCounter = 1;
			this.renderable.setCurrentAnimation('stationary');
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
			
			//if(!this.inViewport) return false;
			if(this.delayCounter == 90){
				//console.log('Camera: ' + this.delayCounter + ' ' + me.timer.getTime());
			}
			
			if(this.delayCounter < this.delayTime){
				this.delayCounter += 1 * me.timer.tick;
				if(this.delayCounter > 80){
					if(this.delayCounter > 120){
						this.renderable.setCurrentAnimation('solid');
					}else{
						this.renderable.setCurrentAnimation('blink');
					}
				}
			}else{
				//console.log('Camera: ' + this.delayCounter + ' ' + me.timer.getTime());
				//Check if it should open or close
				this.delayCounter = 1;
				
				if(this.lookLeft){
					this.flipX(false);
					this.lookLeft = false;
				}else if(!this.lookLeft){
					this.flipX(true);
					this.lookLeft = true;
				}
				//console.log('Camera flip');
				me.audio.play("cameraturn",false, null, 0.3); 
				this.renderable.setCurrentAnimation('rotate','stationary');
			}
			
			/*
			//Delay here if set
			if(this.doDelay){
				
				if(this.stillTime > 0){
					this.stillTime -= me.timer.tick;
					if(this.stillTime < 80){
						if(this.stillTime < 40){
							this.renderable.setCurrentAnimation('solid');
						}else{
							this.renderable.setCurrentAnimation('blink');
						}
					}
				}else if(this.stillTime <= 0){
					this.stillTime = 180;
					if(this.lookLeft){
						this.flipX(false);
						this.lookLeft = false;
					}else if(!this.lookLeft){
						this.flipX(true);
						this.lookLeft = true;
					}
					console.log('Camera flip');
					me.audio.play("cameraturn"); 
					this.renderable.setCurrentAnimation('rotate','stationary');
				}
			}	
			*/
				
			//check to see if spy is in view of the camera (if spy is not invisible)
			if(!spy.stealthOn && spy.alive && !this.renderable.isCurrentAnimation('rotate')){	
				//Is the spy in view of the camera?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
					//Create a deadzone under the camera and if the camera is not looking at the spy
					if((this.lookLeft && (spy.pos.x <= (this.pos.x - this.width))) || (!this.lookLeft && (spy.pos.x >= (this.pos.x + this.width)))){
						spy.caught();
					}
				}
			}
			
			this.parent(this);
			return true;
		}
	}
});

/* ---------------------
a security camera bot entity
----------------------*/

var OldSecurityCameraBotEntity = SecurityCameraEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.setVelocity(.4,0);
		this.setMaxVelocity(.4,0);
		this.gravity = 0;
		this.startX = x;
		this.endX = x + settings.width - settings.spritewidth;
		this.walkLeft = false;
		this.pos.y += 4;
		this.hoverCounter = 0;
		this.hoverUp = true;
		this.renderable.addAnimation('stationary',[0,1],2);
		this.renderable.addAnimation('blink',[3,4],2);
		this.renderable.addAnimation('rotate',[2],8);
		
		this.renderable.setCurrentAnimation('stationary');
		
		if(settings.startSide == 'right'){
			this.pos.x = x + settings.width - settings.spritewidth;
			this.walkLeft = true;
		}else{
			this.pos.x = x;
			this.walkLeft = false;
		}
		
		
	},update:function(){
		//console.log(this.pos.x);
		//move back and forth
		if (this.walkLeft && Math.floor(this.pos.x) <= this.startX) {
			this.walkLeft = false;
		} else if (!this.walkLeft && Math.ceil(this.pos.x) >= this.endX) {
			this.walkLeft = true;
		}
		
		//step through moving on y
		if(this.hoverUp){
			this.pos.y += .1 * me.timer.tick;
			this.hoverCounter += me.timer.tick;
			if(this.hoverCounter >= 30){
				this.hoverUp = false;
			}
		}else if(!this.hoverUp){
			this.pos.y -= .1 * me.timer.tick;
			this.hoverCounter -= me.timer.tick;
			if(this.hoverCounter <= 0){
				this.hoverUp = true;
			}
		}
		
		
		this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
		this.updateMovement();
		
		this.updateMovement();
		this.parent(this);
		return true;
	}	
});

/* ---------------------
a security bot entity
----------------------*/
var OldSecurityBotEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.setVelocity(2,2);
		this.collidable = false;
		this.updateColRect(2,settings.spritewidth-4,2,settings.spritewidth-4);
		this.gravity = 0;
		this.botType = (!settings.bottype) ? false : settings.bottype;
		//Start with box/perimeter movement	
		//Will Check for custom StartX and StopX from Tiled
		
		this.marginLeft = (!settings.marginLeft) ? 0 : settings.marginLeft;
		this.marginRight = (!settings.marginRight) ? 0 : settings.marginRight;
		this.marginTop = (!settings.marginTop) ? 0 : settings.marginTop;
		this.marginBottom = (!settings.marginBottom) ? 0 : settings.marginBottom;
		
		//Start X and Start Y
		//End X and End Y
		//this.startX = x + this.marginLeft;
		//this.endX = x + settings.width - settings.spritewidth - this.marginRight;		
		
		//These are the overall bounding box
		this.startX = x;		
		this.endX = x + settings.width - settings.spritewidth;		
		this.startY = y;
		this.endY = y + settings.height - settings.spritewidth;
		
		//These determine the box for which the bot moves in
		this.startXm = this.startX + this.marginLeft;		
		this.endXm = this.endX - this.marginRight;		
		this.startYm = this.startY + this.marginTop;
		this.endYm = this.endY - this.marginBottom;
		
		this.pos.x = this.startXm;
		this.pos.y = this.startYm;
		
		this.spritewidth = settings.spritewidth;
		this.spriteheight = settings.spriteheight;
		this.spritewidthA = settings.spritewidth / 2 ;
		this.spriteheightA = settings.spriteheight / 2;
		//
		this.walkLeft = false;
		this.walkUp = false;
		this.moveX = false;
		
		//set up animations
		this.renderable.addAnimation('moveX',[4,5,6,7],8);
		this.renderable.addAnimation('moveDown',[0,1,2,3]);
		
		this.doFlipY = false;
		if(this.botType == 'laser'){
			this.renderable.addAnimation('moveUp',[0,1,2,3]);
			this.doFlipY = true;
			
			//attach the laser beam
			//console.log(this.pos.x + 16);
			/*
			botBeam = new BotBeamEntity(this.pos.x + 16, this.pos.y + 7, {startX:x,endX:x + settings.width,startY:y,endY:y + settings.height,botwidth: settings.spritewidth});
			me.game.add(botBeam,4);
			me.game.sort();
				*/
				
		}else{
			
			this.renderable.addAnimation('moveUp',[8,9,10,11]);
		}	
		
		this.renderable.setCurrentAnimation('moveX');
		this.flipX(true);
	},
	update: function(){
		//Move around in a square pattern
		
		//Determine if it should be moving on the x axis or the y axis
		if(this.moveX && (this.pos.x <= this.startXm || this.pos.x >= this.endXm)){
			this.moveX = false;			
		}else if(!this.moveX && (this.pos.y <= this.startYm || this.pos.y >= this.endYm)){
			this.moveX = true;
		}
		
		//console.log(this.moveX,this.pos.x, this.startX, this.endX, this.pos.y, this.startY, this.endY);
		
		//Determine whether it should move left or right, up or down
		if(this.moveX){
			this.renderable.setCurrentAnimation('moveX');
			//set appropriate x and y vel
			if(this.walkLeft && this.pos.x <= this.startXm){
				this.flipX(true);
				this.walkLeft = false;
			}else if(!this.walkLeft && this.pos.x >= this.endXm){
				this.flipX(false);
				this.walkLeft = true;
			}
			this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
			this.vel.y = 0;
		}else{
			//set appropriate x and y vel
			if(this.walkUp && this.pos.y <= this.startYm){
				this.flipY(false);
				this.walkUp = false;
			}else if(!this.walkUp && this.pos.y >= this.endYm){
				//this.flipY(false);
				this.walkUp = true;
				this.flipY(this.doFlipY);
			}
			
			(this.walkUp) ? this.renderable.setCurrentAnimation('moveUp') : this.renderable.setCurrentAnimation('moveDown');
			
			this.vel.y += (this.walkUp) ? -this.accel.y * me.timer.tick : this.accel.y * me.timer.tick;
			//this.vel.y -= this.accel.y * me.timer.tick;
			this.vel.x = 0;
			//console.log(this.moveX);
			//console.log(this.vel.y);
		}		

		//If the spy is in bot's box, caught
		//If spy collides with bot, caught
		if(spy.alive){
			if(spy.stealthOn){
				//check for danger zone
			}
			
			//check for collision
			//var res = me.game.collide(this);
		
			//if(res && res.obj.type == me.game.SPY && spy.alive){
			if(this.colOverlaps(spy.collisionBox)){
				//console.log(res);
				spy.caught();
			}
			
		}else{
			
		}
	
		this.updateMovement();
		this.parent(this);
		return true;
	},draw: function(context){
		this.parent(context);
	},
	straightPattern: function(){
	},
	squarePattern: function(){
	}
});
/*
var LaserBotEntity = SecurityBotEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		//set up dangerzones
		this.dzX1 = 0;
		this.dzX2 = 0;
		this.dzY1 = 0;
		this.dzY2 = 0;
		
		this.flickerC = 0;
		this.flikcerColor = ['rgba(255,0,0,0.5)','rgba(224,0,0,0.9)'];
	},
	update: function(){
		//Custom Collision Here
		
		if(spy.alive){
			//
			if(!this.walkLeft && this.moveX){//if moving x at the top
				this.dzX1 = this.pos.x + this.spritewidth;
				this.dzX2 = this.endX + this.spritewidth;
				this.dzY1 = this.pos.y+this.spriteheightA;
				this.dzY2 = this.pos.y+this.spriteheightA;
			}else if(this.walkLeft && this.moveX){	//if moving x at the bottom
				this.dzX2 = this.pos.x;
				this.dzX1 = this.startX;
				this.dzY1 = this.pos.y+this.spriteheightA;
				this.dzY2 = this.pos.y+this.spriteheightA;
			}else if(this.walkUp && !this.moveX){//if moving y at the right
				this.dzX1 = this.pos.x+this.spriteheightA;
				this.dzX2 = this.pos.x+this.spriteheightA;
				this.dzY2 = this.pos.y;
				this.dzY1 = this.startY;
			}else if(!this.walkUp && !this.moveX){	//if moving y at the left
				this.dzX1 = this.pos.x+this.spriteheightA;
				this.dzX2 = this.pos.x+this.spriteheightA;
				this.dzY1 = this.pos.y + this.spriteheight;
				this.dzY2 = this.endY + this.spriteheight;
			}
		
			//console.log(this.dzX1,	this.dzX2, this.dzY1, this.dzY2);
			
			//Is the spy intersecting the laser?
			
			if(this.dzX1 < (spy.right - 4) && 
					(spy.left + 4) < this.dzX2 && 
			this.dzY1 < (spy.bottom - 4) &&
			((spy.top + 4) < this.dzY2)){
				spy.caught();			
			}
		}
		
		this.parent(this);
		return true;
	},draw: function(context){
		this.parent(context);
		context.beginPath();
		context.lineWidth = 2;
		
		if(!this.walkLeft && this.moveX){//if moving x at the top
			context.moveTo(this.pos.x + this.spritewidth - 2,this.pos.y+this.spriteheightA); 
			context.lineTo(this.endX + this.spritewidth,this.pos.y+this.spriteheightA); 
		}else if(this.walkLeft && this.moveX){	//if moving x at the bottom
			context.moveTo(this.pos.x + 2,this.pos.y+this.spriteheightA); 
			context.lineTo(this.startX,this.pos.y+this.spriteheightA); 
		}else if(this.walkUp && !this.moveX){//if moving y at the right
			context.moveTo(this.pos.x+this.spriteheightA,this.pos.y + 2); 
			context.lineTo(this.pos.x+this.spriteheightA,this.startY); 
		}else if(!this.walkUp && !this.moveX){	//if moving y at the left
			context.moveTo(this.pos.x+this.spriteheightA,this.pos.y + this.spriteheight - 2); 
			context.lineTo(this.pos.x+this.spriteheightA,this.endY + this.spriteheight); 
		}
		
		//#fb2c2c
		this.flickerC = 1 - this.flickerC;
		context.strokeStyle = this.flikcerColor[this.flickerC];
		//console.log(this.flikcerColor[this.flickerC]);
		context.stroke();  
		context.closePath();
	}
});

*/

/* ---------------------
a security beam entity
----------------------*/
var SecurityBeamEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		//this.updateColRect(4,8,2,28);
		//New Collision to account for extra pixel
		this.updateColRect(5,6,2,28);
		//Needs to be faster than invisible speed of spy
		//this.setVelocity(2.5,0);

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.setVelocity(2,0);

		}else{
			this.setVelocity(2.5,0);

		}
		
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.startDelayCounter = 0;
		
		//Set it up to move back and forth
		this.startX = x;
		this.endX = x + settings.width - settings.spritewidth;		
		
		if(settings.startSide == 'left'){
			this.pos.x = this.startX;
			this.walkLeft = false;
		
		}else{
			this.pos.x = x + settings.width - settings.spritewidth;
			this.walkLeft = true;
		}
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		this.renderable.addAnimation('beam', [0]);


		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
				
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update:function(){
		if(this.removeImmediately){
			me.game.remove(this);
		}
		//if(this.resetCheck(this.startPosX,this.startPosY, false)) return false;
		
		if(ScreenTransitionStart && !this.inViewport){ 
			this.pos.x = this.startPosX;
			this.moveUp = this.startMoveUp; 
			this.parent(this);
			return true;
		}
		
		
		/*
		if(!ScreenTransitionState && !this.inViewport){
			this.parent(this);
			return true;
		}
		*/
		//Start Delay
		if(this.startDelay){
			this.startDelayCounter += me.timer.tick;
			if(this.startDelayCounter < this.startDelay){
				this.parent(this);
				return true;
			}else{
				this.startDelay = false;
			}
		}
		
		
		//move back and forth
		if (this.walkLeft && this.pos.x <= this.startX) {
			this.walkLeft = false;
			if(this.inViewport){ me.audio.play('securitybeamsfx',false, null, 0.3); }
		} else if (!this.walkLeft && this.pos.x >= this.endX) {
			this.walkLeft = true;
			if(this.inViewport){ me.audio.play('securitybeamsfx',false, null, 0.3); }
		}
		
		this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
		this.updateMovement();
		
		//var res = me.game.collide(this);
		
		//if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
		if(spy.alive && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			
			if(this.walkLeft){
				direction = 'right';
			}else{
				direction = 'left';
			}
			
			if(me.gamestat.getItemValue('currentMode') != 'ghost'){
				me.audio.play('electricspark');
			}
			spy.caughtBeam(direction);
			
			//spy.caught();
		}
		
		this.parent(this);
		return true;
		
	}
});

/* ---------------------
a pressure plate entity
----------------------*/
var PressurePlateEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.updateColRect(2,12,-4,4);
		this.pressureSen = 50;
		this.pressureCount = 0;
		this.renderable.addAnimation('normal',[0]);
		//this.renderable.addAnimation('armed',[0,2,0,3,0,4,0]);
		this.renderable.addAnimation('armed',[1,2,3,4,5,6,7]);
		this.renderable.addAnimation('triggered',[0,7])
		
		//this.isSet = false;
		this.isArmed = false;
		this.isTriggered = false;
		this.renderable.setCurrentAnimation('normal');
		this.animationSpeed = me.sys.fps / 3;


		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
				
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update:function(){
		if(this.removeImmediately){
			me.game.remove(this);
		}
		//Check for Collision with spy if spy is alive
		if(spy.alive){
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY)){
			if(this.colOverlaps(spy.collisionBox)){
				if(!this.isArmed && !this.isTriggered){
					//Some good sounds here would be good
					this.isArmed = true;
					this.renderable.setCurrentAnimation('armed');
					this.renderable.setAnimationFrame(0);
					me.audio.play('pressureplatesfx');
				}else{
					this.pressureCount += 1 * me.timer.tick;
					if(this.pressureCount % 6 == 0){
						me.audio.play('pressureplatesfx');
					}
				}
				//If pressure sensitivity is reach or if the spy landed on this, trigger
				if(this.pressureCount >= this.pressureSen || spy.wasFalling){
					this.isTriggered = true;
					this.renderable.setCurrentAnimation('triggered');
					if(me.gamestat.getItemValue('currentMode') != 'ghost'){
						me.audio.play('electricspark');
					}
					//spy.caught();
					spy.caughtBeam('left');
				}
			}else{
				//Maybe build in a cool down time
				this.isArmed = false;
				this.pressureCount = 0;
				this.renderable.setCurrentAnimation('normal');
			}
		}
		this.parent(this);
		return true;
	}
});

/* ---------------------
a motion sensor entity
----------------------*/
var MotionSensorEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.updateColRect(2,28,0,1);
		this.alwaysUpdate = true;

		this.playSFX = (settings.playSFX) ? settings.playSFX : false;
		
		this.sensorName = (settings.sensorName) ? settings.sensorName : false;
		
		//Needs to be faster than invisible speed of spy
		this.setVelocity(0,.5);
		this.gravity = 0;
		//Set it up to move back and forth
		this.startX = x;
		this.endX = x + settings.width;
		this.midX = x + 16;
		this.startY = y + 2;
		this.endY = y + settings.height - settings.spriteheight;
		if(settings.startPos == 'top'){
			this.pos.y = y;
			this.startMoveUp = this.moveUp = false;
		
		}else{
			this.pos.y = y + settings.height - settings.spriteheight;
			this.startMoveUp = this.moveUp = true;
		}
		
		this.startPosY = this.pos.y;
		
		//this.renderable.flicker();
		
		this.flickerC = 0;
		//this.flikcerColor = ['rgba(255,0,0,0.05)','rgba(224,0,0,0.2)'];
		this.flikcerColor = ['rgba(224,0,0,0.4)','rgba(224,0,0,0.3)'];
		
		//this.renderable.addAnimation('beam', [0,1]);
		//this.renderable.setCurrentAnimation('beam');
		
		this.transitioning = false;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update:function(){
		if(this.removeImmediately){
			me.game.remove(this);
		}
		//move up and down
		//	
		
		//need to do a reset when screen starts to transition if it's not in the viewport when the transition starts
		//ScreenTransitionState
		//ScreenTransitionStart
		if(ScreenTransitionStart && !this.inViewport){ 
			//console.log('motion sensor reset');
			this.pos.y = this.startPosY;
			this.moveUp = this.startMoveUp; 
			this.parent(this);
			return true;
		}
		
		if (this.moveUp && this.pos.y <= this.startY) {
			this.moveUp = false;
			if(this.inViewport && this.playSFX){ me.audio.play('motionsensorsfx'); }
		} else if (!this.moveUp && this.pos.y >= this.endY) {
			this.moveUp = true;
			if(this.inViewport && this.playSFX){ me.audio.play('motionsensorsfx'); }
		}
		
		this.vel.y += (this.moveUp) ? -this.accel.y * me.timer.tick : this.accel.y * me.timer.tick;
		this.updateMovement();
		
		//var res = me.game.collide(this);
		
		if(spy.alive && spy.moving && this.colOverlaps(spy.collisionBox)){
			spy.caught();
		}
		
		this.parent(this);
		return true;
		
	},
	draw: function(context){
		this.parent(context);
		this.flickerC = 1 - this.flickerC;
		
		//main beam
		/* We'll use this if we decide to get rid of the old beam
		context.beginPath();
		context.lineWidth = 1;			
		context.moveTo(this.endX, this.pos.y); 
		context.lineTo(this.pos.x, this.pos.y);			
		context.strokeStyle = this.flikcerColor[this.flickerC];
		context.stroke();  
		context.closePath();
		*/
		
		/*
		//Left Side
		context.beginPath();
		context.lineWidth = 1;			
		context.moveTo(this.midX, this.startY); 
		context.lineTo(this.pos.x, this.pos.y);			
		context.strokeStyle = this.flikcerColor[this.flickerC];
		context.stroke();  
		context.closePath();
		
		//Right Side
		context.beginPath();
		context.lineWidth = 1;			
		context.moveTo(this.midX, this.startY); 
		context.lineTo(this.pos.x + 32, this.pos.y);			
		context.strokeStyle = this.flikcerColor[this.flickerC];
		context.stroke();  
		context.closePath();
		*/
		
		//Let's draw a triangle
		if(this.inViewport){
			context.fillStyle = this.flikcerColor[this.flickerC];
			context.beginPath();
			context.moveTo(this.midX, this.startY);
			context.lineTo(this.pos.x, this.pos.y);	
			context.lineTo(this.pos.x + 32, this.pos.y);	
			context.moveTo(this.midX, this.startY);
			context.strokeStyle = this.flikcerColor[this.flickerC];
			context.stroke();  
			context.closePath();
			context.fill();
		}

	}
});

/* ---------------------
a motion sensor monitor entity
----------------------*/
var MotionSensorMonitorEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.pos.x += 8;
		this.renderable.addAnimation('monitor', [0,1,2,3,4,5,6,7,8,9]);
		this.renderable.setCurrentAnimation('monitor');
	},
	update:function(){
		this.parent(this);
		return true;
		
	}
});


/* ---------------------
a assassin strike entity
----------------------*/

var AssassinAttackEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 48;
		//this.type = 'JUMPDUST';
		this.collidable = false; 
		//this.gravity= (0);
		this.parent(x,y,settings);
		this.updateColRect(36,12,10,22);
		this.renderable.addAnimation('attack', [0,1,2,3,4,5,6,7,8],2);
		this.renderable.addAnimation('disappear', [8]);
		if(settings.direction == 'right'){
			this.flipX(false);
			this.moveIncrement = 16;
		}else{
			this.flipX(true);
			this.moveIncrement = -16;
		}
		this.attacked = false;
		this.renderable.setCurrentAnimation("attack", "disappear");
		
		me.audio.play('ninjakillsfx');
		
	},
	update: function(){
		if(!this.attacked && this.renderable.getCurrentAnimationFrame() == 1){
			this.pos.x+=this.moveIncrement;
			this.attacked = true;
		}
		this.parent(this);
		return true;
	}
});


/* ---------------------
an assassin entity
----------------------*/
var AssassinEntity = enemyEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		//start position
		//danger zone
		this.isCloaked = true;
		this.sawSpy = false;
		//Set Collision Rect
		//this.updateColRect(7,18,8,24);
		this.updateColRect(10,12,10,22);
		
		this.setVelocity(1,7.5);
		this.setMaxVelocity(1,7.5);
		
		if(settings.image == 'vr_assassin'){
			this.killSprite = 'vr_assassinkill';
		}else{
			this.killSprite = 'assassinkill';
		}
		
		//Set Post Position		
		//Set walk Boundaries
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;		
		
		//Set Danger Zone
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Animations
		this.renderable.addAnimation('uncloak',[9,8,7,6],4);
		this.renderable.addAnimation('cloak',[6,7,8,9,10],4);
		this.renderable.addAnimation('stalk',[0,1,2,3,4,5],8);
		this.renderable.addAnimation('stand',[0],8);
		this.renderable.addAnimation('cloaked',[10,10,10,10,10,10,10,10,10,10,11,12,13,14,15,14,13,12,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,],2);
		
		this.renderable.setCurrentAnimation('cloaked');
		
		//Set FlipX
		this.flipX(false);
		
		if(settings.startSide == 'left'){
			this.pos.x = this.startX;
			this.walkLeft = false;
		
		}else{
			this.pos.x = this.endX;
			this.walkLeft = true;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
				
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		if(this.resetCheck(this.startPosX,this.startPosY,false)) return false;		
		
		//if spy is in danger zone, run the direction of the spy
		if(spy.alive){
			
			//Is the spy in view of the assassin?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				if(!spy.stealthOn){
					this.sawSpy = true;
				}
				//Is the Spy facing the assassin?
				if( (this.pos.x > spy.pos.x && !spy.currentDirection) || (this.pos.x < spy.pos.x && spy.currentDirection)){
					//check to see if cloaked, uncloak and stalk
					if(this.isCloaked){
						me.audio.play('uncloak');
						this.renderable.setCurrentAnimation('uncloak','stalk');
						this.isCloaked = false;
					}
					
					if(!this.renderable.isCurrentAnimation('uncloak')){
					
						if(spy.pos.x < this.pos.x){
							//Run Left
							this.vel.x -= this.accel.x * me.timer.tick;
							this.flipX(true);
						}else if(spy.pos.x > this.pos.x){
							//Run Right
							this.vel.x += this.accel.x * me.timer.tick;
							this.flipX(false);
						}
					
					}
				
				}else{
					//check to see if not cloaked, cloak
					if(!this.isCloaked){
						me.audio.play('cloak');
						this.renderable.setCurrentAnimation('cloak',function(){
								this.renderable.setCurrentAnimation('cloaked');
								this.renderable.setAnimationFrame(0);
						}.bind(this));
					}
					this.isCloaked = true;
					
					this.vel.x = 0;
				}				
				
			}else{
				//cloak up
				//check to see if not cloaked, cloak
				if(!this.isCloaked){
					this.renderable.setCurrentAnimation('cloak',function(){
								this.renderable.setCurrentAnimation('cloaked');
								this.renderable.setAnimationFrame(0);
						}.bind(this));
					this.isCloaked = true;
				}				
				this.vel.x = 0;
			}			
		}else{
			//cloak up
			//check to see if not cloaked, cloak
			if(!this.isCloaked){
				this.renderable.setCurrentAnimation('cloak',function(){
							this.renderable.setCurrentAnimation('cloaked');
							this.renderable.setAnimationFrame(0);
					}.bind(this));
				this.isCloaked = true;
			}				
			this.vel.x = 0;
		}

		this.updateMovement();
		
		//if spy collides with assassin, caught!
		//if(!this.isCloaked){
			//var res = me.game.collide(this);
			
			//if(!this.isCloaked && res && res.obj.type == me.game.SPY && spy.alive){
			//if(res && res.obj.type == me.game.SPY && spy.alive){
			if(spy.alive && this.colOverlaps(spy.collisionBox)){
				//console.log('caught');
				//this.renderable.setCurrentAnimation('lookForward');
				this.vel.x = 0;
				if(spy.pos.x > this.pos.x){
					var direction = 'right';
					//var posInc = 16;
					var posInc = 16;
					spy.caughtKnockedDown('left');
				}else{
					var direction = 'left';
					//var posInc = -48;
					var posInc = -32;
					spy.caughtKnockedDown('right');
				}
				//spy.caught();
				
				//this.renderable.setCurrentAnimation('stand');
				//Remove and add Kill Sprite
				//var assassinAttack = new AssassinAttackEntity(this.pos.x+posInc, this.pos.y, {image:this.killSprite, spritewidth:48, spriteheight: 32, direction: direction });				
				var assassinAttack = me.entityPool.newInstanceOf("assassinattack",this.pos.x+posInc, this.pos.y, {image:this.killSprite, spritewidth:48, spriteheight: 32, direction: direction });
					me.game.add(assassinAttack,this.z);
					//me.game.sort();
					
				this.renderable.alpha = 0;
				me.game.remove(this);
			}
		//}
		
		this.parent(this);
		return true;
	}/*,
	colOverlaps : function(r)	{
		return (this.collisionBox.left < r.right && 
		r.left < this.collisionBox.right && 
		this.top < r.bottom &&
		r.top < this.collisionBox.bottom);
	}*/
});

/* ---------------------
a You Lost entity
----------------------*/
//Display You Lost message, on key press 'R' retry the level
var YouLostMSGEntity = me.ObjectEntity.extend({
	init:function(x,y){
		settings.height = 240;
		settings.width = 320;	
		
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		this.anchorPoint.set(0,0);
		this.floating = true;
		//Load the font
		this.font = new me.BitmapFont(TextFont,8);
		//this.msg1 = "YOU GOT CAUGHT!";
		this.msg1 = "";
		//this.msg1Width = (this.font.measureText(this.msg1)).width;
		//console.log(this.msg1Width);
		
		//TODO: Need to take into all directions
		var textPosX = Math.floor(me.game.viewport.pos.x/320.0) * 320;
		var textPosY = Math.floor(me.game.viewport.pos.x/320.0) * 320;
		
		//var red_alert = new CutSceneActorEntity(0, 0, {image: 'red_alert', spritewidth:320, spriteheight:240, float:true});
		var red_alert = me.entityPool.newInstanceOf("cutsceneactor",0, 0, {image: 'red_alert', spritewidth:320, spriteheight:240, float:true});
		me.game.add(red_alert,90);
		//me.game.sort();
		
		var caught_msg = new CutSceneActorEntity(110, 90, {image: 'caught_msg', spritewidth:100, spriteheight:50, loop: 'once',frames:9, animationSpeed:1, float:true});
		var caught_msg = me.entityPool.newInstanceOf("cutsceneactor",110, 90, {image: 'caught_msg', spritewidth:100, spriteheight:50, loop: 'once',frames:9, animationSpeed:1, float:true});
		me.game.add(caught_msg,100);
		//me.game.sort();
		
		
		this.msgCounter = 0;
		this.msgTime = 15;
		this.msgDrawn = false;
		
		if(me.gamestat.getItemValue('usingGamePad') == 'yes'){
			this.msg = "PRESS <A> TO RETRY!";
		}else{
			this.msg = "PRESS <R> TO RETRY!";
		}
					
		//Enable Spacebar (common jump key) to restart
		//me.input.bindKey(me.input.KEY.SPACE, "retry", true);
		this.retryEnabled = false;
	},
	update:function(){
		//console.log(me.game.viewport.pos.x);
		
		if(this.msgCounter <= this.msgTime){
			this.msgCounter += 1*me.timer.tick;
		}else{
			if(!this.retryEnabled){
				//Enable Spacebar (common jump key) to restart
				//me.input.bindKey(me.input.KEY.SPACE, "retry", true);
				InputControls.setForRetry();
				this.retryEnabled = true;
			}
			
			if(!this.msgDrawn){
				this.msgWidth = this.font.measureText(context,this.msg).width;
				
				//console.log(me.game.viewport.pos.x + me.game.viewport.width/2 - this.msgWidth/2);
				
				//var text = new CutSceneTextEntity(0, 0, {msg:this.msg,textPos:"center",textPosX: me.game.viewport.width/2 - this.msgWidth/2, textPosY: 140});				
				var text = me.entityPool.newInstanceOf("cutscenetext",0, 0, {msg:this.msg,textPos:"center",textPosX: me.game.viewport.width/2 - this.msgWidth/2, textPosY: 140});
					me.game.add(text,100);
					//me.game.sort();	
				this.msgDrawn = true;
			}
		}
		
		if(me.input.isKeyPressed('retry')){
			InputControls.resetForRetry();
			me.game.remove(this);
		}
	},
	draw: function(context){
		//console.log(context);
		//Display Two Lines: You lost, Retry
		/*
		
		this.msg1Width = this.font.measureText(context,this.msg1).width;
		this.msg2Width = this.font.measureText(context,this.msg2).width;	
		
		//console.log(me.game.viewport.pos.x + me.game.viewport.width/2 - this.msg1Width/2);
		this.font.draw(context,
			this.msg1,me.game.viewport.pos.x + me.game.viewport.width/2 - this.msg1Width/2,
			80);
		this.font.draw(context,
			this.msg2,me.game.viewport.pos.x + me.game.viewport.width/2 - this.msg2Width/2,
			140);
			//96
		//Hint Message
		//Try Standing Still
		
		*/
		
	},
	onDestroyEvent: function(){
		//me.input.bindKey(me.input.KEY.SPACE, "jump", true);
		InputControls.resetForRetry();
	}
});


/* ---------------------
a background sprite entity
----------------------*/
var BackgroundSpriteEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		//Custom Start Menu Backgrounds yes
		if(settings.image == 'start_menu'){
			if(gameData.load('currentLevel')){
				var currentLevel = gameData.load('currentLevel'); // Get title of current level
			
				var currentMission = currentLevel.split('_')[1];
				
				//console.log('Current Mission: ' + currentMission);
				
				if(currentMission == '01'){
				}else{}
				
				switch(currentMission){
					case '01':
						settings.image = 'menu_bg_01';
						break;
					case '02':
						settings.image = 'menu_bg_02';
						break;
					case '03':
						settings.image = 'menu_bg_03';
						break;
					case '04':
						settings.image = 'menu_bg_04';
						break;
					case '05':
						settings.image = 'menu_bg_05';
						break;						
					default:
						settings.image = 'menu_bg_01';
				}		
			}else{
				settings.image = 'menu_bg_01';
			}
		}
		
		this.parent(x,y,settings);
		this.image = settings.image;
		this.collidable = false;
		this.isPlaying = true;
		this.startPosY = this.pos.y;
		this.startPosX = this.pos.x;
		this.alwaysUpdate = (settings.alwaysUpdate) ? settings.alwaysUpdate : false;	
		this.VR = (settings.VR) ? settings.VR : false;	
		//(settings.lockToCameraY) ? this.lockToCameraY = settings.lockToCameraY : this.lockToCameraY = false;
		this.lockToCameraY = (settings.lockToCameraY) ? settings.lockToCameraY : false;	
		this.lockToCameraX = (settings.lockToCameraX) ? settings.lockToCameraX : false;	
		(settings.animationSpeed) ? this.animationSpeed = settings.animationSpeed : this.animationSpeed = 16;
		//this.renderable.animationspeed = me.sys.fps / 1; //6
		
		this.pulse = (settings.pulse) ? settings.pulse : false;	
		
		this.random = (settings.random) ? settings.random : false;	
		//Grab a frame at random intervals
		
		
		this.randomCounter = 0;
		this.randomTime = this.getRandomInt(1,20);
		this.rFrame = this.getRandomInt(0,12);
		
		this.timeAttack = (me.gamestat.getItemValue('currentMode') == 'timeAttack') ? true : false;		
		
		//If it's in time attack mode and this is VR, remove 
		 if(this.VR){
			
			if(settings.part == 'right'){
				this.renderable.addAnimation('defaultAnim', [1,3,5], this.animationSpeed);
				this.renderable.addAnimation('glitch',[1,3,5],2);
			}else{	//left
				this.renderable.addAnimation('defaultAnim', [0,2,4], this.animationSpeed);
				this.renderable.addAnimation('glitch',[0,2,4],2);
			}
			
		}
		
		if(!this.VR){
			this.renderable.addAnimation('defaultAnim', null, this.animationSpeed);
		}
		
		/* Hmm...I think this should be below
		if(settings.startframe != ''){
			this.renderable.setAnimationFrame(0);
		}
		*/
		
		//default delay to random if not set
		if(settings.delay == 'none' || settings.delay === 0){
			this.delay = 0;
		}else{			
			if(settings.delay == null){
				this.delay = 20 + Math.floor(Math.random()*11);
			}else{
				this.delay = settings.delay;
			}
		}		
		
		this.timer = 0;
		if(this.delay > 0){
			this.renderable.alpha = 0;
			this.isPlaying = false;
			this.renderable.setCurrentAnimation('default', function() {this.delayAnim()}.bind(this));
			//console.log('test 1');
		}else{
			this.renderable.setCurrentAnimation('defaultAnim');
			this.delay = 0;
			//console.log('test');
		}
		
		if(this.random){
			this.renderable.addAnimation('randomAnim',[this.rFrame]);
			this.renderable.setCurrentAnimation('randomAnim');
		}
		
		if (this.handle)  {
			me.event.unsubscribe(this.handle);
			this.handle = null;
		}
		
		if(this.lockToCameraY){
			this.handle = me.event.subscribe(me.event.VIEWPORT_ONCHANGE, this.updatePosY.bind(this));
		}else if(this.lockToCameraX){
			this.handle = me.event.subscribe(me.event.VIEWPORT_ONCHANGE, this.updatePosX.bind(this));
		}else{
			this.handle = null;
		}
		
		if(settings.startframe != ''){
			this.renderable.setAnimationFrame(settings.startframe);
		}
		
		
		this.pulseCounter = 0;
		this.pulseTime = 60;
		this.pulseAlpha = 1;
		this.reverse = false;
		
		
		
		
	},
	update:function(){
		
		if(this.VR && this.timeAttack){
			me.game.remove(this);
		}
		
		if(this.random){
			if(this.randomCounter<=this.randomTime){
				this.randomCounter++;
			}else{
				this.randomCounter = 0;
				this.randomTime = this.getRandomInt(1,20);
				this.rFrame = this.getRandomInt(0,12);
				this.renderable.addAnimation('randomAnim',[this.rFrame]);
				this.renderable.setCurrentAnimation('randomAnim');
			}
		}
		
		if(this.pulse){
			
			if(this.pulseCounter <= this.pulseTime){
				if(this.reverse){
					this.pulseAlpha += 0.01;
				}else{
					this.pulseAlpha -= 0.01;
				}
				this.renderable.alpha = this.pulseAlpha;
				this.pulseCounter++;
			}else{
				this.pulseCounter = 0;
				this.reverse = !this.reverse;				
			}
		}
		
		if(!this.isPlaying && this.delay > 0){
			if(this.timer < this.delay){
				this.timer += 1*me.timer.tick;
			}else{
				this.timer = 0;
				this.isPlaying = true;
				if(!this.pulse){
					this.renderable.alpha = 1;
				}
				//if(!this.VR){
					this.renderable.setCurrentAnimation('defaultAnim', function() {this.delayAnim()}.bind(this));
				/*}else{
					if(this.side == 'right'){
						this.renderable.setCurrentAnimation('rightAnim', function() {this.delayAnim()}.bind(this));
					}else{	//left
						this.renderable.setCurrentAnimation('leftAnim', function() {this.delayAnim()}.bind(this));
					}
				}*/
			}
		}
		
		//if(this.lockToCameraY){
			//console.log(this.startPosY  + me.game.viewport.pos.y + ' ' + this.pos.y);
			//this.pos.y = this.startPosY  + me.game.viewport.pos.y;
			//console.log('Viewport pos y 3:' + me.game.viewport.pos.y);
			
		//}
		
		this.parent(this);
		return true;	
	},
	updatePosY:function(vpos){
		this.pos.y = this.startPosY  + vpos.y;
	},updatePosX:function(xpos){
		this.pos.x = this.startPosX  + xpos.x;
	},
	delayAnim:function(){
		this.renderable.alpha = 0;
		this.isPlaying = false;
	},
	getRandomInt:function(min,max){
		return Math.floor(Math.random()*(max-min+1)+min);
	},
	glitch:function(){
		this.renderable.alpha = 1;
		this.delay = 0;
		this.renderable.setCurrentAnimation('glitch');
	}
});




/* ---------------------
Traps!

3 Entities: Trigger, Device, and Projectile

When the player steps on the trigger, the trigger finds devices with the same name. 

The devices create a projectile entity and shoots it in a specified direction.

The trigger will have a slight cool down time (red state) before becoming reactivated (green).

----------------------*/
var TrapTriggerEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = (0);
		this.updateColRect(2,28,-4,4);
		
		this.renderable.addAnimation('neutral', [0]);
		this.renderable.addAnimation('triggered', [1]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.deviceName = settings.trapName;
		
		this.isTriggered = false;
		this.coolDownTime = 60;
		this.coolDownCounter = 0;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		if(this.isTriggered){
			if(this.coolDownCounter < this.coolDownTime){
				this.coolDownCounter += 1 * me.timer.tick;
			}else{
				this.coolDownCounter = 0;
				this.isTriggered = false;
				this.renderable.setCurrentAnimation('neutral');
			}
		}else{
			//Check for spy collision, find related devices, trigger the devices
			if(spy.alive){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY) && !res.obj.jumping && (res.obj.pos.y +20 < this.pos.y)){
				if( this.colOverlaps(spy.collisionBox) && !spy.jumping && (spy.pos.y +20 < this.pos.y)){
					this.isTriggered = true;
					this.renderable.setCurrentAnimation('triggered');
					me.audio.play('trapdart');
					
					var trapDevices = me.game.getEntityByProp('trapName',this.deviceName);
					for(var i = 0; i < trapDevices.length; i++){
						//console.log(trapDevices[i]);
						trapDevices[i].shoot();							
					}	
				}
			}
		}
		this.parent(this);
		return true;
	}
});

var TrapDeviceEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.direction = settings.direction;		
		this.trapName = settings.trapName;
		this.gravity = (0);
		//Do animations for:
		//if this direction left
		//if this direction right
		//if this direction down
		
		//TODO: Animations for Activated state
		if(this.direction == 'right'){
			this.renderable.addAnimation('neutral', [0]);
			this.renderable.addAnimation('triggered', [1]);
			this.particleX = x + 8;
			this.particleY = y;

		}else if(this.direction == 'left'){
			this.renderable.addAnimation('neutral', [4]);
			this.renderable.addAnimation('triggered', [5]);
			this.particleX = x - 8;
			this.particleY = y;

		}else if(this.direction == 'down'){
			this.renderable.addAnimation('neutral', [2]);
			this.renderable.addAnimation('triggered', [3]);
			this.particleX = x;
			this.particleY = y + 8;
		}
		
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.triggerTime = 20;
		this.triggerCounter = 0;
		
		this.trapX = x;
		this.trapY = y;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		if(this.triggerCounter < this.triggerTime){
			this.triggerCounter += 1 * me.timer.tick;
		}else{
			this.triggerCounter = 0;
			this.isTriggered = false;
			this.renderable.setCurrentAnimation('neutral');
		}
		
		this.parent(this);
		return true;
	},
	shoot: function(){
		//if this direction left
		//if this direction right
		//if this direction down
		this.isTriggered = true;
		this.renderable.setCurrentAnimation('triggered');
		
		var jumpdust = me.entityPool.newInstanceOf("jumpdust", this.trapX, this.trapY, {image:'trapparticle', spritewidth:16, spriteheight: 16 });
			me.game.add(jumpdust,this.z + 1);
			
			/*
		var jumpdust = new JumpDustEntity(this.particleX, this.particleY, {image:'trapparticle', spritewidth:16, spriteheight: 16 });
			me.game.add(jumpdust,this.z + 1);
			me.game.sort(); */
			
		
		//var trapProjectile = new TrapProjectileEntity(this.trapX, this.trapY, {image:'dart', spritewidth:16, spriteheight: 16, direction: this.direction });
		var trapProjectile = me.entityPool.newInstanceOf("trapprojectile",this.trapX, this.trapY, {image:'dart', spritewidth:16, spriteheight: 16, direction: this.direction });
			me.game.add(trapProjectile,this.z);
			//me.game.sort();
		//console.log(this.pos.x);
		//create projectile object
		//make a sound
		//TODO: Create puff of smoke object

	}
});

/* ---------------------
Timed Trap Device will trigger projectiles on a timer

----------------------*/


var TimedTrapDeviceEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		if(settings.image!='vr_trapdevice'){
			settings.image='trapdeviceM4';
		}else{
			this.VR = true;
		}
		this.parent(x,y,settings);
		this.direction = settings.direction;		
		//this.trapName = settings.trapName;
		this.gravity = (0);
		//Do animations for:
		//if this direction left
		//if this direction right
		//if this direction down
		this.alwaysUpdate = true;
		
		//TODO: Animations for Activated state
		if(this.direction == 'right'){
			this.renderable.addAnimation('neutral', [0]);
			this.renderable.addAnimation('triggered', [1]);
			this.particleX = x + 8;
			this.particleY = y;

		}else if(this.direction == 'left'){
			this.renderable.addAnimation('neutral', [4]);
			this.renderable.addAnimation('triggered', [5]);
			this.particleX = x - 8;
			this.particleY = y;

		}else if(this.direction == 'down'){
			this.renderable.addAnimation('neutral', [2]);
			this.renderable.addAnimation('triggered', [3]);
			this.particleX = x;
			this.particleY = y + 8;
		}
		
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.triggerTime = 20;
		this.triggerCounter = 1;
		
		this.trapX = x;
		this.trapY = y;
		
		this.delayCounter = 1;
		this.delayTime = (settings.delayTime) ? settings.delayTime : 30;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTime = 60;
		}else{
			this.delayTime = 30;
		}

		this.shootDouble = true;
		
	},
	update: function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.isTriggered = false;
			this.triggerCounter = 1;
			this.delayCounter = 1;
			this.renderable.setCurrentAnimation('neutral');
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
			
			if(this.triggerCounter < this.triggerTime){
				this.triggerCounter += 1 * me.timer.tick;
			}else{
				this.triggerCounter = 1;
				this.isTriggered = false;
				this.renderable.setCurrentAnimation('neutral');
			}
			
			if(this.delayCounter < this.delayTime){
				this.delayCounter += 1 * me.timer.tick;
			}else{
				//Check if it should go left or right
				this.delayCounter = 1;
				this.shoot();
			}
			
			
			this.parent(this);
			return true;
		}
	},
	shoot: function(){
		//if this direction left
		//if this direction right
		//if this direction down
		this.isTriggered = true;
		this.renderable.setCurrentAnimation('triggered');
		if(this.inViewport){
			me.audio.play('trapdart',false, null, 0.5);
		}
		
		if(!this.VR){
		//var jumpdust = new JumpDustEntity(this.particleX, this.particleY, {image:'sootparticle', spritewidth:16, spriteheight: 16 });
			var jumpdust = me.entityPool.newInstanceOf('jumpdust',this.particleX, this.particleY, {image:'sootparticle', spritewidth:16, spriteheight: 16 });
				me.game.add(jumpdust,this.z + 1);
			//me.game.sort();
		}
		
		if(this.VR){
			var dartImage = 'vr_dart';
		}else{
			var dartImage = 'dart2';
		}
				
		//var trapProjectile = new TrapProjectileEntity(this.trapX, this.trapY, {image:dartImage, spritewidth:16, spriteheight: 16, direction: this.direction });
		var trapProjectile = me.entityPool.newInstanceOf("trapprojectile",this.trapX, this.trapY, {image:dartImage, spritewidth:16, spriteheight: 16, direction: this.direction });
			me.game.add(trapProjectile,this.z-1);
			me.game.sort();
		//console.log(this.pos.x);
		//create projectile object
		//make a sound
		//TODO: Create puff of smoke object

	}
});


var TrapProjectileEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.direction = settings.direction;
		this.alwaysUpdate = true;
		this.gravity = (0);
		this.collision = false;
		this.updateColRect(6,4,6,4);


		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.speed = 4;
		}else{
			this.speed = 5;
		}

		this.projectileImage = settings.image;

		//TODO: Animations for each direction
		
		this.renderable.addAnimation('side',[0]);
		this.renderable.addAnimation('down',[1]);
		
		if(this.direction == 'right'){
			this.renderable.setCurrentAnimation('side');
		}else if(this.direction == 'left'){
			this.renderable.setCurrentAnimation('side');
			this.flipX(true);			
		}else if(this.direction == 'down'){
			this.renderable.setCurrentAnimation('down');
		}
		
		
	},
	update: function(){
		if(this.direction == 'left'){
			//left
			//console.log(this.gravity);
			this.pos.x -= this.speed * me.timer.tick;
			//this.pos.y = 
			//console.log(this.pos.y);
		}else if(this.direction == 'right'){
			//right
			this.pos.x += this.speed * me.timer.tick;
		}else{
			//down
			this.pos.y += this.speed * me.timer.tick;
		}
		
		
		//var res = me.game.collide(this);
		
		//if(res && res.obj.type == me.game.SPY && spy.alive){
		if(spy.alive && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			this.speed = 0;
			if(this.direction == 'right'){
				direction = 'left';
			}else{
				direction = 'right';
			}
			
			this.addHitSpy();
			spy.caughtKnockedDown(direction);
			me.game.remove(this);
		}
		
		if(!this.inViewport || ScreenTransitionStart){
			me.game.remove(this);
		}
		
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//swap out image here?
		var hitImage = 'hitspy2';
		if(this.projectileImage == 'vr_dart' ){
			hitImage = 'hitspy';
		}
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:hitImage, spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
});


/* ---------------------
Trap Door

When Spy steps on this platform, the trap is trigger and the door opens
Spy has a split second to jump off

----------------------*/
var TrapDoorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = true;
		this.gravity = (0);
		this.type = 'TRAPDOOR';
		this.alwaysUpdate = true;
		this.updateColRect(2,28,-4,4);
		//this.updateColRect(0,32,-4,8);
		
		(settings.debug) ? this.debug = true : this.debug = false;
		
		this.renderable.addAnimation('neutral', [0]);
		//this.renderable.addAnimation('triggered', [1,2,1,2]);
		this.renderable.addAnimation('triggered', [1,2,3,4,3],3);
		//this.renderable.addAnimation('opened', [2]);
		this.renderable.addAnimation('opened', [3]);
		//this.renderable.addAnimation('closing', [1,0]);
		this.renderable.addAnimation('closing', [2,1,0]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.isOpened = false;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTime = 20;
		}else{
			this.delayTime = 15;
		}

		this.coolDownTime = 120;
		this.coolDownCounter = 0;
		
		this.delayTimeCounter = 0;
		
	},
	update: function(){
		if(this.isOpened){
			//small amount of time before it opens
			if(this.coolDownCounter < this.coolDownTime){
				this.coolDownCounter += 1 * me.timer.tick;
			}else{
				this.coolDownCounter = 0;
				this.isOpened = false;
				this.renderable.setCurrentAnimation('closing','neutral');
				me.audio.play('trapdoorclose');
			}
			
		}else if(this.isTriggered){
			//small amount of time before it opens
			if(this.delayTimeCounter < this.delayTime){
				this.delayTimeCounter += 1 * me.timer.tick;
			}else{
				this.delayTimeCounter = 0;
				this.isTriggered = false;
				this.isOpened = true;
				this.renderable.setCurrentAnimation('triggered','opened');
				me.audio.play('trapdoor');
			}
			
		}else{
			//Check for spy collision
			
			if(spy.alive){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY) && !res.obj.jumping && (res.obj.pos.y +20 < this.pos.y) 
				if(this.colOverlaps(spy.collisionBox) && !spy.jumping && (spy.pos.y +20 < this.pos.y) 
					//Give padding - spy needs to be actually on the trap before the trap activates
					//&& (res.obj.pos.x + res.obj.width > this.pos.x + 4) 
					//&& (res.obj.pos.x < this.pos.x - 4) 
				){
					//console.log('Spy: ' + res.obj.pos.y  + ' Door: ' + this.pos.y);
					this.isTriggered = true;			
				}
			}
			
		}
		this.parent(this);
		return true;
	}
});


var HackableTrapDoorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = true;
		this.gravity = (0);
		this.type = 'TRAPDOOR';
		this.doorName = settings.doorName;
		this.alwaysUpdate = true;
		this.updateColRect(2,28,-4,4);
		//this.updateColRect(0,32,-4,8);
		
		(settings.debug) ? this.debug = true : this.debug = false;
		
		this.renderable.addAnimation('neutral', [0]);
		//this.renderable.addAnimation('triggered', [1,2,1,2]);
		this.renderable.addAnimation('triggered', [1,2,3,4,3],3);
		//this.renderable.addAnimation('opened', [2]);
		this.renderable.addAnimation('opened', [3]);
		//this.renderable.addAnimation('closing', [1,0]);
		this.renderable.addAnimation('closing', [2,1,0]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.isOpened = false;
		this.coolDownTime = 120;
		this.coolDownCounter = 0;
		
		this.delayTime = 15;
		this.delayTimeCounter = 0;
		
		this.doTheStuff = false;
		this.doTheStuffCounter = 0;
		this.doTheStuffTime = 16;
		
	},
	update: function(){
		if(this.isOpened && this.doTheStuffCounter < this.doTheStuffTime){
			this.doTheStuffCounter++;
			this.renderable.setCurrentAnimation('opened');
			
			var door = me.game.getEntityByProp('image','bookshelf');
			for(var i = 0; i < door.length; i++){
				//door[i].hacked = true;			
				//door[i].isOpened = true;
				door[i].pos.x += 1;
			}
			
			this.doTheStuff = true;
		}
		this.parent(this);
		return true;
	}
});

/* ---------------------
Timed Trap Door

When Spy steps on this platform, the trap is trigger and the door opens
Spy has a split second to jump off

----------------------*/
var TimedTrapDoorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = true;
		this.gravity = (0);
		this.type = 'TRAPDOOR';
		this.alwaysUpdate = true;
		this.updateColRect(2,28,-4,4);
		//this.updateColRect(0,32,-4,8);
		
		(settings.debug) ? this.debug = true : this.debug = false;
		
		this.renderable.addAnimation('neutral', [0]);
		//this.renderable.addAnimation('triggered', [1,2,1,2]);
		//this.renderable.addAnimation('triggered', [1,2,3,4,3],3);
		this.renderable.addAnimation('triggered', [1,2,3,4],3);
		//this.renderable.addAnimation('opened', [2]);
		this.renderable.addAnimation('opened', [4]);
		//this.renderable.addAnimation('closing', [1,0]);
		this.renderable.addAnimation('closing', [3,2,1,0]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.isOpened = false;
		this.coolDownTime = 120;
		this.coolDownCounter = 0;
		

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTime = 120;
			this.delayTimeOpen = 90;
		}else{
			this.delayTime = 60;
			this.delayTimeOpen = 90;
		}
		
		
		this.delayCounter = 1;
		
		//offset delay
		this.offSetStartTime = (settings.offSetStart) ? settings.offSetStart : 0;
		this.offSetStartCounter = 1;
	},
	update: function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.isOpened = false;
			this.delayCounter = 1;
			this.offSetStartCounter = 1;
			this.renderable.setCurrentAnimation('neutral');
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
	
		if(this.offSetStartCounter < this.offSetStartTime){
			this.offSetStartCounter += 1 * me.timer.tick;
		}else{
			//Timer - Changing it up so we can have different delay times
			if(this.isOpened){
				if(this.delayCounter < this.delayTimeOpen){
				this.delayCounter += 1 * me.timer.tick;
				}else{
					this.delayCounter = 1;
					this.isOpened = false;
					this.renderable.setCurrentAnimation('closing','neutral');
					me.audio.play('autodoorclose',false, null, 0.6);
				}
			}else{
				if(this.delayCounter < this.delayTime){
					this.delayCounter += 1 * me.timer.tick;
				}else{
					this.delayCounter = 1;
					this.isOpened = true;
					this.renderable.setCurrentAnimation('triggered','opened');
					me.audio.play('autodooropen',false, null, 0.6);
				}
			}
		}
		/*
		if(this.delayTimeCounter < this.delayTime){
			this.delayTimeCounter += 1 * me.timer.tick;
		}else{
			//Check if it should open or close
			this.delayTimeCounter = 0;
			if(this.isOpened){
				this.isOpened = false;
				this.renderable.setCurrentAnimation('closing','neutral');
				me.audio.play('trapdoorclose');
			}else{
				this.delayTimeCounter = 0;
				this.isOpened = true;
				this.renderable.setCurrentAnimation('triggered','opened');
				me.audio.play('trapdoor');
			}
		}
		*/
		
		this.parent(this);
		return true;
		}
	}
});

/* ---------------------
a sawblade entity
----------------------*/
var SawBladeEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
	this.parent(x,y,settings);
	this.collidable = false;
	this.anchorPoint.set(0,0);
	this.gravity = 0;
		this.alwaysUpdate = true;
		//2x speed of spy
		this.speed = (settings.speed) ? settings.speed : 4;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.speed = 3;
		}
		
		//check if vertical or horizontal
		//probably won't use velocity
		if(settings.move == 'y'){
			//Set it up to move back and forth
			this.startY = y;
			this.endY = settings.height + y - 16;		
		
			this.move = 'y';
			this.updateColRect(2,12,2,12);
			
			//move left is up
			if(settings.startSide == 'top'){
				this.pos.y = this.startY;
				this.moveUp = false;
				//console.log('Height: ' + settings.height + ' Start Pos: ' + this.startY + ' End Pos: ' + this.endY);
			}else{
				this.pos.y = this.endY;
				this.moveUp = true;
			}
			
			
			
		}else{ //Horizontal/X
			//Set it up to move back and forth
			this.startX = x;
			this.endX = x + settings.width - settings.spritewidth;	
		
			this.move = 'x';
			this.updateColRect(2,12,2,12);
			
				
			if(settings.startSide == 'left'){
				this.pos.x = this.startX;
				this.moveLeft = false;
			
			}else{
				this.pos.x = x + settings.width - settings.spritewidth;
				this.moveLeft = true;
			}
	
		}
		
		
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.startDelayCounter = 1;
		
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTime = 60;
		}else{
			this.delayTime = 30;
		}
		
		this.delayCounter = 1;		
		this.renderable.alpha = 0;
		
		//Need a delay at the beggining and in (in which the animations play)
		this.animDelay = 30;
		this.startDelayCounter = 1;
		
		this.endDelay = 30;		
		this.endDelayCounter = 0;
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		
		this.renderable.addAnimation('extend', [6,5,4,3,2,1,0],4);
		this.renderable.addAnimation('retract', [0,1,2,3,4,5,6],4);
		this.renderable.addAnimation('spin', [0,1],4);
		
		this.retract = false;
		this.extend = true;
		this.hidden = true;
		
		this.doReset = true;
		//this.renderable.alpha = 0;
		//this.renderable.setCurrentAnimation('extend','spin');

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
				
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update:function(){
		if(this.removeImmediately){ me.game.remove(this); }
		//if(this.resetCheck(this.startPosX,this.startPosY)){	return false;}
		
		if(!this.inViewport || ScreenTransitionState){
			//console.log('nop');
			//if(this.doReset){
				//this.delayTime = 30;
				this.delayCounter = 30;		
				this.renderable.alpha = 0;
				
				this.vel.y = 0;
				this.vel.x = 0;
				this.retract = false;
				this.extend = true;
				this.hidden = true;
				this.doReset = false;
				//console.log('yus');
				this.updateMovement();
				this.pos.x = this.startPosX;
				this.pos.y = this.startPosY;
				this.parent(this);
				return true;			
		}
		
		//if(this.inViewport){
		
		this.doReset = true;
		//Start Delay
		/* Apparently this isn't doing anything yet, so I'm commenting it out
		if(this.startDelay && !this.extend && !this.retract){			
			this.startDelayCounter += me.timer.tick;
			if(this.startDelayCounter < this.startDelay){
				this.parent(this);				
				return true;
			}else{
				this.startDelay = false;
				this.extend = true;
			}
		}
		*/
		
		//TODO: Build in a little delay at the start and end
		//This is where the animation will play out
		
		//move horizontal/x
		if(this.move == 'x'){
		
			if (this.moveLeft && this.pos.x <= this.startX) {
				this.retract = true;
			} else if (!this.moveLeft && this.pos.x >= this.endX) {				
				this.retract = true;
			}
			if(!this.retract && !this.extend && !this.hidden){
				this.vel.x = (this.moveLeft) ? -this.speed * me.timer.tick : this.speed * me.timer.tick;
			}else{
				this.vel.x = 0;
			}			
		}else if(this.move == 'y'){ //move vertical/y
			if (this.moveUp && this.pos.y <= this.startY) {
				//console.log(this.hidden + ' ' + this.extend);
				//console.log('at the top');
				this.retract = true;
			} else if (!this.moveUp && this.pos.y >= this.endY) {
				//console.log(this.pos.y + ' ' + this.endY);
				this.retract = true;				
			}			
			
			//console.log(this.moveUp);
			//console.log(this.hidden + ' ' + this.extend);
			
			if(!this.retract && !this.extend  && !this.hidden){
				this.vel.y = (this.moveUp) ? -this.speed : this.speed;
				
			}else{
				this.vel.y = 0;
			}
		}
		
		//Hidden Timer
		if(this.hidden && this.delayCounter <= this.delayTime && !this.retract && !this.extend){
			this.delayCounter += 1 * me.timer.tick;
			this.renderable.alpha = 0;
		}else{
			if(this.hidden && this.delayCounter >= this.delayTime){
				this.extend = true;
				
			}
			this.hidden = false;
			
			this.renderable.alpha = 1;
			this.delayCounter = 1;
			
		}
		
		
		
		//console.log(this.extending);
		if(this.extend && !this.renderable.isCurrentAnimation('extend')){
			//console.log(this.extend);
			this.hidden = false;
			this.renderable.setCurrentAnimation('extend',function() {this.extendBlade()}.bind(this));
			
			this.extending = true;
			//console.log('extending');
			//this.renderable.setAnimationFrame(0);
		}
		if(this.retract){
			this.renderable.setCurrentAnimation('retract',function() {this.retractBlade()}.bind(this));
		}
		
		this.currentFrame = this.renderable.getCurrentAnimationFrame();
		//Change collision box based on animation frame
		if(this.currentFrame != 1 && this.currentFrame != 0){
			//console.log(currentFrame);
			if(this.move == 'y'){
				if(this.renderable.isCurrentAnimation('retract')){
					switch (this.currentFrame){
						case 2:
							this.updateColRect(2,11,2,12);
							break;
						case 3:
							this.updateColRect(2,8,2,12);
							break;
						case 4:
							this.updateColRect(2,5,2,12);
							break;
						case 5:
							this.updateColRect(2,2,2,12);
							break;
						case 6:
							this.updateColRect(0,0,2,12);
							break;
					}
				}else if(this.renderable.isCurrentAnimation('extend')){
					switch (this.currentFrame){
						case 2:
							this.updateColRect(0,0,2,12);
							break;
						case 3:
							this.updateColRect(2,2,2,12);
							break;
						case 4:
							this.updateColRect(2,5,2,12);
							break;
						case 5:
							this.updateColRect(2,8,2,12);
							break;
						case 6:							
							this.updateColRect(2,11,2,12);
							break;
					}					
				}
			}
		}else{
			if(this.move == 'y'){
				//this.updateColRect(2,12,2,12);
			}
		}
		
		//console.log(this.vel.y);
		this.updateMovement();
		//if(!this.hidden && (!(this.renderable.isCurrentAnimation('extend') && (this.currentFrame == 1 || this.currentFrame == 0)) && !(this.renderable.isCurrentAnimation('retract') && (this.currentFrame == 5 || this.currentFrame == 6)))){
		if(!this.hidden && !this.renderable.isCurrentAnimation('extend') && !this.renderable.isCurrentAnimation('retract')){
			//Don't want to trigger collision if blade is just barely poking out
			//var res = me.game.collide(this);
			
			//if(res && res.obj.type == me.game.SPY && spy.alive){
			if(spy.alive && this.colOverlaps(spy.collisionBox)){
				//console.log('caught');
				//spy.caught();
				spy.caughtKnockedDown('down');
			}
		}
		this.parent(this);
		return true;
		
		//}
		
	},
	retractBlade:function(){
		this.renderable.setCurrentAnimation('spin');
		if(this.move == 'x'){ this.pos.x = this.startPosX; }
		else { this.pos.y = this.startPosY; }
		this.hidden = true;
		this.retract = false;
		this.renderable.alpha = 0;
	},
	extendBlade:function(){
		this.renderable.setCurrentAnimation('spin');
		if(this.inViewport && !this.moveUp){ //Bottom of sawblade when set to move up dips into lower leve. 
			//There's probably a better way to fix this.
			me.audio.play('saw');
			
			//console.log('This Pos: ' + this.pos.y + 'Start Pos: ' + this.startPosY + ' End: ' + this.bottom);
		}
		this.extend = false;
		this.extending = false;
		//console.log('why');
	}
});


/* ---------------------
a one-way door entity
----------------------*/
var OneWaySwitchEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.doorName = settings.doorName;
		
		this.cpid = (settings.cpid) ? settings.cpid : 'sw01';
		
		this.activated = false;
		this.renderable.addAnimation('unactivated', [0]);
		this.renderable.addAnimation('activated', [1]);
		this.renderable.setCurrentAnimation('unactivated');
	},
	update: function(){	
		if(!this.activated){
			//if spy collides, start hack
			if(spy.alive){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					//save in temp checkpointData for novice mode
					var checkpointData = me.gamestat.getItemValue('checkpointDataTemp') + ',' + this.cpid;
					me.gamestat.setValue('checkpointDataTemp',checkpointData);
			
					this.activated = true;
					this.renderable.setCurrentAnimation('activated');
					me.audio.play("switchtrigger");
					var door = me.game.getEntityByProp('doorName',this.doorName);
					for(var i = 0; i < door.length; i++){
						door[i].hacked = true;			
						door[i].isOpened = true;			
					}						
				}
			}
		}
		this.parent(this);
		return true;
	},
	checkpointClear:function(){ //For checkpoints
		this.activated = true;
		this.renderable.setCurrentAnimation('activated');
		var door = me.game.getEntityByProp('doorName',this.doorName);
		for(var i = 0; i < door.length; i++){
			door[i].hacked = true;			
			door[i].isOpened = true;			
		}
	}
	
});


/* ---------------------
a hackable computer entity
----------------------*/
var HackableComputerEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);		
		this.doorName = settings.doorName;
		
		this.cpid = (settings.cpid) ? settings.cpid : 'hc01';
		
		this.hackTime = (settings.hackTime) ? settings.hackTime : 45;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.hackTime = 15;
		}
				
		this.hackCounter = 0;
		this.hacked = false;
		//hack		
		//TODO: Base this off of hacktime
		this.renderable.addAnimation('locked', [0,1,2]);
		this.renderable.addAnimation('unlocked', [6]);
		this.renderable.addAnimation('progress1', [3]);
		this.renderable.addAnimation('progress2', [4]);
		this.renderable.addAnimation('progress3', [5]);
		this.renderable.setCurrentAnimation('locked');
		
		if(this.doorName == 'galehdoor1'){
			//Check to see if spy has reached the computer
			//If yes, on level load, position master spy this.x + 16, this.y - 208
			//
		}
	},
	update: function(){
		if(!this.hacked){
			//if spy collides, start hack
			if(spy.alive){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)  && spy.vel.x == 0 && spy.vel.y == 0){
				if(spy.vel.x == 0 && spy.vel.y == 0 && this.colOverlaps(spy.collisionBox)){
					if(this.hackCounter <= this.hackTime){
						this.hackCounter += 1 * me.timer.tick;
						spy.hacking = true;
						if(this.hackCounter <= 15){
							this.renderable.setCurrentAnimation('progress1');
						}else if(this.hackCounter <= 30){
							this.renderable.setCurrentAnimation('progress2');
						}else{
							this.renderable.setCurrentAnimation('progress3');
						}
					}else{
						//find the associated door and open it
						var door = me.game.getEntityByProp('doorName',this.doorName);
						for(var i = 0; i < door.length; i++){
							door[i].hacked = true;							
						}
						this.hacked = true; //is this supposed to be commented out?
						spy.hacking = false;
						spy.wasHacking = true;
						me.audio.play("text");
						this.renderable.setCurrentAnimation('unlocked');
						
						//save in temp checkpointData for novice mode
						var checkpointData = me.gamestat.getItemValue('checkpointDataTemp') + ',' + this.cpid;
						me.gamestat.setValue('checkpointDataTemp',checkpointData);
						if(this.doorName == 'galehdoor1'){
							me.gamestat.setValue('checkpointCurrent','galehdoor1');
						}
					}					
				}else{
					//reset counter
					spy.hacking = false;
					this.hackCounter = 0;
					this.renderable.setCurrentAnimation('locked');
				}
			}
		}
		this.parent(this);
		return true;
	},
	checkpointClear:function(){
		var door = me.game.getEntityByProp('doorName',this.doorName);
		for(var i = 0; i < door.length; i++){
			door[i].hacked = true;							
		}
		this.renderable.setCurrentAnimation('unlocked');
	}
});

/* ---------------------
a hackable door entity
----------------------*/
var HackableDoorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = true;
		this.updateColRect(4,8,-1,0);
		this.doorName = settings.doorName;
		this.hacked = false;
		this.opening = false;
		
		this.isOpened = false;
		//
		this.renderable.addAnimation('locked', [0]);
		this.renderable.addAnimation('opening', [1,2,3,4,],2);
		this.renderable.addAnimation('opened', [5,6,7]);
		this.renderable.setCurrentAnimation('locked');
		
		this.leftX = this.collisionBox.left;
		this.rightX = this.collisionBox.right;
		//console.log(this.rightX);
		//console.log(this.leftX);
			
		this.expandZone = (settings.expandZone) ? JSON.parse(settings.expandZone) : '';
		this.expandZones();
		
		if(settings.hide){
			this.renderable.alpha = 0;
		} 

		this.stoppingSpy = false;
	},
	update: function(){
		//if colliding and not hacked, set spy vel.x = 0
		if(!this.hacked){
						
			//var res = me.game.collide(this);
			//if(res && (res.obj.type == me.game.SPY)){				
			if(this.colOverlaps(spy.collisionBox)){				
				//compare spy's direction and the side being collided against
				if((spy.collisionBox.left > this.leftX && !spy.currentDirection) || (spy.collisionBox.right < this.rightX && spy.currentDirection)){		
					spy.stopX = true;	
					this.stoppingSpy = true;
				}else{
					spy.stopX = false;
					this.stoppingSpy = false;
				}
				
			//}else{				
				//spy.stopX = false;
			}
			
			
		}else{
			//else, open on up and do nothing
			if(!this.opening){		
				if(this.stoppingSpy){
					spy.stopX = false;
				}		
				this.renderable.setCurrentAnimation('opening','opened');
				this.opening = true;
				this.expandZones();
			}
		}
		this.parent(this);
		return true;
	},
	expandZones: function(){
		var ezIndex = 0;
		var ezLength = this.expandZone.length;
		
		for(; ezIndex < ezLength; ezIndex++){
			//console.log(this.expandZone[ezIndex].enemyName);
			
			//find the associated door and open it
			var enemy = me.game.getEntityByProp('enemyName',this.expandZone[ezIndex].enemyName);
			
			for(var i = 0; i < enemy.length; i++){
				//console.log('Enemy DZL: ' + enemy[i].dangerZoneLeft);
				//This works for the tiger. Might have to do some checks for guards and other things.
				enemy[i].dangerZoneLeft -= Number(this.expandZone[ezIndex].left);
				enemy[i].dangerZoneRight += Number(this.expandZone[ezIndex].right);		
				//console.log('Enemy DZL: ' + enemy[i].dangerZoneLeft);
			}
			
		}
	}
});

/* ---------------------
a timed door entity

if it's closing, should it crush Master Spy? YES.
----------------------*/
var TimedDoorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = true;
		this.updateColRect(2,10,-1,0);
		
		this.alwaysUpdate = true;
		
		//Get DelayTimeOffset from settings
		this.delayTime = 90;
		this.delayCounter = 1;	

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTimeClosed = 90;
			this.delayTimeOpen = 120;
		}else{
			this.delayTimeClosed = 90;
			this.delayTimeOpen = 90;
		}
		
		this.delayTime = this.delayTimeClosed;
		this.opened = false;		
		this.opening = false;
		//
		this.renderable.addAnimation('locked', [0]);
		this.renderable.addAnimation('locking', [4,3,2,1],2);
		this.renderable.addAnimation('opening', [1,2,3,4,],2);
		this.renderable.addAnimation('opened', [5,6,7]);
		this.renderable.setCurrentAnimation('locked');
		
		this.leftX = this.collisionBox.left;
		this.rightX = this.collisionBox.right;
	},
	update: function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.delayCounter = 1;
			this.opened = false;		
			this.opening = false;
			this.renderable.setCurrentAnimation('locked');
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
			//Timer
			if(this.delayCounter < this.delayTime){
				this.delayCounter += 1 * me.timer.tick;
			}else{
				//Check if it should open or close
				this.delayCounter = 1;
				if(this.opened){
					this.opened = false;
					this.delayTime = this.delayTimeClosed;
					this.renderable.setCurrentAnimation('locking','locked');
					me.audio.play('timeddoor');
				}else{
					//this.delayCounter = 0;
					this.opened = true;
					this.delayTime = this.delayTimeOpen;
					this.renderable.setCurrentAnimation('opening','opened');
					me.audio.play('timeddoor');
				}
			}
			
			//if colliding and not opened, set spy vel.x = 0
			if(!this.opened){
							
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){				
				if(this.colOverlaps(spy.collisionBox)){				
					//compare spy's direction and the side being collided against
					if(this.renderable.isCurrentAnimation('locking') && spy.alive && this.renderable.getCurrentAnimationFrame() != 0){
						//console.log('caught');
						spy.caughtKnockedDown();
					}else if((spy.collisionBox.left > this.leftX && !spy.currentDirection) || (spy.collisionBox.right < this.rightX && spy.currentDirection)){		
						spy.stopX = true;	
					}else{
						spy.stopX = false;
					}
					
				//}else{				
					//spy.stopX = false;
				}
				
				
			}else{
				spy.stopX = false;
			}
			this.parent(this);
			return true;
		}
	}
});

/* ---------------------
a Grinder entity

It wines and dines but mostly grinds.
----------------------*/
var GrinderEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = 0;
		this.alwaysUpdate = true;
		if(settings.image == 'grinder2'){
			this.updateColRect(-1,0,16,32);
		}else if(settings.image == 'grinder3'){
			this.updateColRect(-1,0,16,48);
		}else{
			this.updateColRect(-1,0,16,16);
		}
				

		//Get DelayTimeOffset from settings
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTimeOff = 90;
			this.delayTimeOn = 60;
			this.renderable.addAnimation('spinup', [1,2,0,1,2,0,1,2,0,1,2,3],2);

		}else{
			this.delayTimeOff = 60;
			this.delayTimeOn = 60;
			this.renderable.addAnimation('spinup', [1,2,0,1,2,3],2);

		}
		
		this.delayTime = this.delayTimeOff;

		//this.delayTime = 60;
		this.delayCounter = 1;	
		
		this.grinding = ( settings.grind ) ? true : false;
		this.startGrinding = this.grinding;

		if(this.startGrinding){
			this.delayTime = this.delayTimeOn;
		}
		//
		this.renderable.addAnimation('neutral', [0]);
		//this.renderable.addAnimation('spinup', [1,2,0,1,2,3],2);
		this.renderable.addAnimation('spindown', [3]);
		this.renderable.addAnimation('grind', [4,5],2);
		if(this.grinding){
			this.renderable.setCurrentAnimation('spinup','grind');
			if(settings.playSoundonStart && this.inViewport){
				me.audio.play('grinder',false, null, 0.2);
			}
		}else{
			this.renderable.setCurrentAnimation('neutral');
		}
	},
	update: function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.delayCounter = 1;
			this.grinding = this.startGrinding;
			if(this.grinding){
				//me.audio.play('grinder');
				this.renderable.setCurrentAnimation('spinup','grind');
			}else{
				this.renderable.setCurrentAnimation('neutral');
			}
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
		//Timer
		if(this.delayCounter < this.delayTime){
			this.delayCounter += 1 * me.timer.tick;
		}else{
			//Check if it should open or close
			this.delayCounter = 1;
			if(this.grinding){
				this.grinding = false;
				this.delayTime = this.delayTimeOff;
				this.renderable.setCurrentAnimation('spindown','neutral');
				//me.audio.play('trapdoor');
			}else{
				this.grinding = true;
				this.delayTime = this.delayTimeOn;
				me.audio.play('grinder',false, null, 0.2);
				//this.delayCounter = 0;
				this.renderable.setCurrentAnimation('spinup','grind');
				//me.audio.play('trapdoor');
			}
		}
		
		//if colliding and not opened, set spy vel.x = 0
		if(this.grinding && spy.alive){
			if(this.renderable.isCurrentAnimation('grind')){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){				
				if(this.colOverlaps(spy.collisionBox)){				
					//console.log('caught');
					spy.caughtKnockedDown();
				}
			}
		}
		
		this.parent(this);
		return true;
		}
	}
});




var LaserBeamEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		//automatically adjust sprite, width, and height
		//console.log('laser width: ' + settings.width);
		if(settings.width > settings.height){
			settings.direction = 'h';
		}
		
		this.flameOn = false;
		if(settings.direction == 'h'){
			settings.spriteheight = 16;
			settings.spritewidth = settings.width;
			settings.image = 'electricarc' + settings.width + 'h';
			if(settings.width == '48'){
				this.flameOn = true;
			}
			if(settings.vr){
				settings.image = 'vr_fire_horiz';
			}
		}else{
			settings.spritewidth = 16;
			settings.spriteheight = settings.height;
			settings.image = 'electricarc' + settings.height;
			if(settings.height == '48'){
				this.flameOn = true;
			}
			
			if(settings.vr){
				settings.image = 'vr_fire_vert';
			}
		}		
		
		/*
		this.laserName = settings.laserName;
		this.lastName = this.laserName;
		console.log(this.laserName + ' d: ' + settings.direction + ' h: ' + settings.height + ' w:' + settings.width + ' img:' + settings.image + ' flame:' + this.flameOn+ ' last name:' + this.lastName);
		*/
		
		if(settings.image != 'laserbeam'){
			this.electricArc = true;			
		}else{
			settings.image = 'laserbeam';
		}
		
		//console.log('laser image: ' + settings.image);
		
		
		this.parent(x,y,settings);
		this.collidable = false;
		
		if(settings.direction == 'h'){
			if(this.flameOn){
				this.updateColRect(2,settings.width-4,4,8);
			}else{
				this.updateColRect(1,settings.width-2,4,8);
			}
		}else{
			//console.log(this.collisionBox);
			if(this.flameOn){
				this.updateColRect(4,8,2,settings.height-4);
			}else{
				this.updateColRect(4,8,0,settings.height);
			}
		}
		
		this.direction = settings.direction;		
		this.laserName = settings.laserName;
		this.laserGroup = (settings.laserGroup) ? settings.laserGroup : 0;
		this.gravity = (0);
		//Do animations for:
		//if this direction left
		//if this direction right
		//if this direction down
		//console.log(this.laserName + ' d: ' + settings.direction + ' h: ' + settings.height + ' w:' + settings.width + ' img:' + settings.image + ' flame:' + this.flameOn+ ' last name:' + this.lastName);
		if(settings.flipY){
			this.flipY(true);
		}		
		
		if(settings.flipX){
			this.flipX(true);
		}	
		
		this.isTriggered = false;	
		
		if(settings.height == 48 || settings.width == 48){
			this.renderable.addAnimation('neutral', [0]);
			this.renderable.addAnimation('turnItUp',[1],3);
			this.renderable.addAnimation('fire', [2,3],3);
			this.renderable.setCurrentAnimation('neutral');
		}else if(this.electricArc){
			this.renderable.addAnimation('neutral', [0]);			
			this.renderable.addAnimation('turnItUp',[1],3);
			this.renderable.addAnimation('fire', [1,2,3],3);
			this.renderable.setCurrentAnimation('neutral');
		}else{		
			this.renderable.alpha = 0;
		}
	},
	update: function(){
	/*
		if(ScreenTransitionStart){
			this.powerDown();
		}
	*/	
		if(this.isTriggered && this.inViewport){
			
			/*
			var results = me.game.collide(this, true);
			var resL = results.length;
			var index = 0;
			for(index; index < resL; ++index){
				var res = results[index];
				if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
				//console.log('caught');
					if(this.flameOn){
						spy.caughtBeam('','burning');
					}else{
						spy.caughtBeam('','shocked');
					}
				
				}
			} */
			
			if(spy.alive && !spy.isCaught && this.colOverlaps(spy.collisionBox)){
				//console.log('caught');
				if(this.flameOn){
					console.log('y: ' + this.pos.y + 'top: ' + this.collisionBox.top + ' bottom:' + this.collisionBox.bottom+ ' spy bottom:' + spy.collisionBox.bottom);
					spy.caughtBeam('','burning');
				}else{
					spy.caughtBeam('','shocked');
				}
			
			}
		}
		this.parent(this);
		return true;
	},
	shoot: function(){
		if(this.electricArc){
			

			if(this.inViewport){

				if(this.flameOn){
					me.audio.play('firejet', false, null, 0.2);
					//console.log(this.laserName);
					this.renderable.setCurrentAnimation('turnItUp','fire');
				}else{
					me.audio.play('electricspark', false, null, 0.2);
					this.renderable.setCurrentAnimation('fire');
				}
				this.isTriggered = true;
			}
		}else{
			this.renderable.alpha = 1;			
			this.isTriggered = true;
		}
		//this.isTriggered = true;
		//console.log(this.laserName);
	},
	powerDown: function(){
		if(this.electricArc){
			this.renderable.setCurrentAnimation('neutral');
		}else{
			this.renderable.alpha = 0;
		}
		this.isTriggered = false;
	}
});

var LaserCoordinatorEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = (0);
		
		this.alwaysUpdate = true;
		
		this.renderable.addAnimation('neutral', [0]);
		//this.renderable.addAnimation('triggered', [1]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.deviceName = settings.trapName;
		
		//get array of laser names from settings. Will be in order of array
		//get laser timings from settings as well. Default to something like 30 or 60.
		//Have option for pause/delay between laser firings.
		
		this.laserGroupName = (settings.laserGroup) ? settings.laserGroup : 0;
		
		this.endDelay = (settings.endDelay) ? settings.endDelay : 0;
		//console.log(settings.lasers);
		this.laserNames = settings.lasers.split(',');
		this.laserTimes = settings.laserTimes.split(',');
		this.laserPauses = (settings.laserPauses) ? settings.laserPauses.split(','):'';
		
		//Probably should add default laser times
		
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.increasePause = true;
		}else{
			this.increasePause = false;
		}

		this.delayTime = this.laserTimes[0];
		this.delayCounter = this.laserTimes[0];
		this.delayCounter = 1;
		
		

		if(this.increasePause){
			for(var ilp = 0; ilp < this.laserPauses.length; ilp++){
				//Only add time if it's the last laser AND it's the only laser
				if(this.laserPauses.length > 1 && ilp == this.laserPauses.length - 1){
					this.laserPauses[ilp] = parseFloat(this.laserPauses[ilp]) + parseFloat(15); //this.laserPauses[i]
				}
				/*
				if(this.laserPauses.length > 1){
					this.laserPauses[ilp] = parseFloat(this.laserPauses[ilp]) + parseFloat(15); //this.laserPauses[i]
				}else if(this.laserPauses[ilp] != 0){
					this.laserPauses[ilp] = parseFloat(this.laserPauses[ilp]) + parseFloat(15); //this.laserPauses[i]
				}
				*/
			}
		}
		
		this.pauseTime = this.laserPauses[0];
		
		this.pauseCounter = 0;
		
		//console.log(this.laserPauses);
		
		this.pauseLaser = false;
		
		this.laserPos = 0;
		this.laserCount = this.laserNames.length - 1;	

		//Initialize 1st Laser
		this.initializeLaser = true;
		
		//offset delay
		this.offSetStartTime = (settings.offSetStart) ? settings.offSetStart : 0;
		this.offSetStartCounter = 1;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		//console.log(this.laserGroupName + ' Delay: ' + this.delayCounter + ' Pause: ' + this.pauseCounter + ' ' + me.timer.getTime());
		
		//resync them here on screen transition
		if(ScreenTransitionStart && !this.inViewport){ 
			this.powerDownLasers();
			this.delayTime = this.laserTimes[0];
			this.delayCounter = this.laserTimes[0];
			this.delayCounter = 1;
			
			this.offSetStartCounter = 1;
			
			this.pauseTime = this.laserPauses[0];
			this.pauseCounter = 0;
			this.pauseLaser = false;
			this.laserPos = 0;
			this.laserCount = this.laserNames.length - 1;
			this.initializeLaser = true;
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
		if(this.offSetStartCounter < this.offSetStartTime){
			this.offSetStartCounter += 1 * me.timer.tick;
		}else if(this.initializeLaser){
			//fire first laser here
			this.initializeLaser = false;
			this.fireLaser();
			this.delayCounter += 1 * me.timer.tick;
			//this.delayTime -= 1;
			//this.pauseTime -= 1;
		}else{
		
		
		//at the end of pause, fire lasers
		//at the end of delay, turn off lasers
		
		

			if(!this.pauseLaser){
			//It's cool to fire lasers
				if(this.delayCounter < this.delayTime){
					this.delayCounter += 1 * me.timer.tick;
				}else{
					//console.log('Laser: ' + this.delayCounter + ' ' + me.timer.getTime());
					this.powerDownLasers();
					//console.log(this.pauseTime);
					//if(this.pauseLaser){
						//this.fireLaser();
					//}	
					this.pauseLaser = true;
					this.delayCounter = 1;	
					this.pauseCounter = 0;						
				}
			}
			
			//Check if paused, run through timer
			if(this.pauseLaser){
				if(this.pauseCounter < this.pauseTime && this.pauseTime != 0){
					this.pauseCounter += 1 * me.timer.tick;
				}else{
					this.fireLaser();
					this.pauseLaser = false;				
					this.pauseCounter = 1;	
					this.delayCounter = 1;
					
				}		
			}
		}
		
		this.parent(this);
		return true;
		
		}
	},
	fireLaser: function(){		
		//console.log(this.laserGroupName + ' ' + this.pauseCounter + ' ' + me.timer.getTime() + ' (pause)');
		/*
		if(this.inViewport){
			me.audio.play('saw');
		}*/
		
		//turn on laser			
		var lasers = me.game.getEntityByProp('laserName',this.laserNames[this.laserPos]);
		for(var i = 0; i < lasers.length; i++){
				lasers[i].shoot();	

				//console.log(this.laserNames[this.laserPos] + ' FIRE!');
		}
		
		this.delayTime = this.laserTimes[this.laserPos];		
		this.pauseTime = this.laserPauses[this.laserPos];

			
		//advance the laser
		if(this.laserPos >= this.laserCount){
			this.laserPos = 0;				
		}else{
			this.laserPos++;				
		}
	},
	powerDownLasers: function(){
		//console.log(this.laserGroupName + ' ' + this.delayCounter + ' ' + me.timer.getTime() + ' (delay)');
		//
		//if(this.pauseTime > 0){			
			
		//}
		//turn off lasers
		var lasers = me.game.getEntityByProp('laserGroup',this.laserGroupName);
		for(var i = 0; i < lasers.length; i++){
				lasers[i].powerDown();
		}
	}
});

/* ---------------------
a horizontal robot crusher thing entity
just moves right/left, maybe with a brief pause at either side?
it's 3 tiles wide and if it hits you you get KO'd
----------------------*/
var HorizontalCrusherEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = 0;
		
		this.alwaysUpdate = true;
		//this.updateColRect(2,12,2,28);
		//Needs to be faster than invisible speed of spy
		this.setVelocity(6,0);
		this.velx = 4;
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.playSFX = (settings.playSFX) ? settings.playSFX : false;		
		this.screenShake = (settings.screenShake) ? settings.screenShake : false;		
		if(gameData.load('screenshakeDisabled') == 'yes'){
			this.screenShake = false;
		}
		this.moveDistance = (settings.moveDistance) ? settings.moveDistance : 16;
		if(settings.flipX){
			this.flipX(true);
		}
		this.startDelayCounter = 1;
		
		//Set it up to move back and forth
		this.startX = x;
		
		
		if(settings.startSide == 'left'){
			//this.pos.x = this.startX;
			this.goLeft = false;
			this.startSide = false;
			this.endX = this.startX + this.moveDistance;
			this.lX = this.startX;
			this.rX = this.startX + this.moveDistance;			
		}else{
			//this.pos.x = x + settings.width - settings.spritewidth;
			this.goLeft = true;
			this.startSide = true;
			this.endX = this.startX - this.moveDistance;
			this.lX = this.startX - this.moveDistance;
			this.rX = this.startX;
		}
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
			
		this.delayCounter = 1;
		
		this.delayTime = 30;
		
		this.delayTime = (this.moveDistance / 16) * 7.5;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTimeOff = 84; //this.delayTime * 12;
			this.delayTimeOn = this.delayTime;
		}else{
			this.delayTimeOff = this.delayTime;
			this.delayTimeOn = this.delayTime;
		}
		
		this.moveAmount = 0;
				
		this.renderable.addAnimation('idle', [0]);
		//this.renderable.addAnimation('left', [1]);
		//this.renderable.addAnimation('right', [2]);
		this.renderable.setCurrentAnimation('idle');
		
	},
	update:function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.delayCounter = 1;
			this.delayTime = this.delayTimeOn;
			this.moveAmount = 0;
			this.goLeft = this.startSide;
			this.renderable.setCurrentAnimation('idle');
			this.pos.x = this.startPosX;
			this.pos.y = this.startPosY;
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
		
		
		if(this.delayCounter < this.delayTime){
			this.delayCounter += 1 * me.timer.tick;
		}else{
			//Check if it should go left or right
			this.delayCounter = 1;
			this.moveAmount = 0;
			if(this.goLeft){
				this.goLeft = false;
				if(!this.startSide){
					this.delayTime = this.delayTimeOn;
				}else{
					this.delayTime = this.delayTimeOff;
				}
			}else{
				this.goLeft = true;
				if(this.startSide){
					this.delayTime = this.delayTimeOn;
				}else{
					this.delayTime = this.delayTimeOff;
				}
			}
			/*
			if(this.screenShake){
				me.game.viewport.shake(4,20, me.game.viewport.AXIS.BOTH);
			}
			*/
		}
		
		
		
		if(this.moveAmount < this.moveDistance){
			this.moveAmount += this.velx;
			
			//need a check here for not going out of 16
			//also need a slight screen shake when it hits a wall or something
			if(!this.goLeft && (this.pos.x + this.velx > this.rX)){
				this.pos.x = this.rX;
			}else if(this.goLeft &&  (this.pos.x - this.velx < this.lX)){
				this.pos.x = this.lX;
			}else{
				//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				this.pos.x += (this.goLeft) ? -this.velx * me.timer.tick : this.velx * me.timer.tick;
			}
			
			if(this.pos.x == this.rX){
				//console.log('hello crusher?');
				//this.renderable.setCurrentAnimation('right','idle');
				if(this.screenShake && !this.startSide && this.inViewport){
					me.game.viewport.shake(10,100, me.game.viewport.AXIS.X); //Both
				}
				
				if(this.playSFX && !this.startSide && this.inViewport){
					me.audio.play('crusherfall');
				}
			}else if(this.pos.x == this.lX){
				//this.renderable.setCurrentAnimation('left','idle');
				if(this.screenShake && this.startSide && this.inViewport){
					me.game.viewport.shake(10,100, me.game.viewport.AXIS.X); //Both
					
				}
				if(this.playSFX && this.startSide && this.inViewport){
					me.audio.play('crusherfall');
				}
				
			}
			
			this.updateMovement();
			
		}
		
		
			//var res = me.game.collide(this);
			
			//if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
			if(spy.alive && !spy.isCaught && this.colOverlaps(spy.collisionBox)){
				//console.log('caught');
				
				if(this.goLeft){
					direction = 'right';
				}else{
					direction = 'left';
				}
				
				spy.caughtKnockedDown(direction);
				
				//spy.caught();
			}
			
		this.parent(this);
		return true;
		
		}
	}
});

/* ---------------------
a vertical robot crusher thing entity
just moves up/down, maybe with a brief pause at either side?
it's 2 tiles wide and if it hits you you get KO'd
----------------------*/
var VerticalCrusherEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = 0;
		
		this.alwaysUpdate = true;
		//this.updateColRect(2,12,2,28);
		//Needs to be faster than invisible speed of spy
		this.setVelocity(0,6);
		this.vely = 6;
		//Check for and set a startDelay (in frames)
		this.barrierName = (settings.barrierName) ? settings.barrierName : false;		
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.screenShake = (settings.screenShake) ? settings.screenShake : true;	
		if(gameData.load('screenshakeDisabled') == 'yes'){
			this.screenShake = false;
		}		
		
		this.moveDistance = (settings.moveDistance) ? settings.moveDistance : 16;		
		this.startDelayCounter = 1;
		
		//Set it up to move back and forth
		this.startY = y;
		
		//left is top
		if(settings.startSide == 'left'){
			//this.pos.x = this.startX;
			this.goLeft = false;
			this.startSide = false;
			this.endY = this.startY + this.moveDistance;
			this.lY = this.startY;
			this.rY = this.startY + this.moveDistance;			
		}else{
			//this.pos.x = x + settings.width - settings.spritewidth;
			this.goLeft = true;
			this.startSide = true;
			this.endY = this.startY - this.moveDistance;
			this.lY = this.startY - this.moveDistance;
			this.rY = this.startY;
		}
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		//console.log('Crusher: startY ' + this.startY + " endY " + this.endY + ' lY: ' + this.lY + ' rY: ' + this.rY + ' Move Distance: ' + this.moveDistance);
		
		this.delayCounter = 1;
		
		this.delayTime = 30;
		
		this.delayTime = (this.moveDistance / 16) * 15;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTimeOff = 90;
			this.delayTimeOn = this.delayTime;
		}else{
			this.delayTimeOff = this.delayTime;
			this.delayTimeOn = this.delayTime;
		}
		
		this.moveAmount = 0;
				
		this.renderable.addAnimation('idle', [0]);
		//this.renderable.addAnimation('left', [1]);
		//his.renderable.addAnimation('right', [2]);
		this.renderable.setCurrentAnimation('idle');
		
		this.stopped = true;
		this.leftX = this.collisionBox.left;
		this.rightX = this.collisionBox.right;
		
	},
	update:function(){
		if(ScreenTransitionStart && !this.inViewport){ 
			this.delayCounter = 1;
			this.moveAmount = 0;
			this.goLeft = this.startSide;
			this.renderable.setCurrentAnimation('idle');
			this.pos.x = this.startPosX;
			this.pos.y = this.startPosY;
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
		
		
		if(this.delayCounter < this.delayTime){
			this.delayCounter += 1 * me.timer.tick;
		}else{
			//Check if it should go left or right
			this.delayCounter = 1;
			this.moveAmount = 0;
			if(this.goLeft){
				this.goLeft = false;
				this.stopped = false;
				this.crushing = true;

				this.delayTime = this.delayTimeOn;
			}else{
				this.goLeft = true;
				this.delayTime = this.delayTimeOff;
				
			}
			
			//this.stopped = false;	
			//console.log('Stopped: false');
		}
		
		
		
		if(this.moveAmount < this.moveDistance){
			this.moveAmount += this.vely;
			
			//need a check here for not going out of 16
			//also need a slight screen shake when it hits a wall or something
			if(!this.goLeft && (this.pos.y + this.vely > this.rY)){
				this.pos.y = this.rY;
			}else if(this.goLeft &&  (this.pos.y - this.vely < this.lY)){
				this.pos.y = this.lY;
			}else{
				//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				this.pos.y += (this.goLeft) ? -this.vely * me.timer.tick : this.vely * me.timer.tick;
			}
			
			if(this.pos.y == this.rY){
				//this.renderable.setCurrentAnimation('right','idle');
				if(this.inViewport){
					if(this.screenShake){ 
						me.game.viewport.shake(10,100, me.game.viewport.AXIS.Y); //BOTH
					}
					me.audio.play('crusherfall');
				}
				this.stopped = true;
				this.crushing = false;
			}else if(this.pos.y == this.lY){
				//this.renderable.setCurrentAnimation('left','idle');
				this.stopped = true;
			}
			
			this.updateMovement();
			
		}
		
		/*
			var res = me.game.collide(this);
			
			if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
				console.log('caught');
				
				if(this.goLeft){
					var direction = 'right';
				}else{
					var direction = 'left';
				}
				
				spy.caughtKnockedDown(direction);
				
				//spy.caught();
			}
		*/

			if(this.stopped && !this.crushing){
					//console.log('Stopped!');			
					//var res = me.game.collide(this);
					//if(res && (res.obj.type == me.game.SPY)){				
					if(this.colOverlaps(spy.collisionBox)){				
						//compare spy's direction and the side being collided against
						if((spy.collisionBox.left > this.leftX && !spy.currentDirection) || (spy.collisionBox.right < this.rightX && spy.currentDirection)){		
							spy.stopX = true;
							spy.stopXBarrier = this.barrierName;
						}else{
							spy.stopX = false;
							spy.stopXBarrier = this.barrierName;
						}						
					}else{	
						if(spy.stopX && spy.stopXBarrier == this.barrierName){
							spy.stopXBarrier = false;
							spy.stopX = false;
						}
					}
					
					
			}else{
				spy.stopX = false;
				
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY) && spy.alive){
				if(spy.alive && this.colOverlaps(spy.collisionBox)){
					//console.log('caught');
					spy.caughtKnockedDown();
				}
			}		
			this.parent(this);
			return true;
		
		}
	}
});

/* ---------------------
Robot Guard Entity
Moves back and forth like a normal guard, but is time synced
----------------------*/
var RobotGuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = 0;
		
		this.alwaysUpdate = true;
		//this.updateColRect(2,12,2,28);
		//Needs to be faster than invisible speed of spy
		this.setVelocity(1,0);
		this.velx = 1.5;
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		//this.moveDistance = (settings.moveDistance) ? settings.moveDistance : 16;		
		this.startDelayCounter = 1;
		
		//Set it up to move back and forth
		this.startX = x;
		
		//this is the codessss
		
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;	
		
//		console.log('Robot: ' + this.startX + " " + this.endX);
		this.moveDistance = this.endX - this.startX;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
				
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.goLeft = false;
			this.startSide = false;
			
			this.flipX(true);
		}else{
			//this.pos.x = x + settings.width - settings.spritewidth;
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.goLeft = true;
			this.startSide = true;
		}
		
		//this.endX = this.startX + this.moveDistance;
		this.lX = this.startX;
		this.rX = this.startX + this.moveDistance;
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		this.delayCounter = 1;
		
		this.delayTime = 30;
		
		//this.delayTime = (this.moveDistance / 16) * 30;
		this.delayTime = (this.moveDistance / 16) * 15;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.delayTime = (this.moveDistance / 16) * 20;
			this.velx = 1.2;
		}else{
			this.delayTime = (this.moveDistance / 16) * 15;
			this.velx = 1.5;
		}
		
		this.moveAmount = 0;
				
		this.renderable.addAnimation('idle', [0]);
		this.renderable.addAnimation('patrol', [0,1,2,3]);
		this.renderable.addAnimation('alarmed', [5,6]);
		this.renderable.addAnimation('gunOut', [4]);
		this.renderable.setCurrentAnimation('patrol');
		
		//console.log('Robot: startX ' + this.startX + " endX " + this.endX + ' lX: ' + this.lX + ' rX: ' + this.rX);
		
		this.spyCaught = false;


		//Code for including/excluding in novice mode 
		this.removeImmediately = false;

		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update:function(){
		if(this.removeImmediately){ me.game.remove(this); }
		if(ScreenTransitionStart && !this.inViewport){ 
			this.delayCounter = 1;
			this.moveAmount = 0;
			this.goLeft = this.startSide;
			this.flipX(!this.goLeft);
			this.renderable.setCurrentAnimation('idle');
			this.pos.x = this.startPosX;
			this.pos.y = this.startPosY;
			this.parent(this);
			return true;
		}else if(this.inViewport || (ScreenTransitionState && !this.inViewport)){
		
		
		if(!this.spyCaught){
			if(this.delayCounter < this.delayTime){
				this.delayCounter += 1 * me.timer.tick;
			}else{
				//Check if it should go left or right
				this.delayCounter = 1;
				this.moveAmount = 0;
				if(this.inViewport){
					me.audio.play('robotsfx', false, null, 0.2);
				}
				if(this.goLeft){
					this.goLeft = false;
				}else{
					this.goLeft = true;
				}
				
				this.flipX(!this.goLeft);
				//me.game.viewport.shake(4,20, me.game.viewport.AXIS.BOTH);
			}
			
			
			
			if(this.moveAmount < this.moveDistance){
				this.moveAmount += this.velx;
				this.renderable.setCurrentAnimation('patrol');
				//need a check here for not going out of 16
				if(!this.goLeft && (this.pos.x + this.velx > this.rX)){
					this.pos.x = this.rX;
				}else if(this.goLeft &&  (this.pos.x - this.velx < this.lX)){
					this.pos.x = this.lX;
				}else{
					//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
					this.pos.x += (this.goLeft) ? -this.velx * me.timer.tick : this.velx * me.timer.tick;
				}
				
				//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				
				/*
				if(this.pos.x == this.rX){
					this.renderable.setCurrentAnimation('idle');
				}else if(this.pos.x == this.lX){
					this.renderable.setCurrentAnimation('idle');
				}
				*/
				
				this.updateMovement();
				
			}
		}
		//Collision Detection
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		if(spy.alive){
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.goLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.goLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.spyCaught = true;
						this.renderable.setCurrentAnimation('gunOut');
						//check side
						/*
						
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
						*/

						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					//console.log('Caught!');
					if(this.goLeft){
						direction = 'right';
					}else{
						direction = 'left';
					}
					
					spy.caughtKnockedDown(direction);
					this.renderable.setCurrentAnimation('gunOut');
					this.spyCaught = true;
					//check side
					/*
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}
					*/

					//check side
					if(me.gamestat.getItemValue('currentMode') == 'ghost'){
						if(this.pos.x > spy.pos.x){
							this.flipX(true);
						}else{
							this.flipX(false);
						}
					}else{
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
					}

				}
			}
		}else if(spy.isCaught){	
			if(!this.renderable.isCurrentAnimation('gunOut')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
				this.spyCaught = true;
			}
		}
		
		/*
			var res = me.game.collide(this);
			
			if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
				console.log('caught');
				
				if(this.goLeft){
					direction = 'right';
				}else{
					direction = 'left';
				}
				
				spy.caughtKnockedDown(direction);
				
				//spy.caught();
			}
		*/	
		this.parent(this);
		return true;
		
		}
	}
});


/* ---------------------
Security Bot Entity
Moves in bursts
Sees in direction it's moving 
----------------------*/
var SecurityBotEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		//this.updateColRect(2,12,2,28);
		//Needs to be faster than invisible speed of spy
		this.setVelocity(2.5,0);
		this.velx = 4;
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.moveDistance = (settings.moveDistance) ? settings.moveDistance : 16;		
		this.startDelayCounter = 0;
		
		//Set it up to move back and forth
		this.startX = x;
		
		
		if(settings.startSide == 'left'){
			//this.pos.x = this.startX;
			this.goLeft = false;
			this.endX = this.startX + this.moveDistance;
			this.lX = this.startX;
			this.rX = this.startX + this.moveDistance;			
		}else{
			//this.pos.x = x + settings.width - settings.spritewidth;
			this.goLeft = true;
			this.endX = this.startX - this.moveDistance;
			this.lX = this.startX - this.moveDistance;
			this.rX = this.startX;
		}
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		this.delayCounter = 1;
		this.delayTime = 30;
		
		this.moveAmount = 0;
		
		this.renderable.addAnimation('beam', [0]);
	},
	update:function(){
		//if(this.resetCheck(this.startPosX,this.startPosY, false)) return false;
		
		if(ScreenTransitionStart && !this.inViewport){ 
			this.pos.x = this.startPosX;
			this.parent(this);
			return true;
		}
		
		
		/*
		if(!ScreenTransitionState && !this.inViewport){
			this.parent(this);
			return true;
		}
		*/
		
		
		if(this.delayCounter < this.delayTime){
			this.delayCounter += 1 * me.timer.tick;
		}else{
			//Check if it should go left or right
			this.delayCounter = 1;
			this.moveAmount = 0;
			if(this.goLeft){
				this.goLeft = false;
			}else{
				this.goLeft = true;
			}
		}
		
		//
		
		
		
		if(this.moveAmount < this.moveDistance){
			this.moveAmount += this.velx;
			
			//need a check here for not going out of 16
			//also need a slight screen shake when it hits a wall or something
			if(!this.goLeft && (this.pos.x + this.velx > this.rX)){
				this.pos.x = this.rX;
			}else if(this.goLeft &&  (this.pos.x - this.velx < this.lX)){
				this.pos.x = this.lX;
			}else{
				//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				this.pos.x += (this.goLeft) ? -this.velx * me.timer.tick : this.velx * me.timer.tick;
			}
			this.updateMovement();
			
		}
		
		//var res = me.game.collide(this);
		
		//if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
		if(spy.alive && !spy.isCaught && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			
			if(this.goLeft){
				direction = 'right';
			}else{
				direction = 'left';
			}
			
			spy.caughtKnockedDown(direction);
			
			//spy.caught();
		}
		
		this.parent(this);
		return true;
		
	}
});


/* ---------------------
a security camera bot entity
----------------------*/

var NotAsOldSecurityCameraBotEntity = enemyEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		
		this.velx = 1;
		this.gravity = 0;
		
		//Start Position, Move Area
		//TODO: Add margins
		this.pos.x = (!settings.offSetX) ? x : x + settings.offSetX;
		
		
		
		//Check for and set a startDelay (in frames)
		this.startDelay = (settings.startDelay) ? settings.startDelay : 0;		
		this.moveDistance = (settings.moveDistance) ? settings.moveDistance : 32;		
		this.startDelayCounter = 0;
		
		//Set it up to move back and forth
		this.startX = this.pos.x;
		this.endX = x + settings.width - this.moveDistance;
		
		if(settings.startSide == 'left'){
			//this.pos.x = this.startX;
			this.goLeft = false;
			this.flipX(true);
		}else{
			//this.pos.x = x + settings.width - settings.spritewidth;
			this.goLeft = true;
			this.flipX(false);			
		}
		
		this.lX = this.startX;
		this.rX = this.startX + settings.width - this.moveDistance;
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		
		this.delayCounter = 1;
		this.delayTime = 90;
		
		this.moveAmount = 0;
		
		//Up/Down Bounce
		this.pos.y += 4;
		this.hoverCounter = 0;
		this.hoverUp = true;
		
		this.renderable.addAnimation('stationary',[0,1],2);
		this.renderable.addAnimation('blink',[3,4],2);
		this.renderable.addAnimation('rotate',[2],8);
		
		this.renderable.setCurrentAnimation('stationary');
		
		
	},update:function(){
		//console.log(this.pos.x);
		//move back and forth
		
		//Movement:
		//moves forward 1 tile each second
		//Maybe have it sweep back and forth when it stops?
		
		
		//step through moving on y
		if(this.hoverUp){
			this.pos.y += .1 * me.timer.tick;
			this.hoverCounter += me.timer.tick;
			if(this.hoverCounter >= 30){
				this.hoverUp = false;
			}
		}else if(!this.hoverUp){
			this.pos.y -= .1 * me.timer.tick;
			this.hoverCounter -= me.timer.tick;
			if(this.hoverCounter <= 0){
				this.hoverUp = true;
			}
		}
		
		//Move on X in intervals
		if(this.delayCounter < this.delayTime){
			this.delayCounter += 1 * me.timer.tick;
		}else{
			//Check if it should go left or right
			this.delayCounter = 1;
			this.moveAmount = 0;
			
			//Check to see which direction to move in
			if(this.goLeft && this.pos.x <= this.startX){
				this.goLeft = false;
				this.flipX(false);
			}else if(!this.goLeft && this.pos.x >= this.endX){
				this.goLeft = true;
				this.flipX(true);
			}
		}		
		
		
		if(this.moveAmount < this.moveDistance){
			this.moveAmount += this.velx;
			
			//need a check here for not going out of 16
			//also need a slight screen shake when it hits a wall or something
			/*
			if(!this.goLeft && (this.pos.x + this.velx > this.endX)){
				this.pos.x = this.endX;
			}else if(this.goLeft &&  (this.pos.x - this.velx < this.lX)){
				this.pos.x = this.lX;
			}else{
			*/
				//this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				this.pos.x += (this.goLeft) ? -this.velx * me.timer.tick : this.velx * me.timer.tick;
			//}
		}
		
		this.updateMovement();
		
		this.parent(this);
		return true;
	}	
});

/* ---------------------
a security camera bot entity
now with 100% more lazy!
----------------------*/

var SecurityCameraBotEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		settings.spriteheight = 16;
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		
		this.velx = 1;
		this.gravity = 0;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		
		
		if(settings.startSide == 'left'){	
			this.dangerZoneLeft = x + 20;
			this.dangerZoneRight = x + settings.width;
		}else{
			this.dangerZoneLeft = x;
			this.dangerZoneRight = x + settings.width - 20;
		}
		
		this.image = settings.image;
		
		//Up/Down Bounce
		this.pos.y += 4;
		this.hoverCounter = 0;
		this.hoverUp = true;
		
		//set up animations
		this.renderable.addAnimation('stationary',[0,1],2);
		this.renderable.addAnimation('blink',[3,4],2);
		this.renderable.addAnimation('rotate',[2],8);
		
		this.renderable.setCurrentAnimation('stationary');
		
		this.animationC = 0;
		
		//Position guard
		if(settings.startSide == 'left'){
			this.pos.x = x;
			this.flipX(false);
		
		}else{
			this.flipX(true);
			this.pos.x = x + settings.width - settings.spritewidth;
		}


		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		//step through moving on y
		if(this.hoverUp){
			this.pos.y += .1 * me.timer.tick;
			this.hoverCounter += me.timer.tick;
			if(this.hoverCounter >= 30){
				this.hoverUp = false;
			}
		}else if(!this.hoverUp){
			this.pos.y -= .1 * me.timer.tick;
			this.hoverCounter -= me.timer.tick;
			if(this.hoverCounter <= 0){
				this.hoverUp = true;
			}
		}
				
		if(!spy.stealthOn && spy.alive){	
			//Is the spy in view of the guard?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .8 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				spy.caught();
				this.renderable.setCurrentAnimation('blink');
				//check side
				/*
				if(this.pos.x > spy.pos.x){
					this.flipX(false);
				}else{
					this.flipX(true);
				}
				*/
			}		
		}
		
		if(spy.isCaught){
			this.renderable.setCurrentAnimation('blink');
		}
		
		//If spy is in dangerzone and not cloaked, caught!
		this.parent(this);
		return true;
	}
	
});

/* ---------------------
	Mission 5
----------------------*/


/* ---------------------
a security guard booth entity
----------------------*/

var NoCloakEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.collidable = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x + 8;
		this.dangerZoneRight = x + settings.width - 8;
		
		//set up animations
		this.renderable.addAnimation('nocloak',[0,1,2,3],2);
		//this.renderable.addAnimation('catch',[3,4],2);
		this.renderable.setCurrentAnimation('nocloak');
		
		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
				
		if(spy.stealthOn && spy.alive){	
			//Is the spy in view of the guard?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				//spy.caught();
				spy.caughtBeam('','shocked');
				//this.renderable.setCurrentAnimation('catch');
			}			
		}		
		
		//If spy is in dangerzone and not cloaked, caught!
		this.parent(this);
		return true;
	}
	
});

/* ---------------------
a elite guard entity
----------------------*/

var EliteGuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		//Set Position and walking boundaries
		//Will Check for custom StartX and StopX from Tiled
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;				
		
		//Set up delay at end of walk cycle
		this.doDelay = false;
		this.stillTime = 60;
		this.isStill = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Need additional area that he can patrol
		
		
		//add animation
		/*
		this.renderable.addAnimation('walk', [0,1,2,3],7);		
		this.renderable.addAnimation('catch', [4]);
		this.renderable.addAnimation('stand', [3]);
		this.renderable.setCurrentAnimation('walk');
		this.renderable.addAnimation('alert',[5]);
		this.renderable.addAnimation('alarmed',[5,6],60);
		*/
		this.animationspeed = me.sys.fps / 6;
		
		
		this.renderable.addAnimation('walk', [0,1,2,3,4,5],6);	
		this.renderable.addAnimation('walkAlert', [7,8,9,10,11,12],6);	
		this.renderable.addAnimation('catch', [13]);
		this.renderable.addAnimation('stand', [14]);
		this.renderable.setCurrentAnimation('walk');
		this.renderable.addAnimation('alert',[6]);
		this.renderable.addAnimation('alarmed',[14,15],60);
		
		
		//Start on the right and make walk left
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.walkLeft = false;
			this.flipX(true);
			if(settings.startOffset) this.pos.x += settings.startOffset;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.walkLeft = true;
			this.flipX(false);
			if(settings.startOffset) this.pos.x -= settings.startOffset;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
		
		this.turnDelay = 6;
		this.turnCounter = 0;
		this.doTurn = false;
		this.turnDirection;

		this.stillDelay = 60;
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.turnDelay = 12;
			this.stillDelay = 120;
		}
		
		this.stillTime = this.stillDelay;
		
		this.isAlert = false;
		this.caught = false;

		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		//var caught = false;
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//console.log(this.inViewport);
		
		//TODO: Check to see if spy has landed anywhere in the guard's perimiter.
		//If Spy has, pause, change to direction that spy was in
		//if(Spy.wasFalling)
		if(spy.alive && !this.caught){
			//if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){	
			
			
			//Check to see if spy has landed in the danger zone!
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
				
				if(spy.wasFalling && !spy.falling){
					if(spy.pos.x > this.pos.x && this.walkLeft != false){
						this.doTurn = true;
						this.turnDirection = 'right';
						this.turnCounter = 0;						
					}else if(spy.pos.x < this.pos.x && this.walkLeft != true){
						this.doTurn = true;
						this.turnDirection = 'left';
						this.turnCounter = 0;
					}
					this.isAlert = true;
				}
			}
			
			if(this.doTurn){
				if(this.turnCounter < this.turnDelay){
					this.turnCounter++;
					this.vel.x = 0;
					this.renderable.setCurrentAnimation('alert');
				}else{
					me.audio.play('guardwhat');
					this.turnCounter = 0;
					this.doTurn = false;
					if(this.turnDirection == 'left'){
						this.flipX(false);
						this.walkLeft = true;
					}else{						
						this.flipX(true);
						this.walkLeft = false;
					}
				}
			}
			
			if(this.walkLeft && this.pos.x <= this.startX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(true);
					this.walkLeft = false;
				}
			}else if(!this.walkLeft && this.pos.x >= this.endX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(false);
					this.walkLeft = true;
					
				}
			}
			
			//Delay here if set
			if(this.doDelay){
				if(this.isStill && this.stillTime > 0){
					this.stillTime -= 1;
				}else if(this.stillTime === 0){
					this.isStill = false;
					this.stillTime = this.stillDelay;
					this.renderable.setCurrentAnimation('walk');
					if(this.walkLeft){
						this.flipX(true);
						this.walkLeft = false;
					}else if(!this.walkLeft){
						this.flipX(false);
						this.walkLeft = true;
					}
				}
			}	
			//}
			
			if(!this.doTurn){
				if(this.isAlert){
					this.renderable.setCurrentAnimation('walkAlert');
				}else{
					this.renderable.setCurrentAnimation('walk');
				}
				this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				if(this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2) me.audio.play('guardstep', false, null, 0.4);
			}
			
			this.updateMovement();
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.caught = true;
						this.renderable.setCurrentAnimation('catch');
						//check side
						/*
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
						*/

						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				
				
				var colres = this.collide(true)
				if(colres.length != 0){ 
							
					for (i = 0; i < colres.length; ++i) {
						res = colres[i];
						
						if(res && res.obj.type == me.game.SPY && spy.alive){
							//console.log('caught');
							
							this.addHitSpy();					
							this.caught = true;
							spy.caught();
							this.renderable.setCurrentAnimation('catch');
							
							
							
							//check side
							/*
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
							*/
							
							//check side
							if(me.gamestat.getItemValue('currentMode') == 'ghost'){
								if(this.pos.x > spy.pos.x){
									this.flipX(true);
								}else{
									this.flipX(false);
								}
							}else{
								if(this.pos.x > spy.pos.x){
									this.flipX(false);
								}else{
									this.flipX(true);
								}
							}
						}
					
					}
				}
			}
		}else if(spy.isCaught || this.caught){	
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
			}

			if(this.caught){
				if(!spy.stealthOn){
					//Is the spy in view of the guard?
					if(this.dangerZoneLeft < spy.right && 
						spy.left < this.dangerZoneRight && 
						this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
						(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
						if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
							//check side
							if(me.gamestat.getItemValue('currentMode') == 'ghost'){
								if(this.pos.x > spy.pos.x){
									this.flipX(true);
								}else{
									this.flipX(false);
								}
							}else{
								if(this.pos.x > spy.pos.x){
									this.flipX(false);
								}else{
									this.flipX(true);
								}
							}
						}
					}
				}else{
					if(this.colOverlaps(spy.collisionBox)){
						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}
					}
				}
			}
		}
		
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
});


/* ---------------------
an elite lazy guard entity
Stands at post, when Spy Lands in front, will walk forward and stop at point spy landed at.
Turn both ways and walk back to post.
----------------------*/

var EliteLazyGuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		//Set Position and walking boundaries
		//Will Check for custom StartX and StopX from Tiled
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;				
		
		//Set up delay at end of walk cycle
		this.doDelay = false;
		this.stillTime = 60;
		this.isStill = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Need additional area that he can patrol
		
		
		//add animation
		this.renderable.addAnimation('walk', [10,11,12,13,14,15],7);		
		this.renderable.addAnimation('catch', [8]);
		this.renderable.addAnimation('stand', [0]);		
		//this.renderable.addAnimation('alert',[6]);
		this.renderable.addAnimation('alert',[9]);
		this.renderable.addAnimation('alertL',[6]);
		this.renderable.addAnimation('alertR',[7]);
		this.renderable.addAnimation('alarmed',[6,7],60);
		this.renderable.addAnimation('break',[1,2,3,4,5]);
		
		this.animationspeed = me.sys.fps / 6;
		
		this.renderable.setCurrentAnimation('stand');
		
		//Start on the right and make walk left
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.walkLeft = false;
			this.flipX(true);
			if(settings.startOffset) this.pos.x += settings.startOffset;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.walkLeft = true;
			this.flipX(false);
			if(settings.startOffset) this.pos.x -= settings.startOffset;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
		
		this.alertDelay = 6;
		this.alertCounter = 0;
		this.doTurn = false;
		this.turnDirection;
		
		this.isChasing = false;
		this.returningToPost = false;
		this.alerted = false;
		this.atPost = true;
		this.toSpyPosition;
		
		this.isInvestigating = false;
		this.investigateDelay = 60;
		this.investigateCounter = 0;
		this.caught = false;

		this.stillDelay = 60;
		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.alertDelay = 12;
			this.stillDelay = 120;
		}
		
		this.stillTime = this.stillDelay;
		
		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
		
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }
		//var caught = false;
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//console.log(this.inViewport);
		
		//TODO: Check to see if spy has landed anywhere in the guard's perimiter.
		//If Spy has, pause, change to direction that spy was in
		//if(Spy.wasFalling)
		if(spy.alive && !this.caught){
			//if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){	
			
			
			//Check to see if spy has landed in the danger zone!
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
				
				//If Spy just landed, walk to point where spy landed
				if(spy.wasFalling && !spy.falling){
					this.toSpyPosition = spy.pos.x;
					this.isChasing = true;
					this.alerted = true;
					this.isInvestigating = false;
					this.investigateCounter = 0;
					this.alertCounter = 0;
					this.returningToPost = false;
					me.audio.play('guardwhat');
					//Spy lands in front, spy lands behind
					/*
					if(this.toSpyPosition > this.pos.x && this.walkLeft){
						this.turnDirection = 'right';
					}else if(this.toSpyPosition < this.pos.x && !this.walkLeft){
						this.turnDirection = 'left';						
					}*/
				}
			}
			
			if(this.isChasing){
			
			
				if(this.alerted){
					if(this.alertCounter < this.alertDelay){
						this.alertCounter++;
						this.vel.x = 0;
						this.renderable.setCurrentAnimation('alert');
					}else{
						this.alertCounter = 0;
						this.alerted = false;
						
						//Check to see if we need to turn here
						if(this.toSpyPosition > this.pos.x && this.walkLeft){
							this.flipX(true);
							this.walkLeft = false;	
						}else if(this.toSpyPosition < this.pos.x && !this.walkLeft){
							this.flipX(false);
							this.walkLeft = true;
						}
					}
				}else{
					
					//Check to see if we've reached our destination to investigate
					if(this.walkLeft && (this.pos.x <= this.toSpyPosition || this.pos.x <= this.startX)){
						this.isInvestigating = true;					
						this.vel.x = 0;					
						this.isChasing = false;
					}else if(!this.walkLeft && (this.pos.x >= this.toSpyPosition || this.pos.x >= this.endX)){
						this.isInvestigating = true;					
						this.vel.x = 0;
						this.isChasing = false;
					}
					
					if(!this.isInvestigating){
						this.renderable.setCurrentAnimation('walk');
						this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
						if(this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2) me.audio.play('guardstep', false, null, 0.4);
					}
				}
			
			}
			
			if(this.isInvestigating  && !this.isChasing){
				//timer here for stuff
				
				if(this.investigateCounter < this.investigateDelay){
				
						if(this.investigateCounter == 25){
							if(this.walkLeft){
								//this.flipX(true);
								this.walkLeft = false;
								this.renderable.setCurrentAnimation('alertR');
							}else{
								//this.flipX(false);
								this.walkLeft = true;
								this.renderable.setCurrentAnimation('alertL');
							}
						}else if(this.investigateCounter == 45){
							if(this.walkLeft){
								//this.flipX(true);
								this.walkLeft = false;
								this.renderable.setCurrentAnimation('alertR');
							}else{
								//this.flipX(false);
								this.renderable.setCurrentAnimation('alertL');
								this.walkLeft = true;
							}
						
						}else{
							if(!this.walkLeft){
								this.renderable.setCurrentAnimation('alertR');
							}else{								
								this.renderable.setCurrentAnimation('alertL');
							}
						}
						
						this.investigateCounter++;
						this.vel.x = 0;
						//this.renderable.setCurrentAnimation('alert');
					}else{
						this.investigateCounter = 0;
						this.isInvestigating = false;
						this.returningToPost = true;						
					}
					
			}
			
			if(this.returningToPost && !this.isChasing){
				if(this.pos.x > this.startPosX + 1 || this.pos.x < this.startPosX - 1){
					if(this.pos.x > this.startPosX + 1){
						this.flipX(false);
						this.walkLeft = true;
					}else{
						this.flipX(true);
						this.walkLeft = false;
					}
					
					this.renderable.setCurrentAnimation('walk');
					this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
					if(this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2) me.audio.play('guardstep', false, null, 0.4);
					
				}else{
					this.vel.x = 0;
					//Snap to start pos
					this.pos.x = this.startPosX;
					this.returningToPost = false;
					this.renderable.setCurrentAnimation('stand');
					this.flipX(this.startFlip);
					this.walkLeft = !this.startFlip;
				}
			}
			
			this.updateMovement();
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.caught = true;
						this.renderable.setCurrentAnimation('catch');
						//check side
						/*
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
						*/

						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					this.addHitSpy();
					//console.log('Caught!');
					spy.caught();
					this.caught = true;
					this.renderable.setCurrentAnimation('catch');
					//check side
					/*
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}
					*/

					//check side
					if(me.gamestat.getItemValue('currentMode') == 'ghost'){
						if(this.pos.x > spy.pos.x){
							this.flipX(true);
						}else{
							this.flipX(false);
						}
					}else{
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}
					}

				}
			}
		}else if(spy.isCaught || this.caught){	
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
			}
			
			if(this.caught){
				if(!spy.stealthOn){
					//Is the spy in view of the guard?
					if(this.dangerZoneLeft < spy.right && 
						spy.left < this.dangerZoneRight && 
						this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
						(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
						if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
							//check side
							if(me.gamestat.getItemValue('currentMode') == 'ghost'){
								if(this.pos.x > spy.pos.x){
									this.flipX(true);
								}else{
									this.flipX(false);
								}
							}else{
								if(this.pos.x > spy.pos.x){
									this.flipX(false);
								}else{
									this.flipX(true);
								}
							}
						}
					}
				}else{
					if(this.colOverlaps(spy.collisionBox)){
						//check side
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							if(this.pos.x > spy.pos.x){
								this.flipX(true);
							}else{
								this.flipX(false);
							}
						}else{
							if(this.pos.x > spy.pos.x){
								this.flipX(false);
							}else{
								this.flipX(true);
							}
						}
					}
				}
			}
		}
		
		this.parent(this);
		return true;
	},
	addHitSpy: function(){
		if(this.pos.x > spy.pos.x){
			var hitX = this.left - 8;
		}else{
			var hitX = this.right - 8;
		}
		
		if(this.pos.y < spy.pos.y){
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}else{
			var hitY = this.top - ((this.top - spy.bottom)/2) - 8;
		}
		
		//console.log(this.top + ' X' + hitX + ' Y' + hitY)
		
		//var hitspy = new HitSpyEntity(hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		var hitspy = me.entityPool.newInstanceOf("hitspy",hitX, hitY, {image:'hitspy', spritewidth:16, spriteheight: 16 });
		me.game.add(hitspy,this.z + 1);
	}
});


/* ---------------------
an elite homing device shooting guard entity
----------------------*/

var EliteHomingGuardEntity = enemyEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		//Set Position and walking boundaries
		//Will Check for custom StartX and StopX from Tiled
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;		
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;				
		
		//Set up delay at end of walk cycle
		this.doDelay = false;
		this.stillTime = 60;
		this.isStill = false;
		
		//set up bounding box for seeing the spy
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Need additional area that he can patrol
		
		
		//add animation
		this.renderable.addAnimation('walk', [0,1,2,3],7);		
		this.renderable.addAnimation('shoot', [4]);
		this.renderable.addAnimation('catch', [4]);
		this.renderable.addAnimation('stand', [3]);
		this.renderable.setCurrentAnimation('walk');
		this.renderable.addAnimation('alert',[5]);
		this.renderable.addAnimation('alarmed',[5,6],60);
		this.animationspeed = me.sys.fps / 6;
		
		//Start on the right and make walk left
		if(settings.startSide == 'left'){
			this.pos.x = x + this.marginLeft;
			this.walkLeft = false;
			this.flipX(true);
			if(settings.startOffset) this.pos.x += settings.startOffset;
		}else{
			this.pos.x = x + settings.width - settings.spritewidth - this.marginRight;
			this.walkLeft = true;
			this.flipX(false);
			if(settings.startOffset) this.pos.x -= settings.startOffset;
		}
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
		
		this.turnDelay = 6;
		this.turnCounter = 0;
		this.doTurn = false;
		this.turnDirection;
		
		this.shooting = false;
		this.shootDelay = 120;
		this.shootCounter = 0;
		
		//this.shot = false;
	},
	update: function(){
		//var caught = false;
		if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		//console.log(this.inViewport);
		
		//TODO: Check to see if spy has landed anywhere in the guard's perimiter.
		//If Spy has, pause, change to direction that spy was in
		//if(Spy.wasFalling)
		if(spy.alive){
			//if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('alarmed')){	
			
			if(!this.shooting){
				//Check to see if spy has landed in the danger zone!
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					
					if(spy.wasFalling && !spy.falling){
						this.shooting = true;
						this.shootCounter = 0;
						//Check to see if should turn or not
						if(spy.pos.x > this.pos.x && this.walkLeft != false){
							this.doTurn = true;
							this.turnDirection = 'right';
							this.turnCounter = 0;						
						}else if(spy.pos.x < this.pos.x && this.walkLeft != true){
							this.doTurn = true;
							this.turnDirection = 'left';
							this.turnCounter = 0;
						}
					}
				}
			}
			
			if(this.doTurn){
				if(this.turnCounter < this.turnDelay){
					this.turnCounter++;
					this.vel.x = 0;
					this.renderable.setCurrentAnimation('alert');
				}else{
					this.turnCounter = 0;
					this.doTurn = false;
					if(this.turnDirection == 'left'){
						this.flipX(false);
						this.walkLeft = true;
					}else{						
						this.flipX(true);
						this.walkLeft = false;
					}
				}
			}
			
			if(this.shooting && !this.doTurn){
				
				//Shoot once, wait a bit
				if(this.shootCounter < this.shootDelay){
					if(this.shootCounter == 0){
						//shoot
						//console.log('shoot!');
						this.shoot(this.walkLeft);
					}
					
					this.renderable.setCurrentAnimation('shoot');
					this.vel.x = 0;
					this.shootCounter++;
				}else{
					this.shooting = false;
					this.shootCounter = 0;
				}				
			}
			
			if(this.walkLeft && this.pos.x <= this.startX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(true);
					this.walkLeft = false;
				}
			}else if(!this.walkLeft && this.pos.x >= this.endX){
				if(this.doDelay){
					this.renderable.setCurrentAnimation('stand');
					this.isStill = true;
				}else{
					this.flipX(false);
					this.walkLeft = true;
					
				}
			}
			
			//Delay here if set
			if(this.doDelay){
				if(this.isStill && this.stillTime > 0){
					this.stillTime -= 1;
				}else if(this.stillTime === 0){
					this.isStill = false;
					this.stillTime = 60;
					this.renderable.setCurrentAnimation('walk');
					if(this.walkLeft){
						this.flipX(true);
						this.walkLeft = false;
					}else if(!this.walkLeft){
						this.flipX(false);
						this.walkLeft = true;
					}
				}
			}
			
			if(!this.doTurn && !this.shooting){
				this.renderable.setCurrentAnimation('walk');
				this.vel.x += (this.walkLeft) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick;
				if(this.renderable.getCurrentAnimationFrame() == 0 || this.renderable.getCurrentAnimationFrame() == 2) me.audio.play('guardstep', false, null, 0.4);
			}
			
			this.updateMovement();
		
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		
			//is Spy close to the guard?
			/*
			if(spy.pos.x > this.pos.x - 32 && spy.pos.x < this.pos.x + 24 && 
				spy.pos.y > this.pos.y - 12 && spy.pos.y < this.pos.y + 12){
				me.gamestat.updateValue("dangerCountTemp", me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					if((this.walkLeft && (spy.pos.x <= (this.pos.x + this.width))) || (!this.walkLeft && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						this.renderable.setCurrentAnimation('catch');
						//check side
						if(this.pos.x > spy.pos.x){
							this.flipX(false);
						}else{
							this.flipX(true);
						}

					}			
				}
			}else{
				//Also check normal collision, you can't walk through this dude
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY)){
				if(this.colOverlaps(spy.collisionBox)){
					//console.log('Caught!');
					spy.caught();
					this.renderable.setCurrentAnimation('catch');
					//check side
					if(this.pos.x > spy.pos.x){
						this.flipX(false);
					}else{
						this.flipX(true);
					}

				}
			}
		}else if(spy.isCaught){	
			if(!this.renderable.isCurrentAnimation('catch')){
				this.renderable.setCurrentAnimation('alarmed');
				this.vel.x = 0;
			}
		}
		
		
		this.parent(this);
		return true;
	},
	shoot: function(direction){
		//true for left, false for right, probably...
		if(direction){
			direction = 'left';
		}else{
			direction = 'right';
		}
		
		//var jumpdust = new JumpDustEntity(this.pos.x, this.pos.y, {image:'trapparticle', spritewidth:16, spriteheight: 16 });
		var jumpdust = me.entityPool.newInstanceOf("jumpdust",this.pos.x, this.pos.y, {image:'trapparticle', spritewidth:16, spriteheight: 16 });
			me.game.add(jumpdust,this.z + 1);
			//me.game.sort();
			
		
		//var homingProjectile = new HomingProjectileEntity(this.pos.x, this.pos.y, {image:'homingprojectile', spritewidth:16, spriteheight: 16, direction: direction });
		var homingProjectile = me.entityPool.newInstanceOf("homingprojectile",this.pos.x, this.pos.y, {image:'homingprojectile', spritewidth:16, spriteheight: 16, direction: direction });
			me.game.add(homingProjectile,this.z-1);
			//me.game.sort();
	}
});



/* ---------------------
Traps!

3 Entities: Trigger, Device, and Projectile

When the player steps on the trigger, the trigger finds devices with the same name. 

The devices create a projectile entity and shoots it in a specified direction.

The trigger will have a slight cool down time (red state) before becoming reactivated (green).

----------------------*/
var HomingTriggerEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.collidable = false;
		this.gravity = (0);
		this.updateColRect(2,28,-4,4);
		
		this.renderable.addAnimation('neutral', [0]);
		this.renderable.addAnimation('triggered', [1]);
		this.renderable.setCurrentAnimation('neutral');
		
		this.deviceName = settings.trapName;
		
		this.isTriggered = false;
		this.coolDownTime = 180;
		this.coolDownCounter = 0;
		
	},
	update: function(){
		if(this.isTriggered){
			if(this.coolDownCounter < this.coolDownTime){
				this.coolDownCounter += 1 * me.timer.tick;
			}else{
				this.coolDownCounter = 0;
				this.isTriggered = false;
				this.renderable.setCurrentAnimation('neutral');
			}
		}else{
			//Check for spy collision, find related devices, trigger the devices
			if(spy.alive){
				//var res = me.game.collide(this);
				//if(res && (res.obj.type == me.game.SPY) && !res.obj.jumping && (res.obj.pos.y +20 < this.pos.y)){
				if(!spy.jumping && (spy.pos.y +20 < this.pos.y) && this.colOverlaps(spy.collisionBox)){
					this.isTriggered = true;
					this.renderable.setCurrentAnimation('triggered');
					me.audio.play('trapdart');
					
					var trapDevices = me.game.getEntityByProp('trapName',this.deviceName);
					for(var i = 0; i < trapDevices.length; i++){
						//console.log(trapDevices[i]);
						trapDevices[i].shoot();							
					}	
				}
			}
		}
		this.parent(this);
		return true;
	}
});

var HomingLauncherEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.image = 'trapdeviceM5';
		this.parent(x,y,settings);
		this.direction = settings.direction;		
		this.trapName = settings.trapName;
		this.gravity = (0);
		//Do animations for:
		//if this direction left
		//if this direction right
		//if this direction down
		
		//TODO: Animations for Activated state
		/*
		if(this.direction == 'right'){
			this.renderable.addAnimation('neutral', [0]);
			this.renderable.addAnimation('triggered', [1]);
			this.particleX = x + 8;
			this.particleY = y;

		}else if(this.direction == 'left'){
			this.renderable.addAnimation('neutral', [4]);
			this.renderable.addAnimation('triggered', [5]);
			this.particleX = x - 8;
			this.particleY = y;

		}else if(this.direction == 'down'){
			this.renderable.addAnimation('neutral', [2]);
			this.renderable.addAnimation('triggered', [3]);
			this.particleX = x;
			this.particleY = y + 8;
		}
		*/
		
		this.renderable.addAnimation('neutral', [0]);
		this.renderable.addAnimation('triggered', [4,3,2,1]);
		this.renderable.addAnimation('triggeredNeutral', [1]);		
		this.renderable.addAnimation('reset', [2,3,4]);
		
		this.renderable.setCurrentAnimation('neutral');
		
		this.isTriggered = false;
		this.triggerTime = 60;
		this.triggerCounter = 0;
		
		this.trapX = x;
		this.trapY = y;
	},
	update: function(){
		if(this.triggerCounter < this.triggerTime){
			this.triggerCounter += 1;
		}else{
			if(this.isTriggered){
				this.renderable.setCurrentAnimation('reset','neutral');
				this.isTriggered = false;
			}			
			
		}
		
		this.parent(this);
		return true;
	},
	shoot: function(){
		//if this direction left
		//if this direction right
		//if this direction down
		this.isTriggered = true;
		this.triggerCounter = 0;
		this.renderable.setCurrentAnimation('triggered','triggeredNeutral');
		
		/*
		var jumpdust = new JumpDustEntity(this.particleX, this.particleY, {image:'trapparticle', spritewidth:16, spriteheight: 16 });
			me.game.add(jumpdust,this.z + 1);
			me.game.sort();
		*/	
		
		me.audio.play('orb_spawn');
		//var homingProjectile = new HomingProjectileEntity(this.pos.x, this.pos.y, {image:'homingprojectile', spritewidth:16, spriteheight: 16, direction: this.direction, amplifySpeed: false });
		//var homingProjectile = me.entityPool.newInstanceOf("trapprojectile",this.trapX, this.trapY, {image:'dart', spritewidth:16, spriteheight: 16, direction: this.direction });
		var homingProjectile = me.entityPool.newInstanceOf("homingprojectile",this.pos.x, this.pos.y, {image:'homingprojectile', spritewidth:16, spriteheight: 16, direction: this.direction });
			me.game.add(homingProjectile,30);
			//me.game.sort();
		//console.log(this.pos.x);
		//create projectile object
		//make a sound
		//TODO: Create puff of smoke object

	}
});



/* ---------------------
a homing device entity
----------------------*/


var HomingProjectileEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		
		this.direction = (settings.direction) ? settings.direction : down;	
		this.amplifySpeed = (settings.amplifySpeed) ? settings.disableAmplifySpeed : false;	
		
		
		this.alwaysUpdate = true;
		this.gravity = (0);
		this.collision = true;
		this.updateColRect(7,2,7,2);
		this.speed = .5;

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.speed = .3;
		}

		
		//TODO: Animations for each direction
		
		//this.renderable.addAnimation('side',[0]);
		this.renderable.addAnimation('side',[0,1,2,3,4,5,5,4,3,2,1,0]);
		this.renderable.addAnimation('destroy',[6,7,8,9,10,11,12]);
		this.renderable.addAnimation('enter',[13,13,13,16,15,14]);
		this.renderable.setCurrentAnimation('enter','side');
			
		if(this.direction == 'right'){
			this.speedAmplifier = 2;
		}else if(this.direction == 'left'){
			this.speedAmplifier = -2;
		}
		
		this.shootTimer = 0;
		this.shootDelay = 30;
		this.lethal = true;
	},
	update: function(){
		/*
		if(this.direction == 'left'){
			//left
			//console.log(this.gravity);
			this.pos.x -= this.speed * me.timer.tick;
			//this.pos.y = 
			//console.log(this.pos.y);
		}else if(this.direction == 'right'){
			//right
			this.pos.x += this.speed * me.timer.tick;
		}else{
			//down
			this.pos.y += this.speed * me.timer.tick;
		}
		*/
		
		if(spy.alive && !spy.isCaught){
			
			if(this.shootTimer < this.shootDelay){
				if(this.amplifySpeed){
					this.pos.x += (this.speed * this.speedAmplifier);
				}
				this.shootTimer++;
			}else{
		
				//Have a timer at the beginning so it doesn't start homing immediately?
				if(spy.pos.x !== this.pos.x){
					if(spy.pos.x > this.pos.x ){
						this.pos.x += this.speed;
					}else{
						this.pos.x -= this.speed;
					}
				}
				
				
				if(spy.pos.y !== this.pos.y){
					if(spy.pos.y > this.pos.y ){
						this.pos.y += this.speed;
					}else{
						this.pos.y -= this.speed;
					}
				}
				
			}
			
			//console.log(this.pos.x);
			
			
			
			if(this.lethal && !spy.isCaught && spy.alive){
				///*
				var results = me.game.collide(this, true);
				var resL = results.length;
				var index = 0;
				for(index; index < resL; ++index){
					var res = results[index];
					if( res && res.obj.type == me.game.SPY){
						//console.log('caught');
						this.speed = 0;
						if(this.direction == 'right'){
							direction = 'left';
						}else{
							direction = 'right';
						}
						
						spy.caughtBeam(direction);

						//Destroy in ghost mode
						if(me.gamestat.getItemValue('currentMode') == 'ghost'){
							me.audio.play('orb_destroy');
							this.lethal = false;
							this.renderable.setCurrentAnimation('destroy',(function () {
								this.lethal = false;
								me.game.remove(this);
							}).bind(this));							
						}

						
					
					}
				} //*/
				
				
				/*
				if( this.colOverlaps(spy.collisionBox)){
					//console.log('caught');
					this.speed = 0;
					if(this.direction == 'right'){
						direction = 'left';
					}else{
						direction = 'right';
					}
					
					spy.caughtBeam(direction);
				
				}*/
			}
			
			/* Fixes computer overlap
			var res = me.game.collide(this);			
			if(this.lethal && res && res.obj.type == me.game.SPY && spy.alive){
				console.log('caught');
				this.speed = 0;
				if(this.direction == 'right'){
					direction = 'left';
				}else{
					direction = 'right';
				}
				
				spy.caughtBeam(direction);
				//me.game.remove(this);
			}
			*/
			
			if(res && res.obj.type == 'STATIONARYBEAM' && this.lethal){
				//Play animation and remove	
				me.audio.play('orb_destroy');
				this.lethal = false;
				this.renderable.setCurrentAnimation('destroy',(function () {
					this.lethal = false;
					me.game.remove(this);
				}).bind(this));
				
			}
		
		}else{
			this.vel.x = 0;
		}
		if(!this.inViewport || ScreenTransitionStart){
			//me.game.remove(this);
		}
		
		this.parent(this);
		return true;
	}
});

/* ---------------------
a barrier don't touch this type thing
----------------------*/

var StationaryBeamEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.type = 'STATIONARYBEAM'
		this.collidable = true;
		
		//Can be vertical or horizontal
		this.renderable.addAnimation('beam',[0,1,2,3,4,5,6,7],4);
		this.renderable.setCurrentAnimation('beam');
		//If homing devices touch these they explode

		
		//Code for including/excluding in novice mode 
		this.removeImmediately = false;
		
		if(settings.noviceMode == "include"){
			if(me.gamestat.getItemValue('currentMode') != 'trueNovice'){				
				this.removeImmediately = true;
			}
		}else if(settings.noviceMode == "exclude"){
			if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
				this.removeImmediately = true;
			}
		}
	},
	update: function(){
		if(this.removeImmediately){ me.game.remove(this); }		
		//var res = me.game.collide(this);
		
		//if(spy.alive && !spy.isCaught && res && res.obj.type == me.game.SPY){
		if(spy.alive && !spy.isCaught && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			
			spy.caughtBeam('left');
			
			//spy.caught();
		}
		
		this.parent(this);
		return true;
	}
	
});

/* ---------------------
an elite guard dog entity
----------------------*/

var EliteGuardDogEntity = enemyEntity.extend({
	init: function(x,y,settings){
		//console.log('dog');
		this.parent(x,y,settings);
		//Set Collision Rect
		this.updateColRect(7,18,8,24);
		

		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.setVelocity(3,7.5);
			this.setMaxVelocity(3,7.5);
		}else{

			this.setVelocity(4,7.5);
			this.setMaxVelocity(4,7.5);
		}
		
		//Set Post Position		
		//Set Run Boundaries
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;		
		this.patrolX = (settings.patrolX) ? settings.patrolX : (this.endX - this.startX);	
		//Set Danger Zone
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = x;
		this.dangerZoneRight = x + settings.width;
		
		//Animations
		this.renderable.addAnimation('catch',[0,1], 8);
		
		this.renderable.addAnimation('lunge',[8], 12);
		
		this.renderable.addAnimation('alarmed',[0,1], 8);
		this.renderable.addAnimation('lookForward',[0,1], 8);
		this.renderable.addAnimation('lookBackward',[2,3], 8);
		this.renderable.addAnimation('chase',[4,5,6,7],2);
		this.renderable.addAnimation('trot',[9,10,11,12],12);
		//Set FlipX
		this.watchCounter = 120;
		this.chaseCounter = 20;
		this.isChasing = false;
		this.returningToPost = false;
		this.atPost = true;
		this.lookForward = true;
		this.bark = false;
		this.renderable.setCurrentAnimation('lookForward');

		this.caught = false;
		
		//check start side
		if(settings.startSide == 'left'){
			this.startPosX = this.startX;
			this.pos.x = this.startPosX;
			this.walkLeft = false;
			this.flipX(true);
		}else{
			this.startPosX = this.endX;
			this.pos.x = this.startPosX;
			this.walkLeft = true;
			this.flipX(false);
		}
		
		this.startXBuffer = this.startX + 24;
		this.endXBuffer = this.endX - 24;
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
	},
	update: function(){
		
		//Dog looks left and right
		
		/*
		if(this.watchCounter > 0  && !this.isChasing && !this.returningToPost){
				this.watchCounter -= me.timer.tick;
		}else if(this.watchCounter <= 0 && !this.isChasing && !this.returningToPost){
			this.watchCounter = 120;
			if(this.lookForward){
				this.renderable.setCurrentAnimation('lookBackward');
				this.lookForward = false;
			}else if(!this.lookForward){
				this.renderable.setCurrentAnimation('lookForward');
				this.lookForward = true;
			}
		}*/
		
		
		
		//if spy is in danger zone, run the direction of the spy
		if(spy.alive && !this.caught){
			if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
			
			//is Spy close to the dog?
			/*
			if(spy.pos.x > this.pos.x - 52 && spy.pos.x < this.pos.x + 44 && 
				spy.pos.y > this.pos.y - 20 && spy.pos.y < this.pos.y + 20){
				me.gamestat.updateValue("dangerCountTemp", 2 * me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}*/
			
			//Is the spy in view of the dog?
			if(this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				//Which way should the dog run?
				if(!this.bark){
					me.audio.play("dogbark",false,null,.3); 
					this.bark = true;
				}
				
				if(spy.pos.x < this.pos.x){
					this.flipX(false);
					this.walkLeft = true;
					if(this.pos.x > this.startX){						
						//Run Left
						this.vel.x -= this.accel.x * me.timer.tick;					
						this.renderable.setCurrentAnimation('chase');
					}else{
						//stop and bark at the spy
						this.vel.x = 0;					
						this.renderable.setCurrentAnimation('alarmed');						
					}
				}else if(spy.pos.x > this.pos.x){
					this.flipX(true);
					this.walkLeft = false;
					if(this.pos.x < this.endX){
						//Run Right
						this.vel.x += this.accel.x * me.timer.tick;					
						this.renderable.setCurrentAnimation('chase');
					}else{
						//stop and bark at the spy
						this.vel.x = 0;					
						this.renderable.setCurrentAnimation('alarmed');						
					}
				}
				this.isChasing = true;
				
			}else{
				//Continue chasing for a few more frames if was chasing
				if(this.isChasing){
					if(this.chaseCounter > 0){
						if(this.pos.x <= this.startX || this.pos.x >= this.endX){
							this.chaseCounter = 0;
							this.vel.x = 0;
						}else{
							this.chaseCounter -= 1 * me.timer.tick;
						}
					}else{
						this.isChasing = false;
						this.chaseCounter = 20;
						//go back to post
						this.returningToPost = true;
						if(this.walkLeft){
							this.flipX(true);
							this.walkLeft = false;
						}else{
							this.flipX(false);
							this.walkLeft = true;
						}
					}		
				}
			}
			
			
			//Instead of returning to a post, the dog should sniff the area for a bit?			
			if(this.returningToPost && !this.isChasing){
				/*
				//If x pos not at start position
				this.renderable.setCurrentAnimation('trot');
				if(this.pos.x > this.startPosX + 4){	
					this.vel.x = -1.5 * me.timer.tick;
					this.flipX(false);
				}else if(this.pos.x < this.startPosX - 4){
					this.vel.x = 1.5 * me.timer.tick;
					this.flipX(true);
				}else{
					this.bark = false;
					this.vel.x = 0;
					//Snap to start pos
					this.pos.x = this.startPosX;
					this.returningToPost = false;
					this.renderable.setCurrentAnimation('lookForward');
					this.watchCounter = 120;
				}*/
				this.returningToPost = false;
			}
			
			//We want the dog to patrol an area
			if(!this.isChasing){
			
				this.renderable.setCurrentAnimation('trot');
				
				if(this.walkLeft && this.pos.x <= this.startX){
					this.flipX(true);
					this.walkLeft = false;
				}else if(!this.walkLeft && this.pos.x >= this.endX){
					this.flipX(false);
					this.walkLeft = true;				
				}
				
				this.vel.x = (this.walkLeft) ? -1 : 1;
			}
			
			
			//*/
		}else if(spy.isCaught || this.caught){	
			//console.log('Dog Dog!');
			if(!this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}
			/*
			if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}else if(this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.vel.x = 0;
				this.isChasing = false;
			}else{
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}
			*/
		}

		this.updateMovement();
		//if spy collides with dog, caught!
		//var res = me.game.collide(this);
		
		//if(res && res.obj.type == me.game.SPY && spy.alive){
		if(spy.alive && this.colOverlaps(spy.collisionBox)  && !this.caught){
			//console.log('caught');
			if( !this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('lunge','catch');
			}
			
			this.isChasing = false;
			//spy.caught();
			
			if(this.pos.x + 8 > spy.pos.x){
				var direction = 'right';
			}else{
				var direction = 'left';
			}
			
			this.caught = true;
			spy.caughtKnockedDown(direction);
			
		}
		
		
		this.parent(this);
		return true;
		
	}
});


/* ---------------------
A SHARK
64 PIXELS OF MASSIVE TEETH

swim back and forth
spy enters danger zone
	track lastSpyPos (x)
	once we reach lastSpyPosition, lung upwards
----------------------*/

var SharkEntity = enemyEntity.extend({
	init: function(x,y,settings){
		
		this.parent(x,y,settings);
		//Set Collision Rect
		//this.updateColRect(7,18,8,24);
		
		//default collision while swimming
		this.updateColRect(8,48,32,32);
		
		this.anchorPoint.set(0,0);
		
		this.collidable = false;
		this.gravity = 0;
		this.setVelocity(4,8);
		this.setMaxVelocity(4,8);


		if(me.gamestat.getItemValue('currentMode') == 'trueNovice'){
			this.setVelocity(3,6);
			this.setMaxVelocity(3,6);
		}else{

			this.setVelocity(4,8);
			this.setMaxVelocity(4,8);
		}
		
		
		//Set Post Position		
		//Set Run Boundaries
		if(!settings.marginLeft) settings.marginLeft = 0;
		if(!settings.marginRight) settings.marginRight = 0;
		this.marginLeft = settings.marginLeft;
		this.marginRight = settings.marginRight;
		this.startX = x + this.marginLeft;
		this.endX = x + settings.width - settings.spritewidth - this.marginRight;		
		this.patrolX = (settings.patrolX) ? settings.patrolX : (this.endX - this.startX);	
		//Set Danger Zone
		this.dangerZoneTop = y - 48;
		this.dangerZoneBottom = y + 32;
		this.dangerZoneLeft = x+12;
		this.dangerZoneRight = x + settings.width-12;
		
		this.splashY = y-32;
		
		//console.log('danger: ' + this.dangerZoneTop);
		
		//Animations
		this.renderable.addAnimation('swim',[0,1,2,4,3,4,5,2], 8);
		this.renderable.addAnimation('turn',[11], 16);
		this.renderable.addAnimation('quickturn',[11], 8);
		this.renderable.addAnimation('lungeStart',[6], 8);
		this.renderable.addAnimation('lunge',[7], 8);
		this.renderable.addAnimation('peak',[8], 8);
		this.renderable.addAnimation('fall',[9], 8);
		this.renderable.addAnimation('splash',[10], 8);
		
		this.renderable.addAnimation('catch',[0,1], 8);
		
		
		this.renderable.addAnimation('alarmed',[0,1], 8);
		this.renderable.addAnimation('lookForward',[0,1], 8);
		this.renderable.addAnimation('lookBackward',[2,3], 8);
		this.renderable.addAnimation('chase',[4,5,6,7],2);
		this.renderable.addAnimation('trot',[4,5,6,7],4);
		//Set FlipX
		this.watchCounter = 120;
		this.chaseCounter = 20;
		this.isChasing = false;
		this.isLunging = false;
		this.hitBoundary = false;
		this.isLungingUp = false;
		this.isLungingDown = false;
		
		this.returningToPost = false;
		this.atPost = true;
		this.lookForward = true;
		this.bark = false;
		this.renderable.setCurrentAnimation('swim');
		
		//check start side
		if(settings.startSide == 'left'){
			this.startPosX = this.startX;
			this.pos.x = this.startPosX;
			this.walkLeft = false;
			this.flipX(true);
		}else{
			this.startPosX = this.endX;
			this.pos.x = this.startPosX;
			this.walkLeft = true;
			this.flipX(false);
		}
		
		this.startXBuffer = this.startX + 24;
		this.endXBuffer = this.endX - 24;
		
		this.startPosX = this.pos.x;
		this.startPosY = this.pos.y;
		this.startFlip = !this.walkLeft;
		
		this.lastSpyPosition;
		
		this.coolDownCounter = 31;
		this.coolDownTime = 30;
		this.lungeCount = 0;
	},
	update: function(){
		//if(this.resetCheck(this.startPosX,this.startPosY,this.startFlip)) return false;
		if(ScreenTransitionStart && !this.inViewport){ 
			this.pos.x = this.startPosX;
			this.isChasing = false;
			this.lungeCount = 0;
			this.renderable.setCurrentAnimation('swim');
			this.parent(this);
			return true;
		}
		
		if(this.coolDownCounter < this.coolDownTime){
			this.coolDownCounter++;
			this.coolingDown = true;
		}else{
			this.coolDownCounter = 0;
			this.coolingDown = false;
		}
		
		//if spy is in danger zone, run the direction of the spy
		if(spy.alive){
			
			//is Spy close to the shark?
			/*
			if(!this.coolingDown && !this.isLunging && spy.pos.x > this.pos.x - 52 && spy.pos.x < this.pos.x + 44 && 
				spy.pos.y > this.pos.y - 20 && spy.pos.y < this.pos.y + 20){
				me.gamestat.updateValue("dangerCountTemp", 2 * me.timer.tick);
				//console.log(this.pos.x + " " + spy.pos.x);
			}
			*/
			
			//Is the spy in shark's danger zone?
			if(!this.isLunging && this.dangerZoneLeft < spy.right && 
				spy.left < this.dangerZoneRight && 
				this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
				(spy.top + (spy.height * .9 )) < this.dangerZoneBottom){
				
				this.lastSpyPosition = spy.pos.x;
				this.isChasing = true;		
				//console.log('Last Pos: ' + spy.pos.x);
			}
			
			//
			if(this.isChasing && !this.isLunging){
				//var sharkX = this.pos.x+32;
				//console.log("Chasing shark x: " + sharkX + ' spy x:' + this.lastSpyPosition);
				//if(  (this.walkLeft && (this.pos.x-24>=this.lastSpyPosition+8) && (this.pos.x-24<=this.lastSpyPosition+14)) || (!this.walkLeft && (this.pos.x+24>=this.lastSpyPosition+8) && (this.pos.x+24<=this.lastSpyPosition+14)) ){ //Lunge here
				//If center is under spy
				//if(this.pos.x+32 >= this.lastSpyPosition+8 && this.pos.x+32 <= this.lastSpyPosition+16){
				/*
				if( (this.walkLeft && ((this.pos.x+32)<=(this.lastSpyPosition+24) && (this.pos.x+32)>=(this.lastSpyPosition))) 
				||  (!this.walkLeft && ((this.pos.x+32)<=(this.lastSpyPosition+24) && (this.pos.x+32)>=(this.lastSpyPosition))) ){
				*/
				/*
				if( ( ((this.pos.x+32)<=(this.lastSpyPosition+24) && (this.pos.x+32)>=(this.lastSpyPosition)) ) ||
					(this.hitBoundary == true && ( ((this.pos.x+16)<=(this.lastSpyPosition+24) && (this.pos.x+16)>=(this.lastSpyPosition)) || ((this.pos.x+48)<=(this.lastSpyPosition+24) && (this.pos.x+48)>=(this.lastSpyPosition)) ) ) ){
					*/
				if( ( ((this.pos.x+32)<=(this.lastSpyPosition+24) && (this.pos.x+32)>=(this.lastSpyPosition)) ) ||
					(this.hitBoundary == true && ( ((this.pos.x+16)<=(this.lastSpyPosition+24) && (this.pos.x+16)>=(this.lastSpyPosition)) || ((this.pos.x+48)<=(this.lastSpyPosition+24) && (this.pos.x+48)>=(this.lastSpyPosition)) ) ) ){
					this.isChasing = false;
					this.isLunging = true;
					this.isLungingUp = true;
					this.vel.x = 0;
					this.renderable.setCurrentAnimation('lungeStart');
					//this.pos.x = this.lastSpyPosition;
				//	console.log(this.walkLeft);
					//console.log("Chasing: " + this.pos.y + ' shark x:'+ this.pos.x + ' spy x:' + this.lastSpyPosition);
				}else if( (this.pos.x+32) > this.lastSpyPosition){ //Chase Left
					this.flipX(false);
					if(!this.walkLeft){
						this.renderable.setCurrentAnimation('quickturn','swim');
					}
					this.walkLeft = true;
					if(this.pos.x > this.startX){						
						//Run Left
						this.vel.x -= this.accel.x * me.timer.tick;					
						//this.renderable.setCurrentAnimation('chase');
						this.hitBoundary = false;
					}else{
						//stop and bark at the spy
						//this.vel.x = 0;					
						//this.renderable.setCurrentAnimation('alarmed');
						this.hitBoundary = true;		
					}
					//console.log('left');
				}else if( (this.pos.x+32) < this.lastSpyPosition){ //Chase Right
					this.flipX(true);
					if(this.walkLeft){
						this.renderable.setCurrentAnimation('quickturn','swim');
					}
					this.walkLeft = false;
					if(this.pos.x < this.endX){
						//Run Right
						this.vel.x += this.accel.x * me.timer.tick;					
					//	this.renderable.setCurrentAnimation('chase');
						this.hitBoundary = false;
					}else{
						//stop and bark at the spy
						//this.vel.x = 0;					
						//this.renderable.setCurrentAnimation('alarmed');
						//console.log('stopped');
						this.hitBoundary = true;
					}
					//console.log('right');
				}

				//reset if spy is out of box
				/*
				if(spy.pos.x < this.startX || spy.pos.x > this.endX){
					this.isChasing = false;
				}*/
				
				if(this.dangerZoneLeft >= spy.right || this.dangerZoneRight <= spy.left){
						this.isChasing = false;
						//console.log('out');
				}
				
			}
			
			
			
			
			//*/
		}else if(spy.isCaught){	
			//console.log('Dog Dog!');
			if(!this.renderable.isCurrentAnimation('lunge')){
				//this.renderable.setCurrentAnimation('catch');
				//this.vel.x = 0;
				this.isChasing = false;
			}
			/*
			if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}else if(this.renderable.isCurrentAnimation('catch') && !this.renderable.isCurrentAnimation('lunge')){
				this.vel.x = 0;
				this.isChasing = false;
			}else{
				this.renderable.setCurrentAnimation('catch');
				this.vel.x = 0;
				this.isChasing = false;
			}
			*/
		}
		
		
		
			if(this.isLunging){
				//lunge up
				
				if(this.walkLeft){
					this.flipX(false);
				}else{
					this.flipX(true);
				}
				//this.updateColRect(26,12,8,48);
				
				
				if(this.isLungingUp){
					//
					if(this.hitBoundary){
					this.updateColRect(12,40,12,40); //reset collision
					}else{
						this.updateColRect(24,16,12,40); //reset collision
					}
					
					this.renderable.setCurrentAnimation('lunge');
					
					
					
					if(this.pos.y > this.startPosY - 64){
						if(this.lungeCount == 0){
							me.audio.play("sharksplashlunge",false,null,.3);
							//sharksplash = new SharkSplashEntity(this.pos.x, this.splashY, {image:'splashlunge', spritewidth:64, spriteheight: 64, flipX: !this.walkLeft });
							var sharksplash = me.entityPool.newInstanceOf("sharksplash",this.pos.x, this.splashY, {image:'splashlunge', spritewidth:64, spriteheight: 64, flipX: !this.walkLeft });
							me.game.add(sharksplash,this.z + 1);
						}
						this.lungeCount++; 
						this.vel.x = 0;
						this.pos.y -= 4;
						//console.log('top: ' + this.pos.y);
					}else{
						this.lungeCount = 0;
						this.isLungingUp = false;
						this.renderable.setCurrentAnimation('peak');
						//console.log('top: ' + this.pos.y);
					}
				}else{
					if(this.hitBoundary){
					this.updateColRect(12,40,16,40); //reset collision
					}else{
						this.updateColRect(24,16,16,40); //reset collision
					}
				
					this.renderable.setCurrentAnimation('fall');
					if(this.pos.y < this.startPosY){
						this.lungeCount++; 
						this.vel.x = 0;
						this.pos.y += 4;
					}else{
						this.pos.y = this.startPosY;
						this.lungeCount = 0;
						this.isLunging = false;
						this.updateColRect(8,48,32,32); //reset collision
						this.renderable.setCurrentAnimation('splash','swim');
						this.coolDownCounter = 0;
						this.coolingDown = true;
						me.audio.play("sharksplashland",false,null,.3); 
						
						//sharksplash = new SharkSplashEntity(this.pos.x, this.splashY, {image:'splashland', spritewidth:64, spriteheight: 64, flipX: !this.walkLeft });
						var sharksplash = me.entityPool.newInstanceOf("sharksplash",this.pos.x, this.splashY, {image:'splashlunge', spritewidth:64, spriteheight: 64, flipX: !this.walkLeft });
						me.game.add(sharksplash,this.z + 1);
			
			
						//console.log('bottom: ' + this.pos.y);
					}
				}
				//lunge down
			}
			
			
			
			//We want the shark to patrol an area
			if(!this.isChasing && !this.isLunging){
			
				//this.renderable.setCurrentAnimation('trot');
				
				if(this.walkLeft && this.pos.x <= this.startX){
					
					this.flipX(true);
					this.renderable.setCurrentAnimation('turn','swim');
					this.walkLeft = false;
				}else if(!this.walkLeft && this.pos.x >= this.endX){
					this.flipX(false);
					this.renderable.setCurrentAnimation('turn','swim');
					this.walkLeft = true;				
				}
				
				this.vel.x = (this.walkLeft) ? -1 : 1;
			}
			
			

		this.updateMovement();
		//if spy collides with shark, caught!
		//var res = me.game.collide(this);
		/*
		var colres = this.collide(true)
		if(this.isLunging && colres.length != 0){ 
					
			for (i = 0; i < colres.length; ++i) {
				res = colres[i];
				
				if(res && res.obj.type == me.game.SPY && spy.alive){
					//console.log('caught');
					if( !this.renderable.isCurrentAnimation('lunge')){
						//this.renderable.setCurrentAnimation('lunge','catch');
					}
					
					this.isChasing = false;
					//spy.caught();
					
					if(this.pos.x + 8 > spy.pos.x){
						var direction = 'right';
					}else{
						var direction = 'left';
					}
					
					spy.caughtKnockedDown(direction);
					
				}
			
			}		
			
		} */
		
		if(this.isLunging && spy.alive && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			if( !this.renderable.isCurrentAnimation('lunge')){
				//this.renderable.setCurrentAnimation('lunge','catch');
			}
			
			this.isChasing = false;
			//spy.caught();
			
			if(this.pos.x + 8 > spy.pos.x){
				var direction = 'right';
			}else{
				var direction = 'left';
			}
			
			spy.caughtKnockedDown(direction);
			
		}
		
		
		
		this.parent(this);
		return true;
		
	}
});

/* ---------------------
a shark splash entity
----------------------*/

var SharkSplashEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.spritewidth = 64;
		this.type = 'SHARKSPLASH';
		this.collidable = false; 
		this.gravity= (0);
		this.parent(x,y,settings);
		if(settings.image == 'splashlunge'){
			this.renderable.addAnimation('splash', [0,1,2,3,4],4);
		}else{
			this.renderable.addAnimation('splash', [0,1,2,3,4,5],4);
		}
		this.flipX(settings.flipX);
		this.renderable.setCurrentAnimation("splash", (function () {
			this.remove();
			 return false; // do not reset to first frame
		}).bind(this));
	},
	update: function(){
		this.parent(this);
		return true;
	},
	remove: function(){
		this.renderable.alpha = 0;
		me.game.remove(this);
	}
});

/* ---------------------
a security guard entity
----------------------*/

var GaleEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		//this.type = me.game.ENEMY_OBJECT;
		this.setVelocity(1.5,0);
		this.collidable = false;
		this.updateColRect(3,10,-1,0);
		this.alwaysUpdate = true;
		
		
		//add animation
		this.renderable.addAnimation('walk', [0,1,2,3],7);		
		this.renderable.addAnimation('catch', [5,6]);
		this.renderable.addAnimation('stand', [4]);
		
		this.renderable.addAnimation('alarmed',[5,6]);
		
		this.renderable.addAnimation('run', [0,1,2,3]);	
		this.renderable.addAnimation('activateTrapsFirstTime',[5,6,5,6,5],6);
		this.renderable.addAnimation('activateTraps',[5,6,5,6,5],6);
		
		this.animationspeed = me.sys.fps / 6;
		
		this.renderable.setCurrentAnimation('stand');
		
		this.flipX(false);
		
		this.dangerZoneTop = y;
		this.dangerZoneBottom = y + settings.height;
		this.dangerZoneLeft = 0;
		this.dangerZoneRight = 1600;
		
		
		//At each position Gale should stop and activate a set of homing devices
		this.stopPosition1 = 152; //this is actually the starting position
		this.stopPosition2 = 472;
		this.stopPosition3 = 792;
		this.stopPosition4 = 1112;
		
		this.stopState = 1;
		this.running = false;
		this.firstLaugh = true;
		this.catchLaugh = true;
		this.narrativeMode = false; 
		if(me.gamestat.getItemValue('currentMode') == 'ghost'){
			this.narrativeMode = true; 
		}
	},
	update: function(){
		
		//if the door is opened, then activate first set of traps and take off running
		//*
			if(!this.running && this.inViewport){
				var door = me.game.getEntityByProp('doorName','galehdoor1');
				for(var i = 0; i < door.length; i++){
					if(door[i].hacked == true){
						//activate homing, take off running
						if(this.firstLaugh){
							me.audio.play('gale_laugh');
							this.firstLaugh = false;
						}
						this.alarmed = true;
						//animation then
						this.flipX(true);
						this.renderable.setCurrentAnimation('activateTrapsFirstTime', function(){ 
							this.flipX(false);
							this.renderable.setCurrentAnimation('run');
							this.activateTraps('trap1');
							this.running = true; }.bind(this));
						//this.renderable.setCurrentAnimation('activateTraps');
						//this.running = true;
						
					}							
				}
			}
		
		//*/
		
		
		//Check position to see if we are at a stop position
		//Run through animation, activate traps, then start running again
		//If we make it to our destination, Spy Loses
		if(this.running && spy.alive){
			if(!this.renderable.isCurrentAnimation('activateTraps')){
			
				if(this.pos.x >= this.stopPosition2 && this.stopState == 1){
					this.vel.x = 0;
					me.audio.play('gale_laugh');
					this.renderable.setCurrentAnimation('activateTraps', function(){ 
							this.renderable.setCurrentAnimation('run');
							this.activateTraps('trap2');
							this.running = true; }.bind(this));
							this.stopState = 2;
				}else if(this.pos.x >= this.stopPosition3  && this.stopState == 2){
					this.vel.x = 0;
					me.audio.play('gale_laugh');
					this.renderable.setCurrentAnimation('activateTraps', function(){ 
							this.renderable.setCurrentAnimation('run');
							this.activateTraps('trap3');
							this.running = true; }.bind(this));
							this.stopState = 3;
				}else if(this.pos.x >= this.stopPosition3  && this.stopState == 3){
					this.vel.x = 0;
					me.audio.play('gale_laugh');
					this.renderable.setCurrentAnimation('activateTraps', function(){ 
							this.renderable.setCurrentAnimation('run');
							this.activateTraps('trap4');
							this.running = true; }.bind(this));
							this.stopState = 4;
				}else if(this.pos.x >= this.stopPosition4  && this.stopState == 4){
					me.audio.play('gale_laugh');
					spy.caught();
					this.running = false;
					this.vel.x = 0;
					if(gameData.load('screenshakeDisabled') != 'yes'){
						me.game.viewport.shake(10,100, me.game.viewport.AXIS.BOTH);
					}
				}else{		
					this.vel.x += this.accel.x;
					
				}
			}
		}
		//Check here to see if Spy is within the width and height of this entity
		//if(spy.pos.x >= this.dangerZoneLeft && spy.pos.x <= this.dangerZoneRigh && (spy.pos.y >= this.dangerZoneTop) && 
		if(spy.alive && this.inViewport && this.alarmed && !this.narrativeMode){
			
			if(!spy.stealthOn){
				//Is the spy in view of the guard?
				if(this.dangerZoneLeft < spy.right && 
					spy.left < this.dangerZoneRight && 
					this.dangerZoneTop < (spy.bottom - (spy.height * .9 )) &&
					(spy.top + (spy.height * .9)) < this.dangerZoneBottom){
					
					if((this.running && (spy.pos.x >= (this.pos.x - this.width)))){
						spy.caught();
						if(this.catchLaugh){
							me.audio.play('gale_laugh');
							this.catchLaugh = false;
						}
						this.renderable.setCurrentAnimation('catch');
						//check side
						if(this.pos.x > spy.pos.x){
							this.flipX(true);
						}else{
							this.flipX(false);
						}
						this.vel.x = 0;
					}else if(this.renderable.isCurrentAnimation('activateTrapsFirstTime') && (spy.pos.x <= (this.pos.x))){
						spy.caught();
						this.renderable.setCurrentAnimation('catch');
						if(this.catchLaugh){
							me.audio.play('gale_laugh');
							this.catchLaugh = false;
						}
						//check side
						if(this.pos.x > spy.pos.x){
							this.flipX(true);
						}else{
							this.flipX(false);
						}
						this.vel.x = 0;
					}	
				}
			}
			
			
		}else if(spy.isCaught){	
			if(!this.renderable.isCurrentAnimation('catch') && !this.renderable.setCurrentAnimation('alarmed')){
				this.renderable.setCurrentAnimation('alarmed');
				if(this.pos.x > spy.pos.x){
					this.flipX(true);
				}else{
					this.flipX(false);
				}
				this.vel.x = 0;
				if(this.catchLaugh){
					me.audio.play('gale_laugh');
					this.catchLaugh = false;
				}
			}
		}
		
		this.updateMovement();
		this.parent(this);
		return true;
	},
	activateTraps: function(trapSetName){
		me.audio.play('trapdart');
		var trapDevices = me.game.getEntityByProp('trapName',trapSetName);
		for(var i = 0; i < trapDevices.length; i++){
			//console.log(trapDevices[i]);
			trapDevices[i].shoot();							
		}
	}
});


/* ---------------------
AutoDeath - Touch it and Die
----------------------*/
var AutoDeathEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.gravity = (0);
		this.collision = false;
		
	},
	update: function(){
		//check for collision with spy
		//var res = me.game.collide(this);
		//if(res && res.obj.type == me.game.SPY && spy.alive){
		if(spy.alive && this.colOverlaps(spy.collisionBox)){
			//console.log('caught');
			
			if(this.direction == 'right'){
				direction = 'left';
			}else{
				direction = 'right';
			}
			
			spy.caughtKnockedDown('right');
			
		}
		
		this.parent(this);
		return true;
	}
});



/* ---------------------
GPU Check Entity

if the fps drops below 45, disable webGL rendering
----------------------*/
var GPUCheckEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		
		this.now = this.last = Date.now();
		// reset delta counting variables
		this.framedelta = 0;
		this.framecount = 0;	
		this.count = 0;
		this.limit = 60; //Was 5
		
		this.webGLUserPrefSet = (gameData.load('webGLUserPrefSet') == 'yes') ? true : false;	
		
		this.firstRunCheck = (gameData.load('firstRunCheck') == 'yes') ? true : false;	
		
	},
	update: function(){
		if(!this.firstRunCheck && !this.webGLUserPrefSet){
			this.last = this.now;
			this.now = Date.now();

			this.delta = (this.now - this.last);

			// only draw the FPS on in the HTML page 
		
			this.framecount++;
			this.framedelta += this.delta;
			if (this.framecount % 10 == 0) {
				//this.fps = (~~((1000 * this.framecount) / this.framedelta)).clamp(0, me.sys.fps);
				this.fps = (~~((1000 * this.framecount) / this.framedelta));
				this.framedelta = 0;
				this.framecount = 0;
			}
			
			if(gameData.load('webGLDisabled') != 'yes' && this.fps > 5 && this.fps < 45){
				//console.log(this.fps);
				this.count++;			
			}
			
			if(this.count>this.limit){
				gameData.save('webGLDisabled','yes');
				gameData.save('firstRunCheck','yes');
				clearWebGL();
				me.game.remove(this);
			}
		}else{
			me.game.remove(this);
		}
	}
});





/* ---------------------
Mission 1 Cutscene
This is probably bad but whatever.
----------------------*/

var MissionBuildingEntity = me.ObjectEntity.extend({
	init:function(x,y,settings){
		this.parent(x,y,settings);
		this.jitter = false;
		this.jitterUp = false;
		this.jitterCounter = 30;
		
		if(me.audio.getCurrentTrack()) me.audio.stop(me.audio.getCurrentTrack());
		//*
		//var bgm = new AudioControllerEntity(0, 0, {newTrack:'ost_m_01_01', fadeTo:.4, fadeStep:0.0025});
		var bgm = me.entityPool.newInstanceOf("audiocontroller",0, 0, {newTrack:'ost_m_01_01', fadeTo:.4, fadeStep:0.0025});
					me.game.add(bgm,100);
		//*/
		me.game.viewport.fadeOut('#000000',300);
		//Transition
		//leveltransition = new LevelTransitionEntity(-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'in' });
		var leveltransition = me.entityPool.newInstanceOf("leveltransition",-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'in' });
		me.game.add(leveltransition,60);
		//me.game.sort();
		
		//console.log(this.pos.y);
		
		tweenP1 = new me.Tween(this.pos).to({y:-368}, 300);
		tweenP1.easing(me.Tween.Easing.Quintic.InOut);
		
		tweenP2 = new me.Tween(this.pos).to({y:-358}, 3000);
		tweenP2.easing(me.Tween.Easing.Quintic.InOut);
		
		tweenP3 = new me.Tween(this.pos).to({y:-368}, 3000);
		tweenP3.easing(me.Tween.Easing.Quintic.InOut);
		
		
		tween1 = new me.Tween(this.pos).to({x:-32}, 600);
		tween1.easing(me.Tween.Easing.Quartic.Out);
		
		tween2 = new me.Tween(this.pos).to({x:32}, 600);
		tween2.easing(me.Tween.Easing.Quartic.Out);
		
		tween3 = new me.Tween(this.pos).to({y:32,x:16}, 1200);
		tween3.easing(me.Tween.Easing.Quartic.Out);
		
		tween4 = new me.Tween(this.pos).to({y:24}, 3000);
		tween4.easing(me.Tween.Easing.Quintic.InOut);
		
		tween5 = new me.Tween(this.pos).to({y:32}, 3000);
		tween5.easing(me.Tween.Easing.Quintic.InOut);
		
		//need to create controls object that skips title here
		//Should it start mission 1 automatically or wait for input?
		
		tweenP1.chain(tween1);
		
		tween1.chain(tween2);
		tween2.chain(tween3);
		tween3.chain(tween4).onComplete(function() {this.drawMissionText();}.bind(this));
		tween4.chain(tween5);
		tween5.chain(tween4);
		tweenP1.start();
		
	},
	update:function(){
		if(me.input.isKeyPressed('nextLevel') || me.input.isKeyPressed('jump')){ 
			//me.game.viewport.fadeIn('#000000',1000,function(){ me.levelDirector.loadLevel('m_01_lvl_01'); });
			
			me.audio.play('title', false, null, 0.5);
			
			//leveltransition = new LevelTransitionEntity(-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
			var leveltransition = me.entityPool.newInstanceOf("leveltransition",-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
					me.game.add(leveltransition,120);
					//me.game.sort();
				
				//TODO: Put code in here that sets the level to the loaded level if continuing game
				//console.log('loading game? ' + me.gamestat.getItemValue('loadingSaveGame'));
				if(me.gamestat.getItemValue('loadingSaveGame')){
					//console.log(gameData.load('currentLevel'));
					me.gamestat.setValue('loadingSaveGame',false);
					me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel(gameData.load('currentLevel')); });
				}else{
					me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel('m_01_lvl_01'); });
				}
				
				
		}
		this.parent(this);
		return true;	
	},
	drawMissionText:function(){
		//Create Mission Title Object using 'mission_01_title'
		missionTitle = new MissionTitleEntity(40, 40, {image:'mission_01_title', spritewidth:140, msg: 'INFILTRATE GALE-ELECTRO TOWER' });
			me.game.add(missionTitle,this.z + 2);
			me.game.sort();
		//draw text to screen
			//INFILTRATE GALE-ELECTRO TOWER
	}
});


/* ---------------------
a Mission Title entity
----------------------*/

var MissionTitleEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		this.msg = settings.msg;
		
		/*
		tween1 = new me.Tween(this.pos).to({x:40}, 600);
		tween1.easing(me.Tween.Easing.Quartic.Out);
		me.audio.play("title");
		tween1.start().onComplete(function() {this.drawMissionText();}.bind(this));
		*/
		
		
		this.renderable.addAnimation('defaultAnim', null, 1);
		this.renderable.addAnimation('defaultAnimStop', [9], 1);
		this.renderable.setCurrentAnimation('defaultAnim',function(){this.drawMissionText();}.bind(this));
		me.audio.play('title_cloak');
	},
	update: function(){
		this.parent(this);
		return true;
	},
	drawMissionText:function(){
		this.renderable.setCurrentAnimation('defaultAnimStop');
		//Create Mission Title Object using 'mission_01_title'
		missionTitle = new MissionSubTitleEntity(0, 0, { msg: this.msg });
			me.game.add(missionTitle,this.z + 2);
			me.game.sort();
		//draw text to screen
			//INFILTRATE GALE-ELECTRO TOWER
	}
});

/* ---------------------
a Mission Sub-Title entity
----------------------*/

var MissionSubTitleEntity = me.ObjectEntity.extend({
	init: function(x,y,settings){
		settings.height = 240;
		settings.width = 320;
		this.alwaysUpdate = true;
		this.parent(x,y,settings);
		//Load the font
		this.font = new me.BitmapFont(TextFont,8);
		this.msg = settings.msg;
		this.msgSplit = this.msg.split('');
		this.msgIndex = 0;
		//console.log(this.msgSplit);
		this.msg = '';
		this.timer = 0;
		this.timer2 = 0;
		this.msgComplete = false;
	},
	update:function(){
		this.timer++;
		if(this.timer > 4){
			if(this.msgIndex < this.msgSplit.length){
				this.msg += this.msgSplit[this.msgIndex];
				this.msgIndex++;
				me.audio.play("text");
			}else{
				this.msgComplete = true;
			}
			this.timer = 0;
		}
		
		if(this.msgComplete) this.timer2++;
		
		if(this.timer2 > 120){
			this.timer2 = 0;
			this.msgComplete = false;
			//me.game.viewport.fadeIn('#000000',1000,function(){ me.levelDirector.loadLevel('m_01_lvl_01'); });
			//me.levelDirector.loadLevel('m_01_lvl_01');
			
			me.audio.play('title', false, null, 0.5);
			
			//leveltransition = new LevelTransitionEntity(-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
			var leveltransition = me.entityPool.newInstanceOf("leveltransition",-160, -120, {image:'spiraltransition3', spritewidth:640, spriteheight: 480, transitionType: 'out' });
					me.game.add(leveltransition,120);
					me.game.sort();
					
				//me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel('m_01_lvl_01'); });
				
				if(me.gamestat.getItemValue('loadingSaveGame')){
					me.gamestat.setValue('loadingSaveGame',false);
					me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel(gameData.load('currentLevel')); });
				}else{
					me.game.viewport.fadeIn('#000000',500, function(){ me.levelDirector.loadLevel('m_01_lvl_01'); });
				}
		}
		
	},
	draw: function(context){
		this.msgWidth = this.font.measureText(context,this.msg).width;
		this.font.draw(context,
			this.msg,40,
			200);
	}
});

/* ---------------------
Controls Handler
----------------------*/
var ControlHandlerEntity = me.ObjectEntity.extend({
	init:function(x,y){
		settings = {};
        settings.width = 0;
        settings.height = 0;		
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		this.nextLevel = me.game.getEntityByName("exitdoor")[0].nextLevel;
		this.mission = this.nextLevel.split("_")[01];
		
		//this.updateWhenPaused = true;
	},
	update:function(){
		//might as well keep track of time here
		me.gamestat.updateValue("timeToBeat", me.timer.tick);
		
		if(me.gamestat.getItemValue('currentMode') == 'timeAttack'){
			me.gamestat.updateValue('currentTimeAttackLevelTime',1);
		}else{
			me.gamestat.updateValue('current_level_time',1);
			//TO DO Set these next 2 only when saving the game
			me.gamestat.updateValue('current_mission_time',1);
			me.gamestat.updateValue('current_game_time',1);
		}
	
		//Retry
		if(me.input.isKeyPressed('retry')){
			//me.game.HUD.reset("EnergyGauge");
			me.levelDirector.reloadLevel();
		}
		
		//Pause The Game!
		if(me.input.isKeyPressed('pause')){
			if(me.state.isPaused()){
				me.state.resume();				
				//me.audio.resumeTrack();
				//console.log('track: ' + me.audio.getCurrentTrack);
			}else{
				//console.log('paused!');
				
				me.audio.play('computer_boot');
				
				//var pauseMenu = new PauseMenuEntity(0, 0,{spritewidth:320,spriteheight:240,image:'black'});
				var pauseMenu = me.entityPool.newInstanceOf("pausemenu",0, 0,{spritewidth:320,spriteheight:240,image:'black'});
				me.game.add(pauseMenu,199);
				//me.game.sort();
				
				me.state.pause(true);
				
				
			}
		}
		
		if(devMode){
			//Level Skip
			if(me.input.isKeyPressed('nextLevel')){ 
				//me.levelDirector.loadLevel(this.nextLevel);
				//me.game.HUD.setItemValue('LevelName',this.nextLevel);
				me.game.getEntityByName("exitdoor")[0].toNextLevel();
			}
			//Mission
					
			//Primative Level Select
			if(me.input.isKeyPressed('lvl_01')){ //01
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_01');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_01');
			}
			if(me.input.isKeyPressed('lvl_02')){ //02
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_02');
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_02');
			}
			if(me.input.isKeyPressed('lvl_03')){ //03
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_03');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_03');
			}
			if(me.input.isKeyPressed('lvl_04')){ //04
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_04');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_04');
			}
			if(me.input.isKeyPressed('lvl_05')){ //05
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_05');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_05');
			}
			if(me.input.isKeyPressed('lvl_06')){ //06
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_06');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_06');
			}
			if(me.input.isKeyPressed('lvl_07')){ //07
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_07');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_07');
			}
			if(me.input.isKeyPressed('lvl_08')){ //08
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_08');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_08');
			}
			if(me.input.isKeyPressed('lvl_09')){ //09
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_09');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_09');
			}
			if(me.input.isKeyPressed('lvl_10')){ //10
				me.levelDirector.loadLevel('m_' + this.mission + '_lvl_10');
				//me.game.HUD.setItemValue('LevelName','m_' + this.mission + '_lvl_10');
			}
		}
		//Toggle Music
		
		//Toggle Sound
	}
});


/* ---------------------
a camera entity
----------------------*/
var CameraEntity = me.ObjectEntity.extend({
	init:function(x,y){
		settings = {};
        settings.width = 0;
        settings.height = 0;
		this.parent(x,y,settings);
		this.alwaysUpdate = true;
		//viewport width
		//get map width	
		//console.log(me.game.currentLevel.tilewidth, me.game.currentLevel.width);
		this.cameraWidth = me.game.viewport.getWidth();
		this.cameraHeight = me.game.viewport.getHeight();
		//get map height
		//determine amount of sectors
		//Start on the Spy
		this.startGame = true;
		this.transitioning = false;
		
		//Ugh global vars...
		ScreenTransitionState = false;
		ScreenTransitionStart = false;
		
		this.defaultScale = 1;
		this.currentScale = 1;
		this.maxScale = 1.05;
		context = me.video.getScreenContext();
		//context.save();
		//context.scale(1.8, 1.8);
		//context.restore();
		//context.setTransform(1.5, 1.5,0,0,0,0);
		//me.video.scale(me.video.getScreenContext(), this.defaultScale);
		
		
		this.mapHeight = me.TMXTileMap.rows * me.TMXTileMap.tileheight;
		this.mapWidth = me.TMXTileMap.cols * me.TMXTileMap.tilewidth;
		//me.game.viewport.setBounds(mapWidth,mapHeight);
	
	},
	update:function(){
		//check the position of the spy
		//update the viewport accordingly
		//Don't need to run if map is only 1 section big
		
		//Zooming code - might not use here
		//if(this.currentScale < this.maxScale){
			//this.currentScale += 0.01;
			//me.video.scale(me.video.getScreenContext(), this.currentScale); 
		//}else{
		//}
		
		if(this.startGame){
			if(spy.pos.x + 16 < me.game.viewport.pos.x){ 
				testx = (Math.floor(spy.pos.x/this.cameraWidth) * this.cameraWidth);
				me.game.viewport.pos.x = testx;
			}else if((spy.pos.x + 8) > (me.game.viewport.pos.x + this.cameraWidth)){
				testx = (Math.floor((spy.pos.x + 8)/this.cameraWidth) * this.cameraWidth);
				me.game.viewport.pos.x = testx;
			}
			
			if((spy.pos.y + 12) > (me.game.viewport.pos.y + this.cameraHeight)){
				testy = (Math.floor((spy.pos.y + 8)/this.cameraHeight) * this.cameraHeight);
				me.game.viewport.pos.y = testy;
			}else if((spy.pos.y + 12) < (me.game.viewport.pos.y + this.cameraHeight)){
				testy = (Math.floor((spy.pos.y + 8)/this.cameraHeight) * this.cameraHeight);
				me.game.viewport.pos.y = testy;
			}
			
			this.startGame = false;
		}
		
		if(spy.alive && !this.transitioning){ //can't use visible since we want the camera to move a little before in some instances
			
			if(spy.pos.x + 12 < me.game.viewport.pos.x){ //Pan Left
				//console.log('pan left ' + spy.pos.x);
				this.transitioning = true;
				ScreenTransitionStart = true;
				testx = (Math.floor(spy.pos.x/this.cameraWidth) * this.cameraWidth);
				tween = new me.Tween(me.game.viewport.pos).to({x:testx}, 600);
				tween.easing(me.Tween.Easing.Quartic.Out);
				tween.onUpdate(function () {
                me.event.publish(me.event.VIEWPORT_ONCHANGE, [
						me.game.viewport.pos
					]);
				});
				tween.onComplete(function () {
						this.transitioning = false;
					}.bind(this));
				tween.start();
			}else if((spy.pos.x + 12) > (me.game.viewport.pos.x + this.cameraWidth)){ //Pan Right
				//console.log('pan right ' + spy.pos.x);
				this.transitioning = true;
				ScreenTransitionStart = true;
				testx = (Math.floor((spy.pos.x + 12)/this.cameraWidth) * this.cameraWidth);
				tween = new me.Tween(me.game.viewport.pos).to({x:testx}, 600);
				tween.easing(me.Tween.Easing.Quartic.Out);
				tween.onUpdate(function () {
                me.event.publish(me.event.VIEWPORT_ONCHANGE, [
						me.game.viewport.pos
					]);
				});
				tween.onComplete(function () {
						this.transitioning = false;
					}.bind(this));
				tween.start();
			}else if((spy.pos.y + 12) < (me.game.viewport.pos.y )){ //Pan Up
				//console.log('pan up ' + me.game.viewport.pos.y);
				
				if(me.game.viewport.pos.y !== 0){
					this.transitioning = true;
					ScreenTransitionStart = true;
					spy.boostUp = true;
					testy = (Math.floor((spy.pos.y + 12)/this.cameraHeight) * this.cameraHeight);
					tween = new me.Tween(me.game.viewport.pos).to({y:testy}, 600).onUpdate(function () {
					me.event.publish(me.event.VIEWPORT_ONCHANGE, [
							me.game.viewport.pos
						]);
					});
					tween.easing(me.Tween.Easing.Quartic.Out).onComplete(function () {
						this.transitioning = false;
					}.bind(this));
					
					tween.start();
				}else{
					this.transitioning = false;
				}
				//console.log(spy.pos.y, me.game.viewport.pos.y, this.cameraHeight);
			}else if((spy.pos.y + 12) > (me.game.viewport.pos.y + this.cameraHeight)){ //Pan Down
				this.transitioning = true;
				ScreenTransitionStart = true;
				//console.log('pan down');
				testy = (Math.floor((spy.pos.y + 12)/this.cameraHeight) * this.cameraHeight);
				
				
				tween = new me.Tween(me.game.viewport.pos)
					.to({ "y" : testy} , 600)
					.easing(me.Tween.Easing.Quartic.Out)
					.onUpdate(function () {
						//console.log('Viewport pos y 1:' + me.game.viewport.pos.y);
						me.event.publish(me.event.VIEWPORT_ONCHANGE, [
							me.game.viewport.pos
						]);
						//console.log('Viewport pos y 2:' + me.game.viewport.pos.y);
					})
					.onComplete(function () {
					this.transitioning = false;
					}.bind(this));
			
				tween.start();
				//console.log(spy.pos.y, me.game.viewport.pos.y, this.cameraHeight);
			}
			
			ScreenTransitionState = this.transitioning;
			//ScreenTransitionStart = false;
			//console.log(spy.pos.x + spy.pos.y + me.game.viewport.pos.x);
		}else{	
			ScreenTransitionStart = false;
			return false;
		}		
	}
});