/***********************************************************************

ai_monster_boss_guardian2.script

monster_boss_guardian2

***********************************************************************/

#define	GUARDIAN2_PAIN_DELAY				0.25
#define GUARDIAN2_RANGE_ATTACK_RANGE		1024
#define GUARDIAN2_RANGE_ATTACK_DELAY		7
#define GUARDIAN2_CHARGE_ATTACK_RANGE		680
#define GUARDIAN2_NUM_PROJECTILES			12
#define GUARDIAN2_ARTILLERY_PROJECTILES		4

// anim blend times
#define	GUARDIAN2_PAIN_TO_IDLE				3
#define GUARDIAN2_PAIN_TO_PAIN				3
#define GUARDIAN2_SIGHT_TO_IDLE				8
#define	GUARDIAN2_MELEE_TO_IDLE				12
#define GUARDIAN2_IDLE_TO_PAIN				3
#define GUARDIAN2_IDLE_TO_WALK				12
#define GUARDIAN2_IDLE_TO_CHARGE			12
#define GUARDIAN2_IDLE_TO_MELEE				12
#define	GUARDIAN2_IDLE_TO_RANGE				12
#define GUARDIAN2_IDLE_TO_SIGHT				12
#define GUARDIAN2_IDLE_TO_LOST				12
#define GUARDIAN2_WALK_TO_IDLE				12
#define GUARDIAN2_WALK_TO_PAIN				3
#define	GUARDIAN2_WALK_TO_CHARGE			8
#define	GUARDIAN2_CHARGE_TO_WALK			0
#define GUARDIAN2_CHARGE_TO_IDLE			12
#define GUARDIAN2_CHARGE_TO_PAIN			3
#define GUARDIAN2_LOST_TO_IDLE				10
#define GUARDIAN2_LOST_TO_PAIN				3
#define GUARDIAN2_LOST_TO_WALK				24
#define GUARDIAN2_LOST_TO_CHARGE			24
#define GUARDIAN2_RANGEATTACK_TO_IDLE		4
#define GUARDIAN2_SPAWN_TO_IDLE				4
#define	GUARDIAN2_IDLE_TO_SPAWN				4

// object seeker_base : monster_base {
// 	boolean			isAlive()						{ return !AI_DEAD; }
// 	void			respawnSeeker( entity enemy )	{ 0; }
// };

object monster_boss_guardian2_spawner_obj : monster_base {
	entity			lightning;
	entity			guardianEnt;
	entity			light;
	entity			beam;
	entity			beam_target;

	vector			beam_offset;
	vector			rotation;
	vector			beam_pain_color;
	vector			beam_color;
	vector			lightning_pain_color;
	vector			lightning_color;

	float			pain_time;
	float			inactive_time;
	float			active_time;

	void 			init();
	void 			destory();
	void 			setGuardian( entity owner );
	void			update_effects();
	void 			state_Inactive();
	void 			state_Active();
	void 			state_Killed();
};

object monster_boss_guardian2 : monster_base {
	float			nextAttack;
// 	seeker_base		seeker1;
// 	seeker_base		seeker2;
// 	seeker_base		seeker3;
	float			sightEnemyTime;
	boolean			in_melee;
	boolean			rightfoot;
	boolean			charge;
	float			ranged_combat_type;
	float			canDamageTime;

	entity			light1;
	entity			light2;

	monster_boss_guardian2_spawner_obj spawner;

	void 			Legs_Sight();
	void 			Legs_Death();
	void 			Legs_Pain();
	void			Legs_RangeAttack();
	void 			Legs_MeleeAttack();
	void 			Legs_Walk_Melee_Left();
	void 			Legs_Walk_Melee_Right();
	void 			Legs_Walk();
	void 			Legs_Run_Melee_Left();
	void 			Legs_Run_Melee_Right();
	void 			Legs_Charge();
	void 			Legs_Lost();
	void 			Legs_Idle();
	void 			Legs_SpawnSeeker();

	void 			init();
	void 			destory();
//	void 			addSeeker( entity seeker );
	void 			sightEnemy();
//	boolean 		seekersAreDead();
//	boolean 		spawnSeeker();
	boolean			combat_artillery_strike();
	boolean			combat_pound_fireball();
	void 			state_Idle();
	void 			state_Killed();
	void 			state_Combat();
	void 			combat_melee();
	void			combat_range();
	void			combat_charge();
};

void monster_boss_guardian2_spawner_obj::init() {
	active_time		= 0;
	inactive_time	= 0;
	pain_time		= 0;

	beam_offset				= getVectorKey( "beam_offset" );
	rotation				= getVectorKey( "rotate" );
	beam_pain_color 		= getVectorKey( "beam_pain_color" );
	beam_color				= getVectorKey( "beam_color" );
	lightning_pain_color	= getVectorKey( "lightning_pain_color" );
	lightning_color			= getVectorKey( "lightning_color" );

	sys.setSpawnArg( "_color", beam_color );
	sys.setSpawnArg( "name", getName() + "light" );
	sys.setSpawnArg( "light", "1024" );
	sys.setSpawnArg( "texture", getKey( "mtr_beam_light_shader" ) );
	sys.setSpawnArg( "start_off", "1" );
	light = sys.spawn( "light" );
	light.setOrigin( getWorldOrigin() );
	light.bind( self );

	sys.setSpawnArg( "name", getName() + "beam_target" );
	beam_target = sys.spawn( "func_beam" );
	beam_target.setOrigin( getWorldOrigin() );
	beam_target.bind( self );

	sys.setSpawnArg( "_color", beam_color );
	sys.setSpawnArg( "name", getName() + "beam" );
	sys.setSpawnArg( "skin", getKey( "mtr_beam_skin" ) );
	sys.setSpawnArg( "target", getName() + "beam_target" );
	sys.setSpawnArg( "start_off", "1" );
	beam = sys.spawn( "func_beam" );
	beam.setOrigin( getWorldOrigin() + beam_offset );
	beam.bind( self );

	setMoveType( MOVETYPE_STATIC );
	setState( "state_Inactive" );
}

void monster_boss_guardian2_spawner_obj::destory() {
	light.remove();
	beam.remove();
	beam_target.remove();
}

void monster_boss_guardian2_spawner_obj::setGuardian( entity owner ) {
	vector offset;

	guardianEnt = owner;
	setOwner( owner );

	offset = getVectorKey( "offset" );
	setOrigin( guardianEnt.getWorldOrigin() + offset );

	sys.setSpawnArg( "name", getName() + "_lightning" );
	sys.setSpawnArg( "nopush", "1" );
	sys.setSpawnArg( "solid", "0" );
	sys.setSpawnArg( "model", getKey( "lightning_model" ) );
	lightning = sys.spawn( "func_mover_amodel" );
	lightning.setOrigin( guardianEnt.getWorldOrigin() + offset );

	bindToJoint( guardianEnt, "origin", false );
	lightning.bind( self );
}

void monster_boss_guardian2_spawner_obj::update_effects() {
	vector	c;
	float	pain_frac;
	float	normal_frac;
	float	hide_frac;

	if ( active_time <= inactive_time ) {
		hide_frac = ( inactive_time + SPAWNER_FADEOUT - sys.getTime() ) / SPAWNER_FADEOUT;
	} else {
		hide_frac = ( sys.getTime() - active_time ) / SPAWNER_FADEIN_TIME;
		if ( hide_frac > 1 ) {
			hide_frac = 1;
		}
	}

	if ( hide_frac < 0 ) {
		hide();
		beam.hide();
		lightning.hide();
		return;
	}

	lightning.show();
	show();
	beam.show();

	lightning.setAngles( rotation * sys.getTime() );

	pain_frac = ( pain_time + SPAWNER_PAIN_FADEOUT - sys.getTime() ) / SPAWNER_PAIN_FADEOUT;
	if ( pain_frac < 0 ) {
		pain_frac = 0;
	}

	normal_frac = 1 - pain_frac;
	pain_frac *= hide_frac;
	normal_frac *= hide_frac;

	c = beam_pain_color * pain_frac + beam_color * normal_frac;
	setColor( c_x, c_y, c_z );
	beam.setColor( c_x, c_y, c_z );
	light.setColor( c_x, c_y, c_z );

	c = lightning_pain_color * pain_frac + lightning_color * normal_frac;
	lightning.setColor( c_x, c_y, c_z );
}

void monster_boss_guardian2_spawner_obj::state_Inactive() {
	inactive_time = sys.getTime();
	while( 1 ) {
		update_effects();
		waitFrame();
	}
}

void monster_boss_guardian2_spawner_obj::state_Active() {
	monster_boss_guardian2 guardian;

	active_time = sys.getTime();
	guardian = guardianEnt;

	lightning.show();
	show();
	light.fadeInLight( 0.5 );
	beam.show();

	while( 1 ) {
		if ( AI_DAMAGE ) {
			guardian.AI_PAIN = true;
			guardian.startSound( "snd_pain", SND_CHANNEL_VOICE, false );
			pain_time = sys.getTime();
			AI_DAMAGE = false;
		}
		update_effects();
		waitFrame();
	}
}

void monster_boss_guardian2_spawner_obj::state_Killed() {
	guardianEnt.setState( "state_Killed" );
	remove();
/*
	setMoveType( MOVETYPE_STATIC );
	inactive_time = sys.getTime();
	pain_time = sys.getTime();

	update_effects();
	while( !isHidden() ) {
		update_effects();
		waitFrame();
	}
	stopThinking();
*/
}

/***********************************************************************

	animation control

***********************************************************************/

void monster_boss_guardian2::Legs_Sight() {
	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "sight" );
	while( !animDone( ANIMCHANNEL_LEGS, GUARDIAN2_SIGHT_TO_IDLE ) ) {
		waitFrame();
	}
	
	finishAction( "sight" );
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_SIGHT_TO_IDLE );
}

void monster_boss_guardian2::Legs_Death() {
// 	seeker1.kill();
// 	seeker2.kill();
// 	seeker3.kill();
	playAnim( ANIMCHANNEL_LEGS, "death_ew" );

	// never exit
	waitUntil( 0 );
}

void monster_boss_guardian2::Legs_Pain() {
	float nextpain;
	float currenttime;

	float damageDelay = sys.random( 2 ) + 3;
	canDamageTime = sys.getTime() + damageDelay;
	ignoreDamage();
	//sys.print( "ignoreDamage()\n" );

	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "pain" );

	nextpain = sys.getTime() + GUARDIAN2_PAIN_DELAY;
	
	while( !animDone( ANIMCHANNEL_LEGS, GUARDIAN2_PAIN_TO_IDLE ) ) {
		if ( AI_PAIN ) {
			currenttime = sys.getTime();
			if ( currenttime > nextpain ) {
				animState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN2_PAIN_TO_PAIN );
			}
		}
		waitFrame();
	}
	
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_PAIN_TO_IDLE );
}

void monster_boss_guardian2::Legs_RangeAttack() {
	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "range_attack" );

	while( !animDone( ANIMCHANNEL_LEGS, GUARDIAN2_RANGEATTACK_TO_IDLE ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	preventPain( 1 );
	waitFrame();
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_RANGEATTACK_TO_IDLE );
}

void monster_boss_guardian2::Legs_MeleeAttack() {
	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "melee_attack" );

	while( !animDone( ANIMCHANNEL_LEGS, GUARDIAN2_MELEE_TO_IDLE ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	preventPain( 1 );
	waitFrame();
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_MELEE_TO_IDLE );
}

void monster_boss_guardian2::Legs_Walk_Melee_Left() {
	in_melee = true;
	rightfoot = false;
	playAnim( ANIMCHANNEL_LEGS, "walk_attack_left" );

	while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	preventPain( 1 );
	in_melee = false;

	if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
		animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Left", 0 );
	} else {
		animState( ANIMCHANNEL_LEGS, "Legs_Walk", 0 );
	}
}

void monster_boss_guardian2::Legs_Walk_Melee_Right() {
	in_melee = true;
	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "walk_attack_right" );

	while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	in_melee = false;
	preventPain( 1 );

	if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
		animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Right", 0 );
	} else {
		animState( ANIMCHANNEL_LEGS, "Legs_Walk", 0 );
	}
}

void monster_boss_guardian2::Legs_Walk() {
	if ( rightfoot ) {
		if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Right", 0 );
		}
		playAnim( ANIMCHANNEL_LEGS, "walk_right" );
	} else {
		if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Left", 0 );
		}
		playAnim( ANIMCHANNEL_LEGS, "walk_left" );
	}
	eachFrame {
		if ( AI_PAIN ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN2_WALK_TO_PAIN );
		}
		if ( !AI_FORWARD ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_WALK_TO_IDLE );
		}

		if ( animDone( ANIMCHANNEL_LEGS, 0 ) ) {
			if ( charge ) {
				animState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN2_WALK_TO_CHARGE );
			}
			rightfoot = !rightfoot;
			if ( rightfoot ) {
				if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
					animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Right", 0 );
				}
				playAnim( ANIMCHANNEL_LEGS, "walk_right" );
			} else {
				if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
					animState( ANIMCHANNEL_LEGS, "Legs_Walk_Melee_Left", 0 );
				}
				playAnim( ANIMCHANNEL_LEGS, "walk_left" );
			}

		}
	}
}

void monster_boss_guardian2::Legs_Run_Melee_Left() {
	in_melee = true;
	rightfoot = false;
	attackBegin( "damage_guardian2Charge" );
	playAnim( ANIMCHANNEL_LEGS, "run_attack_left" );

	while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	attackEnd();
	preventPain( 1 );
	in_melee = false;

	boolean canMelee = testMeleeAttack() && AI_ENEMY_IN_FOV;
	if ( canMelee || testAnimAttack( "run_attack_left" ) ) {
		animState( ANIMCHANNEL_LEGS, "Legs_Run_Melee_Left", 0 );
	} else {
		animState( ANIMCHANNEL_LEGS, "Legs_Charge", 0 );
	}
}

void monster_boss_guardian2::Legs_Run_Melee_Right() {
	in_melee = true;
	rightfoot = true;
	attackBegin( "damage_guardian2Charge" );
	playAnim( ANIMCHANNEL_LEGS, "run_attack_right" );

	while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
		preventPain( 1 );
		waitFrame();
	}
	
	attackEnd();
	in_melee = false;
	preventPain( 1 );

	boolean canMelee = testMeleeAttack() && AI_ENEMY_IN_FOV;
	if ( canMelee || testAnimAttack( "run_attack_right" ) ) {
		animState( ANIMCHANNEL_LEGS, "Legs_Run_Melee_Right", 0 );
	} else {
		animState( ANIMCHANNEL_LEGS, "Legs_Charge", 0 );
	}
}

void monster_boss_guardian2::Legs_Charge() {
	boolean canMelee = testMeleeAttack() && AI_ENEMY_IN_FOV;

	if ( rightfoot ) {
		if ( canMelee || testAnimAttack( "run_attack_right" ) ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Run_Melee_Right", 0 );
		}
		playAnim( ANIMCHANNEL_LEGS, "run_right" );
	} else {
		if ( canMelee || testAnimAttack( "run_attack_left" ) ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Run_Melee_Left", 0 );
		}
		playAnim( ANIMCHANNEL_LEGS, "run_left" );
	}

	eachFrame {
		if ( AI_PAIN ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN2_CHARGE_TO_PAIN );
		}
		if ( animDone( ANIMCHANNEL_LEGS, GUARDIAN2_CHARGE_TO_WALK ) ) {
//			sys.print( "charge = false in Legs_Charge()\n" );
			charge = false;
			animState( ANIMCHANNEL_LEGS, "Legs_Walk", GUARDIAN2_CHARGE_TO_WALK );
		}
	}
}

void monster_boss_guardian2::Legs_Lost() {
	rightfoot = true;
	idleAnim( ANIMCHANNEL_LEGS, "lost_enemy" );

	eachFrame {
		if ( AI_PAIN ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN2_LOST_TO_PAIN );
		}
		if ( AI_FORWARD ) {
			if ( charge ) {
				animState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN2_LOST_TO_CHARGE );
			} else {
				animState( ANIMCHANNEL_LEGS, "Legs_Walk", GUARDIAN2_LOST_TO_WALK );
			}
		}
		if ( sightEnemyTime >= sys.getTime() ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_LOST_TO_IDLE );
		}
	}
}

void monster_boss_guardian2::Legs_Idle() {
	idleAnim( ANIMCHANNEL_LEGS, "idle" );

	eachFrame {
		if ( AI_PAIN ) {
			animState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN2_IDLE_TO_PAIN );
		}
		if ( AI_FORWARD ) {
			if ( charge ) {
				animState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN2_IDLE_TO_CHARGE );
			} else {
				animState( ANIMCHANNEL_LEGS, "Legs_Walk", GUARDIAN2_IDLE_TO_WALK );
			}
		}
		if ( getEnemy() ) {
			if ( sightEnemyTime < sys.getTime() ) {
				animState( ANIMCHANNEL_LEGS, "Legs_Lost", GUARDIAN2_IDLE_TO_LOST );
			}
		}
	}
}

void monster_boss_guardian2::Legs_SpawnSeeker() {
	rightfoot = true;
	playAnim( ANIMCHANNEL_LEGS, "spawn_seeker" );
	while( !animDone( ANIMCHANNEL_LEGS, GUARDIAN2_SPAWN_TO_IDLE ) ) {
		preventPain( 1 );
		waitFrame();
	}
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN2_SPAWN_TO_IDLE );
}

/***********************************************************************

	AI

***********************************************************************/

/*
=====================
monster_boss_guardian2::init
=====================
*/
void monster_boss_guardian2::init() {
	vector color;

	ranged_combat_type		= 1;

	color = getVectorKey( "light_color" );

	sys.setSpawnArg( "name", getName() + "_light1" );
	light1 = sys.spawn( "light" );
	light1.setShader( getKey( "mtr_light_shader" ) );
	light1.setRadius( getFloatKey( "light_radius" ) );
	light1.bindToJoint( self, "Rhand", true );
	light1.setOrigin( getVectorKey( "light_offset_right" ) );
	light1.setColor( color_x, color_y, color_z );

	sys.setSpawnArg( "name", getName() + "_light2" );
	light2 = sys.spawn( "light" );
	light2.setShader( getKey( "mtr_light_shader" ) );
	light2.setRadius( getFloatKey( "light_radius" ) );
	light2.bindToJoint( self, "Lhand", true );
	light2.setOrigin( getVectorKey( "light_offset_left" ) );
	light2.setColor( color_x, color_y, color_z );

	rightfoot = true;
	charge = false;
	canDamageTime = 1;

	setMoveType( MOVETYPE_ANIM );

//	ignoreDamage();

	sightEnemyTime = -1;

	sys.setSpawnArg( "name", getName() + "_spawn" );
	spawner = sys.spawn( "monster_boss_guardian2_spawner_obj" );
	spawner.setGuardian( self );
	
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
	setState( "state_Idle" );
}

/*
=====================
monster_boss_guardian2::destory
=====================
*/
void monster_boss_guardian2::destory() {
	spawner.remove();
	light1.remove();
	light2.remove();
}

/*
=====================
monster_boss_guardian2::addSeeker
=====================
*/
// void monster_boss_guardian2::addSeeker( entity seeker ) {
// 	if ( !seeker1 ) {
// 		seeker1 = seeker;
// 	} else if ( !seeker2 ) {
// 		seeker2 = seeker;
// 	} else if ( !seeker3 ) {
// 		seeker3 = seeker;
// 	} else {
// 		sys.error( "'" + getName() + "' was targeted by more than 3 seekers" );
// 	}
// }

/*
=====================
monster_boss_guardian2::sightEnemy
=====================
*/
void monster_boss_guardian2::sightEnemy() {
	sightEnemyTime = sys.getTime() + 0.5;
	locateEnemy();

	// all seeker's now know the location
// 	seeker1.locateEnemy();
// 	seeker2.locateEnemy();
// 	seeker3.locateEnemy();
}

/*
=====================
monster_boss_guardian2::seekersAreDead
=====================
*/
// boolean monster_boss_guardian2::seekersAreDead() {
// 	if ( seeker1.isAlive() ) {
// 		return false;
// 	}
// 
// 	if ( seeker2.isAlive() ) {
// 		return false;
// 	}
// 
// 	if ( seeker3.isAlive() ) {
// 		return false;
// 	}
// 
// 	return true;
// }


/*
=====================
monster_boss_guardian2::spawnSeeker
=====================
*/
// boolean monster_boss_guardian2::spawnSeeker() {
// 	entity enemy;
// 
// 	// don't go into lost anim for a bit
// 	sightEnemyTime = sys.getTime() + 20;
// 	stopMove();
// 
// 	spawner.setState( "state_Active" );
// 	sys.wait( 1 );
// 
// 	animState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker", GUARDIAN2_IDLE_TO_SPAWN );
// 	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker" ) ) {
// 		waitFrame();
// 	}
// 
// 	enemy = getEnemy();
// 	if ( !( !seeker1 ) && !seeker1.isAlive() ) {
// 		seeker1.respawnSeeker( enemy );
// 	}
// 
// 	animState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker", GUARDIAN2_IDLE_TO_SPAWN );
// 	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker" ) ) {
// 		waitFrame();
// 	}
// 
// 	if ( !( !seeker2 ) && !seeker2.isAlive() ) {
// 		seeker2.respawnSeeker( enemy );
// 	}
// 
// 	animState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker", GUARDIAN2_IDLE_TO_SPAWN );
// 	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker" ) ) {
// 		waitFrame();
// 	}
// 
// 	if ( !( !seeker3 ) && !seeker3.isAlive() ) {
// 		seeker3.respawnSeeker( enemy );
// 	}
// 
// 	sys.wait( 0.5 );
// 	sightEnemyTime = sys.getTime() - 0.1;
// 	spawner.setState( "state_Inactive" );
// }

/*
=====================
monster_boss_guardian2::state_Idle
=====================
*/
void monster_boss_guardian2::state_Idle() {
	if ( getIntKey( "hide" ) ) {
		//
		// hide until triggered
		//
		hide();
		waitUntil( AI_ACTIVATED );
		if ( getIntKey( "hide" ) == 1 ) {
			AI_ACTIVATED = false;
			clearEnemy();
		}
		waitUntil( canBecomeSolid() );
		show();
//		ignoreDamage();
	}

	wait_for_enemy();

	faceEnemy();

	// don't go into lost anim for a bit
	sightEnemyTime = sys.getTime() + 20;
	animState( ANIMCHANNEL_LEGS, "Legs_Sight", GUARDIAN2_IDLE_TO_SIGHT );
	waitAction( "sight" );

	nextAttack = RandomTime( GUARDIAN2_RANGE_ATTACK_DELAY );
	setState( "state_Combat" );
}

/*
=====================
monster_boss_guardian2::state_Killed
=====================
*/
void monster_boss_guardian2::state_Killed() {
	activateTargets( $world );

	light1.fadeOutLight( 0.5 );
	light2.fadeOutLight( 0.5 );

	AI_DEAD = true;
	stopMove();
	animState( ANIMCHANNEL_LEGS, "Legs_Death", 0 );
	waitAction( "dead" );
	
	stopThinking();
}

/*
=====================
monster_boss_guardian2::state_Combat
=====================
*/
void monster_boss_guardian2::state_Combat() {
	while( 1 ) {
		if ( canDamageTime > 0 && canDamageTime < sys.getTime() ) {
			allowDamage();
			canDamageTime = 0;
		}
		//sys.print( "state_Combat\n" );
		if ( AI_ENEMY_DEAD ) {
			enemy_dead();
			continue;
		}
		while( sightEnemyTime < sys.getTime() ) {
			//sys.print( "state_Combat : 1\n" );
			stopMove();
// 			if ( seekersAreDead() ) {
// 				spawnSeeker();
// 			}
		 	sightEnemyTime = sys.getTime() + 20;
			waitFrame();
			if ( canDamageTime > 0 && canDamageTime < sys.getTime() ) {
				allowDamage();
				canDamageTime = 0;
			}
		}

		while( sightEnemyTime >= sys.getTime() ) {
			if ( canDamageTime > 0 && canDamageTime < sys.getTime() ) {
				allowDamage();
				canDamageTime = 0;
			}
			//sys.print( "state_Combat : 2\n" );
			if ( in_melee ) {
				waitFrame();
				continue;
			}
// 			if ( seekersAreDead() ) {
// 				spawnSeeker();
// 			}
		 	sightEnemyTime = sys.getTime() + 20;
			//sys.print( "moveToEnemy()\n" );
			moveToEnemy();
			if ( !inAnimState( ANIMCHANNEL_TORSO, "Legs_Pain" ) ) {
				if ( AI_DEST_UNREACHABLE || ( sys.getTime() >= nextAttack ) ) {
					if ( enemyRange() < GUARDIAN2_RANGE_ATTACK_RANGE ) {
						if ( canHitEnemy() ) {
							combat_range();
							waitFrame();
							continue;
						}
					}
				} else if ( enemyRange() > GUARDIAN2_CHARGE_ATTACK_RANGE ) {
					if ( canHitEnemy() ) {
						combat_charge();
						waitFrame();
						continue;
					}
				}
			}

			if ( testMeleeAttack() && AI_ENEMY_IN_FOV ) {
				combat_melee();
			} 
			waitFrame();
		}
	}
}

/*
=====================
monster_boss_guardian2::combat_melee
=====================
*/
void monster_boss_guardian2::combat_melee() {
	//sys.print( "combat_melee()\n" );
	stopMove();
	animState( ANIMCHANNEL_LEGS, "Legs_MeleeAttack", GUARDIAN2_IDLE_TO_MELEE );
	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_MeleeAttack" ) ) {
		waitFrame();
	}
}

/*
=====================
monster_boss_guardian2::combat_range
=====================
*/
void monster_boss_guardian2::combat_range() {
	//sys.print( "combat_range()\n" );
	faceEnemy();
	stopMove();

	if ( ranged_combat_type > 1 ) {
		combat_pound_fireball();
		ranged_combat_type--;
	} else {
		combat_artillery_strike();
		ranged_combat_type = sys.random( 3 ) + 1;
	}

	if ( ranged_combat_type > 1 ) {
		nextAttack = sys.getTime() + 1;
	} else {
		nextAttack = DelayTime( GUARDIAN2_RANGE_ATTACK_DELAY );
	}
}

/*
=====================
monster_boss_guardian2::combat_charge
=====================
*/
void monster_boss_guardian2::combat_charge() {
	//sys.print( "combat_charge()\n" );
	charge = true;
	//sys.print( "moveToEnemy()\n" );
	moveToEnemy();
	//sys.print( "while charge()\n" );
	while( charge ) {
		waitFrame();
	}
	//sys.print( "stopMove()\n" );
	stopMove();
	//sys.print( "combat_charge() ... done\n" );
	charge = false;
}

/*
=====================
monster_boss_guardian2::combat_pound_fireball
=====================
*/
boolean monster_boss_guardian2::combat_pound_fireball() {
	//sys.print( "combat_pound_fireball()\n" );
	animState( ANIMCHANNEL_LEGS, "Legs_RangeAttack", GUARDIAN2_IDLE_TO_RANGE );
	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_RangeAttack" ) ) {
		waitFrame();
	}
}

/*
=====================
monster_boss_guardian2::combat_artillery_strike
=====================
*/
boolean monster_boss_guardian2::combat_artillery_strike() {
	//sys.print( "combat_artillery_strike()\n" );
	animState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker", GUARDIAN2_IDLE_TO_SPAWN );
	while( inAnimState( ANIMCHANNEL_LEGS, "Legs_SpawnSeeker" ) ) {
		waitFrame();
	}
}

/*
=====================
monster_boss_guardian2::pound_impact
=====================
*/
void monster_boss_guardian2::pound_impact( string joint ) {
	//sys.print( "pound_impact()\n" );

	string	entname;
	entity	explosion;
	float	handJoint;
	vector	org;

	handJoint = getJointHandle( joint );
	org = getJointPos( handJoint );

	sys.radiusDamage( org, self, self, spawner, "damage_guardian2PoundGround", 1.0 );

	entname = getKey( "def_poundground" );
	explosion = sys.spawn( entname );
	explosion.setOrigin( org - '0 0 32');
	explosion.setShaderParm( 4, -sys.getTime() );	
	sys.wait( 0.75 );
	explosion.remove();
}

/*
=====================
monster_boss_guardian2::pound_attack
=====================
*/
void monster_boss_guardian2::pound_attack( string joint ) {
	//sys.print( "pound_attack()\n" );

	float	handJoint;
	vector	org;
	vector	ang;
	float	i;

	handJoint = getJointHandle( joint );
	org = getJointPos( handJoint );

	sys.radiusDamage( org, self, self, spawner, "damage_guardian2PoundGround", 1.0 );

	ang = getAngles();
	for( i = 0; i < GUARDIAN2_NUM_PROJECTILES; i++ ) {
		ang_y += 360 / GUARDIAN2_NUM_PROJECTILES;
		launchMissile( org, ang );
	}

	thread pound_impact( joint );
}

/*
=====================
monster_boss_guardian2::pound_attack_left
=====================
*/
void monster_boss_guardian2::pound_attack_left() {
	pound_attack( "lhand" );
}

/*
=====================
monster_boss_guardian2::pound_attack_right
=====================
*/
void monster_boss_guardian2::pound_attack_right() {
	pound_attack( "rhand" );
}

/*
=====================
monster_boss_guardian2::smash_ground
=====================
*/
void monster_boss_guardian2::smash_ground() {
	float	handJoint;
	vector	org1, org2, org;
	vector	ang;
	float	i;
	
	thread pound_impact( "lhand" );
	thread pound_impact( "rhand" );

	handJoint = getJointHandle( "lhand" );
	org1 = getJointPos( handJoint );
	handJoint = getJointHandle( "rhand" );
	org2 = getJointPos( handJoint );
	org = ( org1 + org2 ) * 0.5;

	ang = getAngles();
	for( i = 0; i < GUARDIAN2_NUM_PROJECTILES; i++ ) {
		ang_y += 360 / GUARDIAN2_NUM_PROJECTILES;
		launchMissile( org, ang );
	}
}

/*
=====================
monster_boss_guardian2::artillery_strike
=====================
*/
void monster_boss_guardian2::artillery_strike() {
//	float i;

//	setHomingMissileGoal();
//	for( i = 0; i < GUARDIAN2_ARTILLERY_PROJECTILES; i++ ) {
		launchHomingMissile();
		wait( 0.25 );
		launchHomingMissile();
		wait( 0.25 );
		launchHomingMissile();
		wait( 0.25 );
		launchHomingMissile();
		wait( 0.25 );
//	}
}