#using scripts\codescripts\struct;

#using scripts\shared\abilities\_ability_player;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\util_shared;
#using scripts\shared\weapons\_weaponobjects;
#using scripts\shared\weapons\_tacticalinsertion;
#using scripts\shared\vehicles\_raps;
#using scripts\shared\table_shared;
#using scripts\shared\scoreevents_shared;

    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          

#namespace killstreaks;

function is_killstreak_weapon( weapon )
{
	if ( weapon == level.weaponNone || weapon.notKillstreak )
	{
		return false;
	}

	if ( weapon.isSpecificUse || is_weapon_associated_with_killstreak( weapon ) )
	{
		return true;
	}

	return false;
}

function is_weapon_associated_with_killstreak( weapon )
{
	return ( isdefined( level.killstreakWeapons ) && isdefined( level.killstreakWeapons[ weapon ] ) );
}

function switch_to_last_non_killstreak_weapon( immediate, awayfromBall )
{
	//Check if we were going into last stand
	ball = GetWeapon( "ball" );
	if( isdefined( ball ) && self HasWeapon( ball ) && !( isdefined( awayfromBall ) && awayfromBall ) )
	{
		self switchToWeaponImmediate( ball );
		self DisableWeaponCycling();
		self DisableOffhandWeapons();	
	} 
	else if ( ( isdefined( self.lastStand ) && self.lastStand ) )
	{
		if ( isdefined( self.laststandpistol ) && self hasWeapon( self.laststandpistol ) )
		{
			self switchToWeapon( self.laststandpistol );
		}
	}
	else if( isdefined( self.lastNonKillstreakWeapon ) && self hasWeapon(self.lastNonKillstreakWeapon) )
	{
		if ( self.lastNonKillstreakWeapon.isHeroWeapon )
		{
			if ( self.lastNonKillstreakWeapon.gadget_heroversion_2_0 )
			{
				if ( self.lastNonKillstreakWeapon.isGadget && self GetAmmoCount( self.lastNonKillstreakWeapon ) > 0 )
				{
					slot = self GadgetGetSlot( self.lastNonKillstreakWeapon );
					if ( self ability_player::gadget_is_in_use( slot ) )
					{
						return self switchToWeapon( self.lastNonKillstreakWeapon );						
					}
					else
						return true;
				}				
			}
			else
			{
				if ( self GetAmmoCount( self.lastNonKillstreakWeapon ) > 0 )
				{
					return self switchToWeapon( self.lastNonKillstreakWeapon );
				}				
			}
			
			// cycle
			if( ( isdefined( awayfromBall ) && awayfromBall ) && isdefined( self.lastDroppableWeapon ) && self hasWeapon( self.lastDroppableWeapon ) )
				self switchToWeapon( self.lastDroppableWeapon );
			else
				self switchToWeapon();
			
			return true;
		}
		else
		{
			if( ( isdefined( immediate ) && immediate ) )
				self switchToWeaponImmediate( self.lastNonKillstreakWeapon );
			else
				self switchToWeapon( self.lastNonKillstreakWeapon );
		}
	}
	else if( isdefined( self.lastDroppableWeapon ) && self hasWeapon(self.lastDroppableWeapon) )
	{
		self switchToWeapon( self.lastDroppableWeapon );
	}
	else
	{
		return false;
	}
		
	return true;
}

function get_killstreak_weapon( killstreak )
{
	if( !isdefined( killstreak ) )
	{
		return level.weaponNone;
	}

	Assert( isdefined(level.killstreaks[killstreak]) );
	
	return level.killstreaks[killstreak].weapon;
}

function isHeldInventoryKillstreakWeapon( killstreakWeapon )
{
	switch( killstreakWeapon.name )
	{
	case "inventory_minigun":
	case "inventory_m32":
		return true;
	}

	return false;
}

function WaitForTimecheck( duration, callback, endCondition1, endCondition2, endCondition3 )
{
	self endon( "hacked" );
	
	if( isdefined( endCondition1 ) )
		self endon( endCondition1 );
	if( isdefined( endCondition2 ) )
		self endon( endCondition2 );
	if( isdefined( endCondition3 ) )
		self endon( endCondition3 );
	
	hostmigration::MigrationAwareWait( duration );
	
	self notify( "time_check" );
	self [[ callback ]]();
}

function EMP_IsEMPd()
{
	if( isdefined( level.enemyEMPActiveFunc ) )
	{
		return self [[ level.enemyEMPActiveFunc ]]();
	}
	
	return false;
}

function WaitTillEMP( onEmpdCallback, arg )
{
	self endon ( "death" );
	self endon ( "delete" );
	
	self waittill( "emp_deployed", attacker );
	
	if( isdefined( onEmpdCallback ) )
	{
		[[ onEmpdCallback ]]( attacker, arg );
	}
}

function HasUav( team_or_entnum )
{
	return level.activeUAVs[ team_or_entnum ] > 0;
}

function HasSatellite( team_or_entnum )
{
	return level.activeSatellites[ team_or_entnum ] > 0;
}

function DestroyOtherTeamsEquipment( attacker, weapon )
{
	foreach( team in level.teams )
	{
		if( team == attacker.team )
		{
			continue;
		}
			
		DestroyEquipment( attacker, team, weapon );
		DestroyTacticalInsertions( attacker, team );
	}
	
	DestroyEquipment( attacker, "free", weapon );
	DestroyTacticalInsertions( attacker, "free" );
}

function DestroyEquipment( attacker, team, weapon )
{
	for( i = 0; i < level.missileEntities.size; i++ )
	{
		item = level.missileEntities[i];

		if ( !isdefined( item.weapon ) )
		{
			continue;
		}

		if ( !isdefined( item.owner ) )
		{
			continue;
		}

		if ( isdefined( team ) && item.owner.team != team ) 
		{
			continue;
		}
		else if ( item.owner == attacker )
		{
			continue;
		}

		if ( !item.weapon.isEquipment && !( isdefined( item.destroyedByEmp ) && item.destroyedByEmp ) )
		{
			continue;
		}

		watcher = item.owner weaponobjects::getWatcherForWeapon( item.weapon );

		if ( !isdefined( watcher ) )
		{
			continue;
		}

		watcher thread weaponobjects::waitAndDetonate( item, 0.0, attacker, weapon );
	}
}

function DestroyTacticalInsertions( attacker, victimTeam )
{
	for ( i = 0; i < level.players.size; i++ )
	{
		player = level.players[ i ];

		if ( !isdefined( player.tacticalInsertion ))
		{
			continue;
		}

		if ( level.teamBased && player.team != victimTeam )
		{
			continue;
		}

		if ( attacker == player )
		{
			continue;
		}

		player.tacticalInsertion thread tacticalinsertion::fizzle();
	}
}

function DestroyOtherTeamsActiveVehicles( attacker, weapon )
{
	foreach( team in level.teams )
	{
		if( team == attacker.team )
		{
			continue;
		}
			
		DestroyActiveVehicles( attacker, team, weapon );
	}
	
	//DestroyActiveVehicles( attacker, undefined, weapon );
	
	DestroyNeutralGameplayVehicles( attacker, weapon );
}

function DestroyNeutralGameplayVehicles( attacker, weapon )
{
	script_vehicles = GetEntArray( "script_vehicle", "classname" );
	foreach( vehicle in script_vehicles )
	{
		if( IsVehicle( vehicle ) && ( !isdefined( vehicle.team ) || vehicle.team == "neutral" ) )
		{
			if( isdefined( vehicle.DetonateViaEMP ) && ( isdefined( weapon.isEmpKillstreak ) && weapon.isEmpKillstreak ) )
			{
				vehicle [[vehicle.DetonateViaEMP]]( attacker, weapon );
			}
			
			if( isdefined( vehicle.archetype ) )
			{
				if ( vehicle.archetype == "siegebot" )
				{
					vehicle DoDamage( vehicle.health + 1, vehicle.origin, attacker, attacker, "", "MOD_EXPLOSIVE", 0, weapon );
				}
			}
		}
	}	
}

function DestroyActiveVehicles( attacker, team, weapon )
{
	targets = Target_GetArray();
	DestroyEntities( targets, attacker, team, weapon );
	
	ai_tanks = GetEntArray( "talon", "targetname" );
	DestroyEntities( ai_tanks, attacker, team, weapon );

	remoteMissiles = GetEntArray( "remote_missile", "targetname" );
	DestroyEntities( remoteMissiles, attacker, team, weapon );
	
	remoteDrone = GetEntArray( "remote_drone", "targetname" );
	DestroyEntities( remoteDrone, attacker, team, weapon );
	
	script_vehicles = GetEntArray( "script_vehicle", "classname" );
	foreach( vehicle in script_vehicles )
	{
		if( isdefined( team ) && ( vehicle.team == team ) && IsVehicle( vehicle ) )
		{
			if( isdefined( vehicle.DetonateViaEMP ) && ( isdefined( weapon.isEmpKillstreak ) && weapon.isEmpKillstreak ) )
			{
				vehicle [[vehicle.DetonateViaEMP]]( attacker, weapon );
			}
			
			if( isdefined( vehicle.archetype ) )
			{
				if( vehicle.archetype == "raps" )
				{
					vehicle raps::detonate( attacker );	
				}
				else if( vehicle.archetype == "turret" || vehicle.archetype == "rcbomb" || vehicle.archetype == "wasp" || vehicle.archetype == "siegebot" )
				{
					vehicle DoDamage( vehicle.health + 1, vehicle.origin, attacker, attacker, "", "MOD_EXPLOSIVE", 0, weapon );
				}
			}
		}
	}
	
	planeMortars = GetEntArray( "plane_mortar", "targetname" );
	foreach( planeMortar in planeMortars )
	{
		if ( isdefined( team ) && isdefined( planeMortar.team ) )
		{
			if ( planeMortar.team != team )
			{
				continue;
			}
		}
		else if ( planeMortar.owner == attacker )
		{
			continue;
		}

		planeMortar notify( "emp_deployed", attacker );
	}

	droneStrikes = GetEntArray( "drone_strike", "targetname" );
	foreach( droneStrike in droneStrikes )
	{
		if ( isdefined( team ) && isdefined( droneStrike.team ) )
		{
			if ( droneStrike.team != team )
			{
				continue;
			}
		}
		else if ( droneStrike.owner == attacker )
		{
			continue;
		}

		droneStrike notify( "emp_deployed", attacker );
	}

	counteruavs = GetEntArray( "counteruav", "targetname" );	
	foreach( counteruav in counteruavs )
	{
		if ( isdefined( team ) && isdefined( counteruav.team ) )
		{
			if ( counteruav.team != team )
			{
				continue;
			}
		}
		else if ( counteruav.owner == attacker )
		{
			continue;
		}

		counteruav notify( "emp_deployed", attacker );
	}
	
	satellites = GetEntArray( "satellite", "targetname" );
	foreach( satellite in satellites )
	{
		if ( isdefined( team ) && isdefined( satellite.team ) )
		{
			if ( satellite.team != team )
			{
				continue;
			}
		}
		else if ( satellite.owner == attacker )
		{
			continue;
		}

		satellite notify( "emp_deployed", attacker );
	}

	robots = GetAIArchetypeArray( "robot" );
	foreach( robot in robots )
	{		
		if( robot.allowdeath !== false &&
		    robot.magic_bullet_shield !== true &&
		    isdefined( team ) && 
		    robot.team == team )
		{
			if ( isdefined( attacker ) && ( !isdefined( robot.owner ) || robot.owner util::IsEnemyPlayer( attacker ) ) )
			{
				scoreevents::processScoreEvent( "destroyed_combat_robot", attacker, robot.owner, weapon );
				LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_COMBAT_ROBOT", attacker.entnum );		
			}			
			robot Kill();
		}
	}
	
	if ( isdefined ( level.missile_swarm_owner ) ) 
	{
		if ( level.missile_swarm_owner util::IsEnemyPlayer( attacker ) )
		{
			level.missile_swarm_owner notify( "emp_destroyed_missile_swarm", attacker );
		}
	}
}

function DestroyEntities( entities, attacker, team, weapon )
{
	meansOfDeath = "MOD_EXPLOSIVE";

	damage = 5000;
	direction_vec = ( 0, 0, 0 );
	point = ( 0, 0, 0 );
	modelName = "";
	tagName = "";
	partName = "";

	foreach( entity in entities )
	{
		if ( isdefined( team ) && isdefined( entity.team ) )
		{
			if ( entity.team != team )
			{
				continue;
			}
		}
		else if ( isdefined( entity.owner ) && ( entity.owner == attacker ) )
		{
			continue;
		}

		entity notify( "damage", damage, attacker, direction_vec, point, meansOfDeath, tagName, modelName, partName, weapon );
	}
}
