#using scripts\codescripts\struct;

#using scripts\shared\clientfield_shared;
#using scripts\shared\gameskill_shared;
#using scripts\shared\math_shared;
#using scripts\shared\statemachine_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\turret_shared;
#using scripts\shared\flag_shared;
#using scripts\shared\damagefeedback_shared;
#using scripts\shared\laststand_shared;
#using scripts\shared\gameobjects_shared;
#using scripts\cp\_objectives;

    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                            	  	  	              	   	                                                                                                                                       	                                                                                                                                                            	                                                                                                                                                                

#using scripts\shared\ai\systems\blackboard;
#using scripts\shared\ai\blackboard_vehicle;
                                                                  	                             	  	                                      

#using scripts\cp\gametypes\_globallogic_ui;

#using scripts\shared\vehicle_shared;
#using scripts\shared\vehicle_ai_shared;
#using scripts\shared\vehicle_death_shared;

#using scripts\cp\_oed;


	






	

 //Number of times that a player can destroy the trophy weakspot before it is permanently destroyed
	
 //Used to limit the number of spikes that can hit a QT before trophy system gets re-enabled
	



	




 //an actor target must be at least this range from the QT for the QT to use the javelin attack


	
#precache( "objective", "cp_quadtank_weakpoint" );
#precache( "objective", "cp_quadtank_trophy_disabled" );
#precache( "objective", "cp_quadtank_rocket_icon" );
	

#precache( "string", "tag_target_lower" );
	
#namespace quadtank;

function autoexec __init__sytem__() {     system::register("quadtank",&__init__,undefined,undefined);    }
	
#using_animtree( "generic" );

function __init__()
{
	vehicle::add_main_callback( "quadtank", &quadtank_initialize );

	clientfield::register( "toplayer", "player_shock_fx", 1, 1, "int" );
	clientfield::register( "vehicle", "quadtank_trophy_state", 1, 1, "int" ); 
}

function quadtank_initialize() 
{
	self useanimtree( #animtree );
	
	self EnableAimAssist();
	self SetNearGoalNotifyDist( 50 );
	
	// AI SPECIFIC INITIALIZATION
	blackboard::CreateBlackBoardForEntity( self );
	self Blackboard::RegisterVehicleBlackBoardAttributes();
	
	self.turret_state = 1;
	
	self.fovcosine = 0; // +/-90 degrees = 180 fov, err 0 actually means 360 degree view
	self.fovcosinebusy = 0;
	self.maxsightdistsqrd = ( (10000) * (10000) );
	
	self.weakpointobjective = 0;
	self.combatactive = true; //used for weakpoint marker to make sure that objective is not added if tank is off
	self.damage_during_trophy_down = 0;
	self.spike_hits_during_trophy_down = 0;
	self.trophy_disables = 0;
	self.allow_movement = true;
	
	assert( isdefined( self.scriptbundlesettings ) );
	
	self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
	
	
	objectives::set( "cp_quadtank_rocket_icon", self );
	objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
	

	self.variant = "cannon";
	
	if( IsSubStr( self.vehicleType, "mlrs" ) )
	{
		self.variant = "rocketpod";
	}
	
	self.goalRadius = 9999999;
	self.goalHeight = 512;
	self SetGoal( self.origin, false, self.goalRadius, self.goalHeight );

	self SetSpeed( self.settings.defaultMoveSpeed, 10, 10 );
	self SetMinDesiredTurnYaw( 45 );
	self show_weak_spots( false );
	
	turret::_init_turret( 1 );
	turret::_init_turret( 2 );
	
	turret::set_best_target_func( &_get_best_target_quadtank_side_turret, 1 );
	turret::set_best_target_func( &_get_best_target_quadtank_side_turret, 2 );
	
	self quadtank_update_difficulty();
	
	self quadtank_side_turrets_forward();	
	self.overrideVehicleDamage = &QuadtankCallback_VehicleDamage;

	//disable some cybercom abilities
	if( IsDefined( level.vehicle_initializer_cb ) )
	{
    	[[level.vehicle_initializer_cb]]( self );
	}

	self.ignoreFireFly = true;
	self.ignoreDecoy = true;
	self vehicle_ai::InitThreatBias();

	self.disableElectroDamage = true;
	self.disableBurnDamage = true;

	self thread vehicle_ai::target_hijackers();

	self HidePart( "tag_defense_active" );
	
	defaultRole();
}

function quadtank_update_difficulty()
{
//	testing out changing the turret parameters based solely upon the number of players, since damage
//	is alread scaled based upon the difficulty of the individual player
//	so, saving out current method until change has been tested
//
//	value = gameskill::get_general_difficulty_level();
//	
//	scale_up = mapfloat( 0, 7, 0.8, 2.0, value );
//	scale_down = mapfloat( 0, 7, 1.0, 0.5, value );
	
	if( isDefined( level.players) )
	{
		value = level.players.size;
	}
	else
	{
		value = 1;
	}
	
	
	scale_up = mapfloat( 1, 4, 1, 1.5, value );
	scale_down = mapfloat( 1, 4, 1.0, 0.75, value );
	
	turret::set_burst_parameters( 1.5, 2.5 * scale_up, 0.25 * scale_down, 0.75 * scale_down, 1 );
	turret::set_burst_parameters( 1.5, 2.5 * scale_up, 0.25 * scale_down, 0.75 * scale_down, 2 );
	
	self.difficulty_scale_up = scale_up;
	self.difficulty_scale_down = scale_down;
}

function defaultRole()
{
	self.state_machine = self vehicle_ai::init_state_machine_for_role( "default" );
	
    self vehicle_ai::get_state_callbacks( "pain" ).update_func = &pain_update;
    self vehicle_ai::get_state_callbacks( "emped" ).update_func = &quadtank_emped;

    self vehicle_ai::get_state_callbacks( "off" ).enter_func = &state_off_enter;
    self vehicle_ai::get_state_callbacks( "off" ).exit_func = &state_off_exit;

    self vehicle_ai::get_state_callbacks( "scripted" ).update_func = &state_scripted_update;
    self vehicle_ai::get_state_callbacks( "driving" ).update_func = &state_driving_update;
    
    self vehicle_ai::get_state_callbacks( "combat" ).update_func = &state_combat_update;
    self vehicle_ai::get_state_callbacks( "combat" ).exit_func = &state_combat_exit;

    self vehicle_ai::get_state_callbacks( "death" ).update_func = &quadtank_death;

    self vehicle_ai::call_custom_add_state_callbacks();
    
	self vehicle_ai::StartInitialState();
}

// ----------------------------------------------
// State: off
// ----------------------------------------------
function quadtank_off()
{
	self vehicle_ai::set_state( "off" );
	self.combatactive = false;
}

function quadtank_on()
{
	self vehicle_ai::set_state( "combat" );
	self.combatactive = true;
}
	
function state_off_enter( params )
{
	self playsound( "veh_quadtank_power_down" );

	self LaserOff();
	self ClearTargetEntity();
	self CancelAIMove();
	self ClearVehGoalPos();

	vehicle_ai::TurnOffAllLightsAndLaser();
	vehicle_ai::TurnOffAllAmbientAnims();
	self vehicle::toggle_tread_fx( 0 );
	self vehicle::toggle_sounds( 0 );
	self vehicle::toggle_exhaust_fx( 0 );
	
	angles = self GetTagAngles( "tag_flash" );
	target_vec = self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
	target_vec = target_vec + ( 0, 0, -500 );
	self SetTargetOrigin( target_vec );		
	self set_side_turrets_enabled( false );
	self thread quadtank_disabletrophy();

	if( !isdefined( self.emped ) )
	{
		self DisableAimAssist();
	}
}

function state_off_exit( params )
{
	self vehicle::lights_on();
	self vehicle::toggle_tread_fx( 1 );
	self vehicle::toggle_sounds( 1 );
	self thread bootup();
	self vehicle::toggle_exhaust_fx( 1 );
	self EnableAimAssist();
}

function bootup()
{
	self endon("death");
	self playsound( "veh_quadtank_power_up" );
	self vehicle_ai::blink_lights_for_time( 1.5 );
	
	angles = self GetTagAngles( "tag_flash" );
	target_vec = self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
	self.turretRotScale = 0.3;
	
	driver = self GetSeatOccupant( 0 );
	if( !isdefined(driver) )
	{
		self SetTargetOrigin( target_vec );
	}
	wait 1;
	
	self.turretRotScale = 1 * self.difficulty_scale_up;
}
// State: off -----------------------------------

// ----------------------------------------------
// State: pain
// ----------------------------------------------
function pain_update( params )
{
	self endon( "change_state" );
	self endon( "death" );
	
	isTrophyDownPain = params.notify_param[0];

	if( isTrophyDownPain === true )
	{
		// trophy system must be going down now
		asmState = "trophy_disabled@stationary";
	}
	else 
	{
		// can only take pain when trophy is down
		asmState = "pain@stationary";
	}
	self ASMRequestSubstate( asmState );
	playsoundatposition ("prj_quad_impact", self.origin);
	
	self CancelAIMove();
	self ClearVehGoalPos();	
	self ClearTurretTarget();
	self SetBrake( 1 );
	
	self vehicle_ai::waittill_asm_complete( asmState, 6 );
	
	self SetBrake( 0 );

	self ASMRequestSubstate( "locomotion@movement" );
	
	driver = self GetSeatOccupant( 0 );
	if( !isdefined( driver ) )
	{
		self vehicle_ai::set_state( "combat" );
	}
	else
	{
		self vehicle_ai::set_state( "driving" );
	}
}
// State: pain ----------------------------------

// ----------------------------------------------
// State: scripted
// ----------------------------------------------
function state_scripted_update( params )
{
	self endon( "death" );
	self endon( "change_state" );
	
	self set_side_turrets_enabled( false );
	self LaserOff();
	self ClearTargetEntity();
	self CancelAIMove();
	self ClearVehGoalPos();

	self vehicle::toggle_ambient_anim_group( 2, true );
}
// State: scripted ------------------------------

// ----------------------------------------------
// State: driving
// ----------------------------------------------
function state_driving_update( params )
{
	self endon( "death" );
	self endon( "change_state" );

	self set_side_turrets_enabled( false );
	self LaserOff();
	self ClearTargetEntity();
	self CancelAIMove();
	self ClearVehGoalPos();

	self vehicle::toggle_ambient_anim_group( 2, true );
	objectives::hide_for_target( "cp_quadtank_rocket_icon", self );

	driver = self GetSeatOccupant( 0 );
	if( isdefined(driver) )
	{
		self.turretRotScale = 1;
		self DisableAimAssist();
		self thread quadtank_set_team( driver.team );
		self SetBrake( 0 );
		self ASMRequestSubstate( "locomotion@movement" );
		self thread quadtank_player_fireupdate();
		self thread footstep_handler();

		self.trophy_disables = 4 - 1;
		self thread quadtank_disabletrophy();
	}
}

function quadtank_exit_vehicle()
{
	self SetGoal( self.origin );
}
// State: driving -------------------------------

// ----------------------------------------------
// State: combat
// ----------------------------------------------
function state_combat_update( params )
{
	self endon( "death" );
	self endon( "change_state" );

	if ( isalive( self ) )
	{
	}

	if ( isalive( self ) && !trophy_disabled() )
	{
		self thread quadtank_enabletrophy();
	}
	
	if ( self.allow_movement )
	{
		self thread quadtank_movementupdate();
	}
	else
	{
		self SetBrake( 1 );
	}
	
	switch ( self.variant )
	{
	case "cannon":
		vehicle_ai::Cooldown( "main_cannon", 4 ); // don't shoot cannon immediately
		self thread quadtank_weapon_think_cannon();	
		break;
	case "rocketpod":
		self thread Attack_Thread_rocket();
		break;
	}
}

function state_combat_exit( params )
{
	self notify( "end_attack_thread" );
	self notify( "end_movement_thread" );
	self ClearTurretTarget();
	self ClearLookAtEnt();
}
// State: combat --------------------------------

// ----------------------------------------------
// State: death
// ----------------------------------------------
function quadtank_death( params )
{
	self endon( "death" );	
	self endon( "nodeath_thread" );

	self set_trophy_state( false );
	self quadtank_weakpoint_display( false );
	objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
	self remove_repulsor();
	self HidePart( "tag_lidar_null", "", true );
	self vehicle::set_damage_fx_level( 0 );

	// Need to prep the death model
	StreamerModelHint( self.deathmodel, 6 );
	
	if ( !isdefined( self.custom_death_sequence ) )
	{
		playsoundatposition ("prj_quad_impact", self.origin);
		self playsound( "veh_quadtank_power_down" );
		self playsound("veh_quadtank_sparks");
		self ASMRequestSubstate( "death@stationary" );
		self waittill( "explosion_c" );
	}
	else
	{
		self [[self.custom_death_sequence]]();
	}

	if( isdefined( level.disable_thermal ) )
	{
		[[level.disable_thermal]]();
	}

	if( isdefined( self.stun_fx ) )
	{
		self.stun_fx delete();
	}
	
	BadPlace_Box( "", 0, self.origin, 90, "neutral" );
	self vehicle_death::set_death_model( self.deathmodel, self.modelswapdelay );
	self vehicle_death::death_radius_damage();

	vehicle_ai::waittill_asm_complete( "death@stationary", 5 );

	self thread vehicle_death::CleanUp();
	vehicle_death::FreeWhenSafe();
}

// ----------------------------------------------
// State: emped
// ----------------------------------------------
function quadtank_emped( params )
{
	self endon ("death");
	self endon( "change_state" );
	self endon( "emped" );
	
	if( isdefined( self.emped ) )
	{
		// already emped, just return for now.
		return;
	}
	
	self.emped = true;
	PlaySoundAtPosition( "veh_quadtankemp_down", self.origin );
	self.turretRotScale = 0.2;
	if( !isdefined( self.stun_fx) )
	{
		self.stun_fx = Spawn( "script_model", self.origin );
		self.stun_fx SetModel( "tag_origin" );
		self.stun_fx LinkTo( self, "tag_turret", (0,0,0), (0,0,0) );
		//PlayFXOnTag( level._effect[ "quadtank_stun" ], self.stun_fx, "tag_origin" );
	}
	
	time = params.notify_param[0];
	assert( isdefined( time ) );
	vehicle_ai::Cooldown( "emped_timer", time );

	while( !vehicle_ai::IsCooldownReady( "emped_timer" ) )
	{
		timeLeft = max( vehicle_ai::GetCooldownLeft( "emped_timer" ), 0.5 );
		wait timeLeft;
	}
	
	self.stun_fx delete();
	self.emped = undefined;
	self playsound ("veh_boot_quadtank");

	self vehicle_ai::evaluate_connections();
}

// ----------------------------------------------
// trophy system
// ----------------------------------------------
function trophy_disabled()
{
	if( self.trophy_down === true )
	{
		return true;
	}

	if ( trophy_destroyed() )
	{
		return true;
	}
	
	return false;
}

function trophy_destroyed()
{
	if ( self.trophy_disables >= 4 )
	{
		return true;
	}
	return false;
}

function set_trophy_state( isOn )
{
	self clientfield::set( "quadtank_trophy_state", isOn );
}

function quadtank_disabletrophy()
{
	self endon( "death" );
	self notify( "stop_disabletrophy" );
	self endon( "stop_disabletrophy" );
	self notify( "stop_enabletrophy" );
	
	set_trophy_state( false );

	if( trophy_disabled() )
		return;
	
	self.trophy_down = true;

	driver = self GetSeatOccupant( 0 );
	if( !isdefined( driver ) && self vehicle_ai::get_current_state() != "off" && self vehicle_ai::get_next_state() !== "off" )
	{
		self notify( "pain", true ); // Play a trophy system down animation using the pain state
	}
	
	Target_Set( self , (0,0,60) );
	
	self HidePart( "tag_defense_active" );
	//self HidePart( "tag_target_upper" );
	
	self.attackerAccuracy = 0.5;
	self.damage_during_trophy_down = 0;
	self.spike_hits_during_trophy_down = 0;
	self.trophy_disables += 1;
	
	self quadtank_weakpoint_display( false );
	self remove_repulsor();
	
	driver = self GetSeatOccupant( 0 );
	if( !isdefined( driver ) && self vehicle_ai::get_current_state() != "off" && self vehicle_ai::get_next_state() !== "off" )
	{
		objectives::show_for_target( "cp_quadtank_rocket_icon", self );
	}
	else
	{
		objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
	}
	
	self set_side_turrets_enabled( false );
	
	if( IsDefined( level.vehicle_defense_cb ) )
	{
    	[[level.vehicle_defense_cb]]( self, false );
	}

	if( trophy_destroyed() )
	{
		self notify("trophy_system_destroyed");
		level notify("trophy_system_destroyed",self);
		self playsound ("wpn_trophy_disable");
		PlayFXOnTag( self.settings.trophydetonationfx, self, "tag_target_lower" );
		self HidePart( "tag_lidar_null", "", true );
		return;
	}

	self notify("trophy_system_disabled");
	level notify("trophy_system_disabled",self);
	self playsound ("wpn_trophy_disable");
	
	self vehicle_ai::Cooldown( "trophy_down", self.settings.trophySystemDownTime );
	while( !self vehicle_ai::IsCooldownReady("trophy_down") || self vehicle_ai::get_current_state() === "off" )
	{
		if ( vehicle_ai::GetCooldownLeft( "trophy_down" ) < 0.5 * self.settings.trophySystemDownTime && ( self.damage_during_trophy_down >= self.settings.trophysystemdisablethreshold ||
			self.spike_hits_during_trophy_down >= 5 ) )
		{
			self vehicle_ai::ClearCooldown( "trophy_down" );
		}

		wait 1;
	}

	// player's trophy don't get back up
	driver = self GetSeatOccupant( 0 );
	if( isdefined( driver ) )
	{
		self.trophy_disables = 4;
	}

	if( !trophy_destroyed() )
	{	
		self thread quadtank_enabletrophy();
	}
}

function quadtank_enabletrophy()
{
	self endon( "death" );
	self notify( "stop_enabletrophy" );
	self endon( "stop_enabletrophy" );

	set_trophy_state( true );
	time = (isdefined(self.settings.trophywarmup)?self.settings.trophywarmup:0.1);
	wait time;
		
	driver = self GetSeatOccupant( 0 );

	self.trophy_down = false;
	self.attackerAccuracy = 1;
	self ShowPart( "tag_defense_active" );
	//self ShowPart( "tag_target_upper" );
	objectives::hide_for_target( "cp_quadtank_rocket_icon", self );

	self quadtank_projectile_watcher();
	self thread quadtank_automelee_update();

	if( !isdefined( driver ) )
	{
		self quadtank_weakpoint_display( true );
	}
	else
	{
		self quadtank_weakpoint_display( false );
	}
	
	if ( Target_IsTarget(self) )
	{
		Target_remove( self ); 
	}
	
	if( !isdefined( driver ) )
	{
		self set_side_turrets_enabled( true );
	}
	self.trophy_system_health = self.settings.trophySystemHealth;
	
	if( isDefined( level.players) && level.players.size > 0 )
	{
		num_players_trophy_health_modifier = 0.75;
		
		if( level.players.size == 2) 
		{
			num_players_trophy_health_modifier = 1;	
		}
		if( level.players.size == 3) 
		{
			num_players_trophy_health_modifier = 1.25;	
		}
		if( level.players.size >= 4) 
		{
			num_players_trophy_health_modifier = 1.5;	
		}
		self.trophy_system_health = self.trophy_system_health * num_players_trophy_health_modifier;
	}
	
	if( IsDefined( level.vehicle_defense_cb ) )
	{
    	[[level.vehicle_defense_cb]]( self, true );
	}

	self notify("trophy_system_enabled");
	level notify("trophy_system_enabled",self);
}

// trophy system --------------------------------

function quadtank_side_turrets_forward()
{	
	self SetTurretTargetRelativeAngles( (10, -90, 0), 1 );
	self SetTurretTargetRelativeAngles( (10, 90, 0), 2 );
	self.turretRotScale = 1 * self.difficulty_scale_up;
}

// rotates the turret around until he can see his enemy
function quadtank_turret_scan( scan_forever )
{
	self endon( "death" );
	self endon( "change_state" );
	
	self.turretRotScale = 0.3;

	while( scan_forever || ( !isdefined( self.enemy ) || !(self VehCanSee( self.enemy )) ) )
	{
		if( self.turretontarget && self.turret_state != 0 )
		{
			self.turret_state++;
			if( self.turret_state >= 5 )
				self.turret_state = 1;
		}
		
		switch( self.turret_state )
		{	
			// reserved for taking damage and looking responsive
			case 0:
				if( isdefined( self.enemy ) )
				{
					self SetLookAtEnt( self.enemy );
					target_vec = self.enemy.origin + ( 0, 0, 40 );
					self SetTargetOrigin( target_vec );		
					wait 1.0;
					self ClearLookAtEnt();
					self.turret_state++;
				}	// else fall through to FORWARD
				
			case 1:
				target_vec = self.origin + AnglesToForward( ( 0, self.angles[1], 0 ) ) * 1000;
				break;
				
			case 2:
				target_vec = self.origin + AnglesToForward( ( 0, self.angles[1] + 30, 0 ) ) * 1000;
				break;
				
			case 3:
				target_vec = self.origin + AnglesToForward( ( 0, self.angles[1], 0 ) ) * 1000;
				break;
				
			case 4:
				target_vec = self.origin + AnglesToForward( ( 0, self.angles[1] - 30, 0 ) ) * 1000;
				break;
		}

		target_vec = target_vec + ( 0, 0, 40 );
		self SetTargetOrigin( target_vec );		
		
		wait 0.2;
	}
}

function set_side_turrets_enabled( on )
{
	if( on )
	{
		turret::enable( 1, false );
		turret::enable( 2, false );
	}
	else
	{
		turret::disable( 1 );
		turret::disable( 2 );
	}
}

function show_weak_spots( show )	// vents on the sides that are exposed when firing the main gun
{
	if( show )
	{
		self vehicle::toggle_exhaust_fx( 1 );
	}
	else
	{
		self vehicle::toggle_exhaust_fx( 0 );
	}
}

function set_detonation_time( target )
{
	self endon( "change_state" );

	self playsound("veh_quadtank_cannon_charge");
	
	self waittill( "weapon_fired", proj );
	
	self thread railgun_sound(proj);
	
	if( isdefined( target ) && isdefined( proj ) )
	{	
		vel = proj GetVelocity();
		
		proj_speed = length( vel );
		
		dist = Distance( proj.origin, target.origin ) + RandomFloatRange( 0, 40 );
		
		time_to_enemy = dist / proj_speed;
		
		proj ResetMissileDetonationTime( time_to_enemy );
	}
}

function quadtank_weapon_think_cannon()
{
	self endon( "death" );
	self endon( "change_state" );
	
	cant_see_enemy_count = 0;
	
	self set_side_turrets_enabled( true );
	self SetOnTargetAngle( 10 );	// self.turretontarget will be true when the turret is aimed within this rage
	
	self.getreadytofire = undefined;
	
	while ( 1 )
	{
		if( self.hold_cannon === true || !vehicle_ai::IsCooldownReady( "main_cannon" ) )
		{
			if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
			{
				self SetTurretTargetEnt( self.enemy );
				self SetLookAtEnt( self.enemy );
			}

			wait 0.2;
			continue;
		}

		if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
		{
			self.turretRotScale = 1 * self.difficulty_scale_up;
			self SetTurretTargetEnt( self.enemy );
			self SetLookAtEnt( self.enemy );
			
			if( cant_see_enemy_count >= 2 )
			{
				wait 0.1;	// let the self.turretontarget have time to update so we don't shoot in a bad direction
				
				// found enemy, react by changing goal positions
				self CancelAIMove();
				self ClearVehGoalPos();
				self notify( "near_goal" );
			}
			cant_see_enemy_count = 0;
			fired = false;
			
			if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
			{
				if( DistanceSquared( self.origin, self.enemy.origin ) > 270 * 270 && self.turretontarget )
				{
					v_my_forward = Anglestoforward( self.angles );
					v_to_enemy = self.enemy.origin - self.origin;
					v_to_enemy = VectorNormalize( v_to_enemy );
					dot = VectorDot( v_to_enemy, v_my_forward );
				
					if( dot > 0.707 ) // body is facing within 45' of enemy
					{
						self ASMRequestSubstate( "fire@stationary" );
						self SetTurretTargetEnt( self.enemy );
						self thread set_detonation_time( self.enemy );
						
						if( isDefined( level.players) && level.players.size < 3)
						{
							self set_side_turrets_enabled( false );
						}
						
						self show_weak_spots( true );
						self.getreadytofire = true;
						fired = true;
						
						self CancelAIMove();
						self ClearVehGoalPos();
						self notify( "near_goal" );
						
						self.turretRotScale = 0.7;

						wait 1;
						
						level notify( "sndStopCountdown" );
						
						self vehicle_ai::waittill_asm_complete( "fire@stationary", 6 );
						
						self set_side_turrets_enabled( true );

						self.turretRotScale = 1;
					}
				}
			}
			
			self.getreadytofire = undefined;
			
			if ( isdefined( self.enemy ) )
			{
				self SetTurretTargetEnt( self.enemy );
				self SetLookAtEnt( self.enemy );
			}
			
			if( fired )
			{
				self show_weak_spots( false );
				
				vehicle_ai::Cooldown( "main_cannon", RandomFloatRange( 5, 7.5 ) );
			}
			else
			{
				wait 0.25;
			}
		}
		else
		{	
			cant_see_enemy_count++;
			
			wait 0.5;
			
			if( cant_see_enemy_count > 40 )
			{
				self quadtank_turret_scan( false );
			}
			else if( cant_see_enemy_count > 30 )
			{
				self ClearLookAtEnt();
				self ClearTargetEntity();
			}
			else
			{
				if( isdefined( self.enemy ) )
				{
					self SetTurretTargetEnt( self.enemy );
					self ClearLookAtEnt();
				}
				else
				{
					self ClearLookAtEnt();
					self quadtank_turret_scan( false );
				}
			}
		}
	}
}


function Attack_Thread_rocket()
{
	self endon( "death" );
	self endon( "end_attack_thread" );

	self vehicle::toggle_ambient_anim_group( 2, false ); // close the weapon doors

	while( true )
	{
		useJavelin = false;
		
		if ( isdefined( self.enemy ) )
		{
			self SetTurretTargetEnt( self.enemy );
			self SetLookAtEnt( self.enemy );
		}

		if( isdefined( self.enemy) && vehicle_ai::IsCooldownReady( "javelin_rocket_launcher", 0.5 )  )
		{
			if( isVehicle( self.enemy ) || Distance2DSquared( self.origin, self.enemy.origin) >= ( (800) * (800) ) )
			{
				useJavelin = !self vehseenrecently( self.enemy, 3 ) || ( RandomInt( 100 ) < 3 );
			}
		}

		if ( isdefined( self.enemy ) && vehicle_ai::IsCooldownReady( "rocket_launcher", 0.5 ) )
		{
			if( isDefined( level.players) && level.players.size < 3)
			{
				self set_side_turrets_enabled( false );
			}
			self ClearVehGoalPos();
			self notify( "near_goal" );
			self show_weak_spots( true );
			self vehicle::toggle_ambient_anim_group( 2, true );

			if( !useJavelin )
			{
				self SetVehWeapon( GetWeapon( "quadtank_main_turret_rocketpods_straight" ) );
				offset = ( 0, 0, -50 );
				if ( isPlayer( self.enemy ) )
				{
					origin = self.enemy.origin;
					eye = self.enemy GetEye();
					offset = ( 0, 0, origin[2] - eye[2] - 5 );
				}
				vehicle_ai::SetTurretTarget( self.enemy, 0, offset );
			}
			else
			{
				self playsound ("veh_quadtank_mlrs_plant_start");				
				
				self SetVehWeapon( GetWeapon( "quadtank_main_turret_rocketpods_javelin" ) );
		
				vehicle_ai::SetTurretTarget( self.enemy, 0, (0,0,300) );
			}

			wait 1;
			msg = self util::waittill_any_timeout( 2, "turret_on_target" );

			if ( isdefined( self.enemy ) && Distance2DSquared( self.origin, self.enemy.origin ) > ( (350) * (350) ) )
			{	
				fired = false;
				for( i = 0; i < 4 && isdefined( self.enemy ); i++ )
				{
					if( useJavelin )
					{
						if ( isPlayer( self.enemy ) )
						{
							self thread vehicle_ai::Javelin_LoseTargetAtRightTime( self.enemy );
						}
						self thread javeline_incoming(GetWeapon( "quadtank_main_turret_rocketpods_javelin" ));
					}
					self FireWeapon( 0, self.enemy );
										
					fired = true;
					wait 0.8;
				}

				if ( fired )
				{
					vehicle_ai::Cooldown( "rocket_launcher", randomFloatRange( 8, 10 ) );
					
					if( useJavelin )
					{
						vehicle_ai::Cooldown( "javelin_rocket_launcher", 20 );
					}
				}
			}

			self set_side_turrets_enabled( true );
			self vehicle::toggle_ambient_anim_group( 2, false );			
		}
		wait 1;
	}
}

// self == player
function trigger_player_shock_fx()
{
	if ( !isdefined( self._player_shock_fx_quadtank_melee ) )
	{
		self._player_shock_fx_quadtank_melee = 0;
	}

	self._player_shock_fx_quadtank_melee = !self._player_shock_fx_quadtank_melee;
	self clientfield::set_to_player( "player_shock_fx", self._player_shock_fx_quadtank_melee );
}

function path_update_interrupt()
{
	self endon( "death" );
	self endon( "change_state" );
	self endon( "near_goal" );
	self endon( "reached_end_node" );

	wait 1;
	
	cantSeeEnemyCount = 0;
	
	while( 1 )
	{
		if( isdefined( self.current_pathto_pos ) )
		{
			if( isdefined( self.enemy ) ) 
			{
				if( distance2dSquared( self.enemy.origin, self.current_pathto_pos ) < 250 * 250 )
				{
					self.move_now = true;
					self notify( "near_goal" );
				}
				
				if( !self VehCanSee( self.enemy ) )
				{
					if( !self vehicle_ai::CanSeeEnemyFromPosition( self.current_pathto_pos, self.enemy, 80 ) )
					{
						cantSeeEnemyCount++;
						if( cantSeeEnemyCount > 5 )
						{
							self.move_now = true;
							self notify( "near_goal" );
						}
					}
				}
			}
			
			if( distance2dSquared( self.current_pathto_pos, self.goalpos ) > self.goalradius * self.goalradius )
			{
				wait 1;
				
				self.move_now = true;
				self notify( "near_goal" );
			}
		}
		
		wait 0.3;
	}
}

function Movement_Thread_Wander()
{
	self endon( "death" );
	self endon( "change_state" );
	self notify( "end_movement_thread" );
	self endon( "end_movement_thread" );

	if( self.goalforced )
	{
		return self.goalpos;
	}
	
	minSearchRadius = 0;
	maxSearchRadius = 2000;
	halfHeight = 300;
	innerSpacing = 90;
	outerSpacing = innerSpacing * 2;
	maxGoalTimeout = 15;

	self ASMRequestSubstate( "locomotion@movement" );

	wait 0.5;
	self SetBrake( 0 );

	while ( true )
	{
		self SetSpeed( self.settings.defaultMoveSpeed, 5, 5 );

		PixBeginEvent( "_quadtank::Movement_Thread_Wander" );
		queryResult = PositionQuery_Source_Navigation( self.origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing, self, outerSpacing );
		PixEndEvent();

		// filter
		PositionQuery_Filter_DistanceToGoal( queryResult, self );
		vehicle_ai::PositionQuery_Filter_OutOfGoalAnchor( queryResult );
		vehicle_ai::PositionQuery_Filter_Random( queryResult, 200, 250 );

		foreach ( point in queryResult.data )
		{
			if( distance2dSquared( self.origin, point.origin ) < 170 * 170 )
			{
				/#    if ( !isdefined( point._scoreDebug ) )    {     point._scoreDebug = [];    }    point._scoreDebug[ "tooCloseToSelf" ] = -100;    #/    point.score += -100;;
			}
		}
		self vehicle_ai::PositionQuery_DebugScores( queryResult );

		vehicle_ai::PositionQuery_PostProcess_SortScore( queryResult );

		foundpath = false;
		goalPos = self.origin;
		count = queryResult.data.size;
		if( count > 3 )
			count = 3;
		
		for ( i = 0; i < count && !foundpath; i++ )
		{
			goalPos = queryResult.data[i].origin;
			foundpath = self SetVehGoalPos( goalPos, false, true );
		}

		if( foundpath )
		{
	
			self.current_pathto_pos = goalpos;
			self thread path_update_interrupt();
			self ASMRequestSubstate( "locomotion@movement" );
			
			msg = self util::waittill_any_timeout( maxGoalTimeout, "near_goal", "force_goal", "reached_end_node", "goal" );
			self CancelAIMove();
			self ClearVehGoalPos();
			
			if( isdefined( self.move_now ) )
			{
				self.move_now = undefined;
				
				wait 0.1;
			}
			else
			{
				wait 0.5;
			}
		}
		else
		{
			self.current_pathto_pos = undefined;
			
			goalYaw = self GetGoalYaw();
			
			wait 1;
		}
	}
}

function quadtank_movementupdate()
{
	self endon( "death" );
	self endon( "change_state" );
	
	//if( distance2dSquared( self.origin, self.goalpos ) > 20 * 20 )
	//	self SetVehGoalPos( self.goalpos, true, 2 );
	
	self ASMRequestSubstate( "locomotion@movement" );
	wait 0.5;
	
	self SetBrake( 0 );
	
	while ( self.allow_movement )
	{
		if ( self.getreadytofire !== true )
		{
			goalpos = vehicle_ai::FindNewPosition( 80 );

			if ( isdefined( goalpos ) && ( Distance2DSquared( goalpos, self.origin ) > ( (50) * (50) ) || Abs( goalpos[2] - self.origin[2] ) > self.height  ) )
			{
				self SetSpeed( self.settings.defaultMoveSpeed, 5, 5 );
				self SetVehGoalPos( goalpos, false, true );
				self.current_pathto_pos = goalpos;
				self thread path_update_interrupt();
				self ASMRequestSubstate( "locomotion@movement" );
				result = self util::waittill_any_return( "near_goal", "reached_end_node", "force_goal" );
			}
			else
			{
				self notify( "goal" );
			}

			self CancelAIMove();
			self ClearVehGoalPos();

			if ( isdefined( self.move_now ) )
			{
				self.move_now = undefined;

				wait 0.1;
			}
			else
			{
				wait 0.5;
			}
		}
		else
		{
			while ( isdefined( self.getreadytofire ) )
			{
				wait 0.2;
			}
		}

	}
}

function quadtank_player_fireupdate()
{
	self endon( "death" );
	self endon( "exit_vehicle" );
	
	weapon = self SeatGetWeapon( 1 );
	fireTime = weapon.fireTime;
	
	while( 1 )
	{
		self SetGunnerTargetVec( self GetGunnerTargetVec( 0 ), 1 );
		if( self IsGunnerFiring( 0 ) )
		{
			self FireWeapon( 2 );
		}
		wait fireTime;
	}
}

function do_melee( shouldDoDamage, enemy )
{
	if( !isAlive( enemy ) || distanceSquared( enemy.origin, self.origin ) > ( (270) * (270) ) )
	{
		return false;
	}

	if ( vehicle_ai::EntityIsArchetype( enemy, "quadtank" ) || vehicle_ai::EntityIsArchetype( enemy, "raps" ) )
	{
		return false;
	}
	
	if ( isPlayer( enemy ) && enemy laststand::player_is_in_laststand() )
	{
		return false;
	}

	self notify ( "play_meleefx" );

	if ( shouldDoDamage )
	{
		// don't damage player, but crush player vehicle
		players = GetPlayers();
		foreach( player in players )
		{
			player._takedamage_old = player.takedamage;
			player.takedamage = false;
		}

		RadiusDamage( self.origin + (0,0,40), 270, 400, 400, self );

		foreach( player in players )
		{
			player.takedamage = player._takedamage_old;
			player._takedamage_old = undefined;
		}
	}

	if ( isdefined( enemy ) && isPlayer( enemy ) )
	{
		direction = ( ( enemy.origin - self.origin )[0], ( enemy.origin - self.origin )[1], 0 );
		if ( Abs( direction[0] ) < 0.01 && Abs( direction[1] ) < 0.01 )
		{
			direction = ( RandomFloatRange( 1, 2 ), RandomFloatRange( 1, 2 ), 0 );
		}
		direction = VectorNormalize( direction );
		strength = 1000;
		enemy SetVelocity( enemy GetVelocity() + direction * strength );
		enemy trigger_player_shock_fx();
		enemy DoDamage( 15, self.origin, self );
	}

	self playsound( "veh_quadtank_emp" );

	return true;
}

function quadtank_automelee_update()
{
	self endon( "death" );

	assert( isdefined( self.team ) );

	while( !trophy_disabled() )
	{
		enemies = self GetEnemies();
		
		meleed = false;

		foreach( enemy in enemies )
		{
			if( enemy IsNoTarget() )
			{
				continue;
			}

			meleed = meleed || self do_melee( !meleed, enemy );
			if ( meleed )
			{
				break;
			}
		}

		wait 0.3;
	}
}


function quadtank_destroyturret( index )
{
	turret::disable( index );
	
	if( index == 1 )
	{
		self HidePart( "tag_gunner_barrel1" );
		self HidePart( "tag_gunner_turret1" );
	}
	else if( index == 2 )
	{
		self HidePart( "tag_gunner_barrel2" );
		self HidePart( "tag_gunner_turret2" );
	}
}

function QuadtankCallback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
{
	is_damaged_by_grenade = weapon.weapClass == "grenade";
	
	if( IsSubstr( weapon.name , "spike") )
	{
		if ( eAttacker.team !== self.team )
		{
			self.spike_hits_during_trophy_down += 1;
		}
		is_damaged_by_grenade = false;
	}
	
	if ( isdefined( eAttacker ) && ( eAttacker == self || isplayer( eAttacker ) && eAttacker.usingvehicle && eAttacker.viewlockedentity === self ) )
	{
		return 0;
	}

	if ( sMeansOfDeath === "MOD_MELEE" || sMeansOfDeath === "MOD_MELEE_WEAPON_BUTT" || sMeansOfDeath === "MOD_MELEE_ASSASSINATE" || sMeansOfDeath === "MOD_ELECTROCUTED" || sMeansOfDeath === "MOD_CRUSH" || weapon.isEmp )
	{
		return 0;
	}

	if ( vehicle_ai::EntityIsArchetype( eAttacker, "raps" ) && !trophy_disabled() )
	{
		self.trophy_system_health = 0;
		self.trophy_disables = 4 - 1;
		self thread quadtank_disabletrophy();

		if( IsPlayer( eAttacker ) && damagefeedback::doDamageFeedback( weapon, eInflictor ) )
		{
			eAttacker thread damagefeedback::update( sMeansOfDeath, eInflictor );
		}
	}

	if ( partName == "tag_target_lower" || partName == "tag_target_upper" || partName == "tag_defense_active" || partName == "tag_body_animate" )	
	{
		if( isdefined( eAttacker) && IsPlayer( eAttacker ) && eAttacker.team != self.team )
		{
			if ( !isDefined( self.trophy_system_health ) )
			{
				self.trophy_system_health = self.settings.trophySystemHealth;
			}

			//debug display information regarding damage done to weak spot
//			damage_amount = STR( iDamage );
//			trophy_health = STR( self.trophy_system_health );
//			damage_string = "Damage Done = " + damage_amount + " || Remaining Health = " + trophy_health;
//			/#
//        		PrintTopRightln( damage_string );
// 			#/    

			if( !trophy_disabled() )
			{
				self.trophy_system_health -= iDamage;
				quadtank_weakpoint_trigger();

				if( self.trophy_system_health <= 0 )
				{
					self thread quadtank_disabletrophy();
				}
			
				if( IsPlayer( eAttacker ) && damagefeedback::doDamageFeedback( weapon, eInflictor ) )
				{
					if ( iDamage > 0 )
						eAttacker thread damagefeedback::update( sMeansOfDeath, eInflictor );
				}
			}
		}
	}
	else if ( is_damaged_by_grenade /*|| sMeansOfDeath == "MOD_EXPLOSIVE" */ )
	{
		iDamage = Int( iDamage * 3 );
	}
	
	// when taking damage let the turret know if it is scanning to look at our enemy
	// hopefully code will update our enemy
	self.turret_state = 0;
	self.turretRotScale = 1.0 * self.difficulty_scale_up;
	self.turret_on_target = true;
		
	if( sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_PISTOL_BULLET" )	// Quadtank is immune to bullets but that filtering happens later
	{
		return iDamage;
	}
	
	// cap the damage actors can do
	if( IsActor( eAttacker ) && iDamage > 250 )
	{
		iDamage = 250;
	}

	num_players = GetPlayers().size;
	maxDamage = self.healthdefault * ( 0.20 - 0.025 * num_players );
	if ( sMeansOfDeath !== "MOD_UNKNOWN" && iDamage > maxDamage )
	{
		iDamage = maxDamage;
	}
	
	damageLevelChanged = vehicle::update_damage_fx_level( self.health, iDamage, self.healthdefault );
	
	driver = self GetSeatOccupant( 0 );

	if ( sMeansOfDeath != "MOD_UNKNOWN" && !vehicle_ai::EntityIsArchetype( eAttacker, "quadtank" ) )
	{	
		if( self.damage_during_trophy_down + iDamage > self.settings.trophysystemdisablethreshold && self.trophy_disables < 4 && !isdefined(driver) )
		{
			iDamage = max( 1, self.settings.trophysystemdisablethreshold - self.damage_during_trophy_down );
		}
		
		self.damage_during_trophy_down += iDamage;
	}
	
	if( damageLevelChanged && sMeansOfDeath != "MOD_MELEE_ASSASSINATE" && ( !isdefined(eAttacker) || eAttacker.team !== self.team ) && !isdefined( driver ) ) // no pain for player driving version
	{
		//self notify( "pain" ); // too many pains. no pain for damage state change
		playsoundatposition ("prj_quad_impact", self.origin);
	}

	iDamage = vehicle_ai::shared_callback_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
	
	return iDamage;
}

function quadtank_set_team( team )
{
	self.team = team;
	
	if( !self vehicle_ai::is_instate( "off" ) )
	{
		self vehicle_ai::blink_lights_for_time( 0.5 );
	}
}

function remove_repulsor()
{
	if( isdefined( self.missile_repulsor ) ) 
	{
		missile_deleteattractor( self.missile_repulsor );
		self.missile_repulsor = undefined;
	}
	self notify( "end_repulsor_fx" );
}

function repulsor_fx()
{
	self notify( "end_repulsor_fx" );
	self endon( "end_repulsor_fx" );
	self endon( "death" );
	self endon( "change_state" );
	
	while( 1 )
	{	
		self util::waittill_any( "projectile_applyattractor", "play_meleefx" );
		if ( vehicle_ai::IsCooldownReady("repulsorfx_interval") )
		{
			PlayFxOnTag( self.settings.trophyrepulsefx, self, "tag_body" );

			self vehicle::impact_fx( self.settings.trophyrepulsefx_ground );
			
			vehicle_ai::Cooldown( "repulsorfx_interval", 0.5 );

			self PlaySound( "wpn_quadtank_shield_impact" );

			quadtank_weakpoint_trigger();
		}
	}
}
		
function quadtank_projectile_watcher()
{
	if( !isdefined( self.missile_repulsor ) ) 
	{
		self.missile_repulsor = missile_createrepulsorent( self, 40000, self.settings.trophysystemrange, true );
	}
	self thread repulsor_fx();
}

function turn_off_laser_after( time )
{
	self notify( "turn_off_laser_thread" );
	self endon( "turn_off_laser_thread" );
	self endon( "death" );
	
	wait time;
	
	self LaserOff();
}



//self = turret/vehicle
function side_turret_is_target_in_view_score( v_target, n_index )
{
	s_turret = turret::_get_turret_data( n_index );
	
	v_pivot_pos = self GetTagOrigin( s_turret.str_tag_pivot );
	v_angles_to_target = VectorToAngles( v_target - v_pivot_pos );
	
	n_rest_angle_pitch = s_turret.n_rest_angle_pitch + self.angles[0];
	n_rest_angle_yaw = s_turret.n_rest_angle_yaw + self.angles[1];
	
	n_ang_pitch = AngleClamp180( v_angles_to_target[0] - n_rest_angle_pitch );
	n_ang_yaw = AngleClamp180( v_angles_to_target[1] - n_rest_angle_yaw );
	
	b_out_of_range = false;

	if ( n_ang_pitch > 0 )
	{
		if ( n_ang_pitch > s_turret.bottomarc )
		{
			b_out_of_range =  true;
		}
	}
	else
	{
		if ( Abs( n_ang_pitch ) > s_turret.toparc )
		{
			b_out_of_range =  true;
		}
	}
	
	if ( n_ang_yaw > 0 )
	{
		if ( n_ang_yaw > s_turret.leftarc )
		{
			b_out_of_range =  true;
		}
	}
	else
	{
		if ( Abs( n_ang_yaw ) > s_turret.rightarc )
		{
			b_out_of_range =  true;
		}
	}

	if( b_out_of_range )
	{
		return 0.0;
	}
	
	return ( Abs( n_ang_yaw ) / 90 * 800 );
}

function _get_best_target_quadtank_side_turret( a_potential_targets, n_index )
{
	takeEasyOnOneTarget = MapFloat( 0, 4, 800, 0, level.gameskill );

	if ( n_index === 1 )
	{
		other_turret_target = turret::get_target( 2 );
	}
	else if ( n_index === 2 )
	{
		other_turret_target = turret::get_target( 1 );
	}

	e_best_target = undefined;
	f_best_score = 100000;		// lower is better
	
	s_turret = turret::_get_turret_data( n_index );

	foreach( e_target in a_potential_targets )
	{
		f_score = Distance( self.origin, e_target.origin );
		
		b_current_target = turret::is_target( e_target, n_index );
		
		if( b_current_target )
		{
			f_score -= 100;
		}
		
		if( e_target === self.enemy )
		{
			f_score += 300;
		}

		if ( e_target === other_turret_target )
		{
			f_score += ( 100 + takeEasyOnOneTarget );
		}
		
		if( IsSentient( e_target ) && e_target AttackedRecently( self, 2 ) )
		{
			f_score -= 200;
		}
		
		if ( isAlive( self.lockon_owner ) && e_target === self.lockon_owner )
		{
			f_score -= 1000;
		}

		v_offset = turret::_get_default_target_offset( e_target, n_index );
			
		view_score = side_turret_is_target_in_view_score( e_target.origin + v_offset, n_index );
		
		if( view_score != 0.0 )
		{
			f_score += view_score;
			
			b_trace_passed = turret::trace_test( e_target, v_offset, n_index );
						
			if ( b_current_target && !b_trace_passed && !isdefined( s_turret.n_time_lose_sight ) )
			{
				s_turret.n_time_lose_sight = GetTime();
			}
			
			if( b_trace_passed )
			{
				f_score -= 500;
			}
		}
		else if ( b_current_target )
		{	
			s_turret.b_target_out_of_range = true;
			f_score += 5000;
		}
	
		if( f_score < f_best_score )
		{
			f_best_score = f_score;
			e_best_target = e_target;
		}
	}
	
	return e_best_target;
}

function quadtank_weakpoint_trigger()
{
	if( ( isdefined( self.displayweakpoint ) && self.displayweakpoint ) )
	{
		self globallogic_ui::triggerWeakpointDamage( &"tag_target_lower" );
	}
}

function quadtank_weakpoint_display( state )
{
	if( self.displayweakpoint !== state )
	{
		self.displayweakpoint = state;
		
		if( !self.displayweakpoint && self.weakpointobjective === 1 )
		{
			self.weakpointobjective = 0;
			self globallogic_ui::destroyWeakpointWidget( &"tag_target_lower" );
		}
		
		player = level.players[0];
		if( self.displayweakpoint && self.combatactive && self.weakpointobjective !== 1 && ( !isdefined( player ) || player.team !== self.team ) )
		{
			self.weakpointobjective = 1;
			self globallogic_ui::createWeakpointWidget( &"tag_target_lower" );
		}
	}
}

function footstep_handler()
{
	self endon( "death" );
	self endon( "exit_vehicle" );
	
	while( 1 )
	{
		note = self util::waittill_any_return( "footstep_front_left", "footstep_front_right", "footstep_rear_left", "footstep_rear_right" );
		
		switch( note )
		{
			case "footstep_front_left":
			{
				bone = "tag_foot_fx_left_front";
				break;
			}
			case "footstep_front_right":
			{
				bone = "tag_foot_fx_right_front";
				break;
			}
			case "footstep_rear_left":
			{
				bone = "tag_foot_fx_left_back";
				break;
			}
			case "footstep_rear_right":
			{
				bone = "tag_foot_fx_right_back";
				break;
			}
		}
		
		position = self GetTagOrigin( bone ) + (0,0,15);
		
		self RadiusDamage( position, 60, 50, 50, self, "MOD_CRUSH" );
	}
}

function javeline_incoming(projectile)
{
	self endon( "entityshutdown" );
	self endon ("death");

	self waittill( "weapon_fired", projectile );

	distance = 1400;
	alias = "prj_quadtank_javelin_incoming";

	wait(5);

	if(!isdefined( projectile ) )
		return;

	while(isdefined(projectile) && isdefined( projectile.origin ))
	{
		if ( isdefined( self.enemy ) && isdefined( self.enemy.origin ))
		{
			projectileDistance = DistanceSquared( projectile.origin, self.enemy.origin);

			if( projectileDistance <= distance * distance )
			{
				projectile playsound (alias);
				return;
			}
		}

		wait (.2);	
	}
}

function railgun_sound(projectile)
{
	self endon( "entityshutdown" );
	self endon ("death");
	
		self waittill( "weapon_fired", projectile );
		
			distance = 900;
			alais = "wpn_quadtank_railgun_fire_rocket_flux";
			players = level.players;
							
			while(isdefined(projectile) && isdefined( projectile.origin ))
			{
				if ( isdefined( players[0] ) && isdefined( players[0].origin ))
				{
					projectileDistance = DistanceSquared( projectile.origin, players[0].origin);
					
					if( projectileDistance <= distance * distance )
					{
						projectile playsound (alais);
						return;
					}
				}
				
				wait (.2);	
			}	
	
}


