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

ai_monster_zombie_commando_tentacle.script

monster_zombie_commando_tentacle

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

#define ZCT_RUNDISTANCE			128
#define ZCT_WALKTURN			65
#define ZCT_ATTACK_RATE			5
#define ZCT_TENTACLE_RANGE_MAX	200
#define ZCT_NOFOVTIME			4

#define ATTACK_TENTACLE			ATTACK_SPECIAL1

object monster_zombie_commando_tentacle : monster_base {
	float		nextAttack;
	float		nextNoFOVAttack;
	boolean		tentacleDamage;

	//
	// States
	//
	void		state_Begin();
	void		state_Idle();

	// attacks
	float		check_attacks();
	void		do_attack( float attack_flags );
	void		combat_tentacle();
	void		combat_melee();

	void		init();

	// torso anim states
	void		Torso_Idle();
	void		Torso_Pain();
	void		Torso_MeleeAttack();
	void		Torso_TentacleAttack();
	
	// legs anim states
	void		Legs_Idle();
	void		Legs_Walk();
	void		Legs_Run();
};

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

	Torso animation control

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

void monster_zombie_commando_tentacle::Torso_Idle() {
	idleAnim( ANIMCHANNEL_TORSO, "idle" );
	
	eachFrame {
		if ( AI_PAIN ) { animState( ANIMCHANNEL_TORSO, "Torso_Pain", 0 ); }
	}
}

void monster_zombie_commando_tentacle::Torso_Pain() {
	string animname;
	float nextpain;
	float currenttime;
	
	animname = getPainAnim();
	playAnim( ANIMCHANNEL_TORSO, animname );

	nextpain = sys.getTime() + 0.25;
	
	while( !animDone( ANIMCHANNEL_TORSO, 2 ) ) {
		if ( AI_PAIN ) {
			currenttime = sys.getTime();
			if ( currenttime > nextpain ) {
				animState( ANIMCHANNEL_TORSO, "Torso_Pain", 0 );
			}
		}
		waitFrame();
	}

	finishAction( "pain" );
	animState( ANIMCHANNEL_TORSO, "Torso_Idle", 2 );
}

void monster_zombie_commando_tentacle::Torso_MeleeAttack() {
	playAnim( ANIMCHANNEL_TORSO, "melee_attack" );

	while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
		waitFrame();
	}
	
	finishAction( "melee_attack" );
	animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}

void monster_zombie_commando_tentacle::Torso_TentacleAttack() {
	disablePain();
	faceEnemy();

	playAnim( ANIMCHANNEL_TORSO, "range_attack" );
	while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
		waitFrame();
	}

	finishAction( "tentacle_attack" );
	animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}

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

	Legs animation control

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

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

	eachFrame {
		if ( run && AI_FORWARD )	{ animState( ANIMCHANNEL_LEGS, "Legs_Run", 4 ); }
		if ( AI_FORWARD )			{ animState( ANIMCHANNEL_LEGS, "Legs_Walk", 4 ); }
	}
}

void monster_zombie_commando_tentacle::Legs_Walk() {
	playCycle( ANIMCHANNEL_LEGS, "walk" );
	
	eachFrame {
		if ( run && AI_FORWARD )	{ animState( ANIMCHANNEL_LEGS, "Legs_Run", 4 ); }
		if ( !AI_FORWARD )			{ animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 ); }
	}
}

void monster_zombie_commando_tentacle::Legs_Run() {
	playCycle( ANIMCHANNEL_LEGS, "run" );
	
	eachFrame {
		if ( !run && AI_FORWARD )	{ animState( ANIMCHANNEL_LEGS, "Legs_Walk", 4 ); }
		if ( !AI_FORWARD )			{ animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 ); }
	}
}

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

	AI

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

/*
=====================
monster_zombie_commando_tentacle::init
=====================
*/
void monster_zombie_commando_tentacle::init() {
	run_distance	= ZCT_RUNDISTANCE;
	walk_turn		= ZCT_WALKTURN;

	setState( "state_Begin" );
}

/*
=====================
monster_zombie_commando_tentacle::state_Begin
=====================
*/
void monster_zombie_commando_tentacle::state_Begin() {
	animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
	animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );

	monster_begin();
	setMoveType( MOVETYPE_ANIM );	
	setState( "state_Idle" );
}

/*
=====================
monster_zombie_commando_tentacle::state_Idle
=====================
*/
void monster_zombie_commando_tentacle::state_Idle() {
	wait_for_enemy();
	
	tentacleDamage	= false;
	nextAttack		= 0;
	nextNoFOVAttack = 0;
	
	setState( "state_Combat" );
}

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

	attacks

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

/*
=====================
monster_zombie_commando_tentacle::do_attack
=====================
*/
void monster_zombie_commando_tentacle::do_attack( float attack_flags ) {
	nextNoFOVAttack = sys.getTime() + ZCT_NOFOVTIME;
	if ( attack_flags & ATTACK_MELEE ) {
		combat_melee();
	} else if ( attack_flags & ATTACK_TENTACLE ) {
		combat_tentacle();
	}
}

/*
=====================
monster_zombie_commando_tentacle::check_attacks
=====================
*/
float monster_zombie_commando_tentacle::check_attacks() {
	float range;
	float currentTime;
	float attack_flags;
	
	attack_flags = 0;	

	if ( testMeleeAttack() ) {
		attack_flags |= ATTACK_MELEE;
	}

	if ( ( ( sys.getTime() > nextNoFOVAttack ) && AI_ENEMY_VISIBLE ) || AI_ENEMY_IN_FOV ) {
		range = enemyRange();
		currentTime = sys.getTime();
		if ( ( range < ZCT_TENTACLE_RANGE_MAX ) && ( !canReachEnemy() || ( currentTime >= nextAttack ) ) ) {
			if ( canHitEnemy() ) {
				attack_flags |= ATTACK_TENTACLE;
			}
		}
	}
	
	return attack_flags;
}

/*
=====================
monster_zombie_commando_tentacle::tentacle_attack_start
=====================
*/
void monster_zombie_commando_tentacle::tentacle_attack_start() {
	tentacleDamage = true;
}

/*
=====================
monster_zombie_commando_tentacle::tentacle_attack_end
=====================
*/
void monster_zombie_commando_tentacle::tentacle_attack_end() {
	tentacleDamage = false;
}

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

	Combat

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

/*
=====================
monster_zombie_commando_tentacle::combat_tentacle
=====================
*/
void monster_zombie_commando_tentacle::combat_tentacle() {
	tentacleDamage = false;
	stopMove();
	animState( ANIMCHANNEL_TORSO, "Torso_TentacleAttack", 4 );
	while( inAnimState( ANIMCHANNEL_TORSO, "Torso_TentacleAttack" ) ) {
		if ( tentacleDamage ) {
			if ( meleeAttackToJoint( "joint13", "melee_commandoTentacle" ) ) {
				tentacleDamage = false;
			}
		}
		waitFrame();
	}
	
	tentacleDamage = false;

	// don't attack for a bit
	nextAttack = DelayTime( ZCT_ATTACK_RATE );
	nextNoFOVAttack = sys.getTime() + ZCT_NOFOVTIME;
}

/*
=====================
monster_zombie_commando_tentacle::combat_melee
=====================
*/
void monster_zombie_commando_tentacle::combat_melee() {
	tentacleDamage = false;
	faceEnemy();
	animState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack", 5 );
	while( inAnimState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack" ) ) {
		lookAtEnemy( 1 );
		if ( tentacleDamage ) {
			if ( meleeAttackToJoint( "joint13", "melee_commandoTentacle" ) ) {
				tentacleDamage = false;
			}
		}
		waitFrame();
	}
	tentacleDamage = false;
}