#using scripts\codescripts\struct;

#using scripts\mp\_util;
#using scripts\mp\gametypes\_hostmigration;
#using scripts\mp\killstreaks\_airsupport;
#using scripts\mp\killstreaks\_emp;
#using scripts\mp\killstreaks\_killstreakrules;
#using scripts\mp\killstreaks\_killstreak_bundles;
#using scripts\mp\killstreaks\_killstreak_hacking;
#using scripts\mp\killstreaks\_killstreaks;
#using scripts\mp\killstreaks\_placeables;
#using scripts\mp\teams\_teams;
#using scripts\mp\teams\_teams;

#using scripts\shared\callbacks_shared;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\popups_shared;
#using scripts\shared\turret_shared;
#using scripts\shared\util_shared;
#using scripts\shared\vehicle_shared;
#using scripts\shared\weapons\_weaponobjects;
#using scripts\shared\scoreevents_shared;

  
                                                                                                   	  	                                                                    	                     	                 	                                                                         	                       	                                                      	                                                      	                                                       	                                                                                                  	                                                                                                                 	                                                   	                	                                          	                                      	       	  	             	                                                     	                                                                             	                         	                                                                	                                                             	                                                             	                                                                                      	                                                         	                                                         	                                                               	                                                               	                                                   	                                                                	                                                     	                                                	                                                	                                                        	                                                                                                  	                                                                             	                                            	                                                                                    	                                          	                     	                                              	                                        	                 	   
    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   

#using_animtree ( "mp_emp_power_core" );

#precache( "string", "KILLSTREAK_EARNED_EMP" );
#precache( "string", "KILLSTREAK_EMP_NOT_AVAILABLE" );
#precache( "string", "KILLSTREAK_EMP_INBOUND" );
#precache( "string", "KILLSTREAK_EMP_HACKED" );
#precache( "string", "KILLSTREAK_DESTROYED_EMP" );
#precache( "triggerstring", "KILLSTREAK_EMP_PLACE_TURRET_HINT" );
#precache( "triggerstring", "KILLSTREAK_EMP_INVALID_TURRET_LOCATION" );
#precache( "triggerstring", "KILLSTREAK_EMP_TURRET_PICKUP" );
#precache( "string", "mpl_killstreak_emp_activate" );

//#precache( "fx", "killstreaks/fx_emp_core" );
#precache( "fx", "killstreaks/fx_emp_exp_death" );




#namespace emp;

function init()
{
	bundle = struct::get_script_bundle( "killstreak", "killstreak_emp" );
	level.empKillstreakBundle = bundle;
	
	level.ActivePlayerEMPs = [];
	level.ActiveEMPs = [];
	foreach( team in level.teams )
	{
		level.ActiveEMPs[ team ] = false;
	}

	level.enemyEMPActiveFunc = &EnemyEMPActive;
	
	level thread EMPTracker();
	
	killstreaks::register( "emp", "emp", "killstreak_emp", "emp_used", &ActivateEMP );
	killstreaks::register_strings( "emp", &"KILLSTREAK_EARNED_EMP", &"KILLSTREAK_EMP_NOT_AVAILABLE", &"KILLSTREAK_EMP_INBOUND", undefined, &"KILLSTREAK_EMP_HACKED", false );
	killstreaks::register_dialog( "emp", "mpl_killstreak_emp_activate", "empDialogBundle", undefined, "friendlyEmp", "enemyEmp", "enemyEmpMultiple", "friendlyEmpHacked", "enemyEmpHacked", "requestEmp", "threatEmp" );

	clientfield::register( "scriptmover", "emp_turret_init", 1, 1, "int" ); // re-export model in close position to save this clientfield
	clientfield::register( "vehicle", "emp_turret_deploy", 1, 1, "int" );
		
	spinAnim = %o_turret_emp_core_spin;
	deployAnim = %o_turret_emp_core_deploy;
		
	callback::on_spawned( &OnPlayerSpawned );
	callback::on_connect( &OnPlayerConnect );
	vehicle::add_main_callback( "emp_turret", &InitTurretVehicle );
}

function InitTurretVehicle()
{
	turretVehicle = self;
	
	turretVehicle killstreaks::setup_health( "emp" );
	turretVehicle.damageTaken = 0;
	turretVehicle.health = turretVehicle.maxhealth;
	
	turretVehicle clientfield::set( "enemyvehicle", 1 );
	turretVehicle.soundmod = "drone_land"; // TODO: update this to the correct value

	turretVehicle.overrideVehicleDamage = &OnTurretDamage;
	turretVehicle.overrideVehicleDeath = &OnTurretDeath;

	Target_Set( turretVehicle, ( 0, 0, 36 ) );
}

function OnPlayerSpawned()
{
	self endon( "disconnect" );
	
	self UpdateEMP();
}

function OnPlayerConnect()
{
	self.entNum = self getEntityNumber();
	level.ActivePlayerEMPs[ self.entNum ] = false;
}

function ActivateEMP()
{
	player = self;
	
	killstreakId = player killstreakrules::killstreakStart( "emp", player.team, false, false );
	if( killstreakId == (-1) )
	{
		return false;
	}
	
	bundle = level.empKillstreakBundle;

	empBase = player placeables::SpawnPlaceable( "emp", killstreakId, &OnPlaceEMP, &OnCancelPlacement, undefined, &OnShutdown, undefined, undefined,
	                                           	 "wpn_t7_turret_emp_core", "wpn_t7_turret_emp_core_yellow", "wpn_t7_turret_emp_core_red", true, "", undefined, undefined, 0,
												 bundle.ksPlaceableHint, bundle.ksPlaceableInvalidLocationHint );

	empBase thread util::ghost_wait_show_to_player( player );
	empBase.otherModel thread util::ghost_wait_show_to_others( player );
	empBase clientfield::set( "emp_turret_init", 1 );
	empBase.otherModel clientfield::set( "emp_turret_init", 1 );

	event = empBase util::waittill_any_return( "placed", "cancelled", "death", "disconnect" );
	if( event != "placed" )
	{
		return false;
	}
	
	return true;
}

function OnPlaceEMP( emp )
{
	player = self;
	assert( IsPlayer( player ) );
	assert( !isdefined( emp.vehicle ) );

	emp.vehicle = SpawnVehicle( "emp_turret", emp.origin, emp.angles );
	emp.vehicle thread util::ghost_wait_show( 0.05 );

	emp.vehicle.killstreakType = emp.killstreakType; // need to do this for enable_hacking

	emp.vehicle.owner = player;
	emp.vehicle SetOwner( player );
	emp.vehicle.ownerEntNum = player.entNum;
	emp.vehicle.parentStruct = emp;
	
	player.EMPTime = GetTime();
	player killstreaks::play_killstreak_start_dialog( "emp", player.pers["team"], emp.killstreakId );
	player AddWeaponStat( GetWeapon( "emp" ), "used", 1 );
	level thread popups::DisplayKillstreakTeamMessageToAll( "emp", player );
	emp.vehicle killstreaks::configure_team( "emp", emp.killstreakId, player );
	emp.vehicle killstreak_hacking::enable_hacking( "emp", &HackedCallbackPre, &HackedCallbackPost );
	emp thread killstreaks::WaitForTimeout( "emp", ( 60 * 1000 ), &on_timeout, "death" );
	if ( IsSentient( emp.vehicle ) == false )
		emp.vehicle MakeSentient(); // so other sentients will consider this as a potential enemy

	emp.vehicle vehicle::disconnect_paths( 0, false );

	// perform deploy on separate thread because of the wait delays
	// always complete OnPlace() in same frame for killstreak accounting; otherwise exploits can happen
	player thread DeployEmpTurret( emp );
}

function DeployEmpTurret( emp )
{
	player = self;
	
	player endon( "disconnect" );
	player endon( "joined_team" );
	player endon( "joined_spectators" );

	emp endon( "death" );

	// deploy emp
	emp.vehicle UseAnimTree( #animtree );
	emp.vehicle SetAnim( %o_turret_emp_core_deploy, 1.0 );
	length = GetAnimLength( %o_turret_emp_core_deploy );
	emp.vehicle clientfield::set( "emp_turret_deploy", 1 );
	wait length * 0.75;

	// fire emp pulse
	emp.vehicle thread PlayEMPFx();
	emp.vehicle playsound( "mpl_emp_turret_activate" );
	emp.vehicle SetAnim( %o_turret_emp_core_spin, 1.0 );

	// Jam Enemies and destroy other scorestreaks!
	player thread EMP_JamEnemies( emp, false );
	
	wait length * 0.25;
	emp.vehicle ClearAnim( %o_turret_emp_core_deploy, 0 ); // stop deploy anim
}

function HackedCallbackPre( hacker )
{
	emp_vehicle = self;
	emp_vehicle clientfield::set( "enemyvehicle", 2 );
	emp_vehicle.parentStruct killstreaks::configure_team( "emp", emp_vehicle.parentStruct.killstreakId, hacker, undefined, undefined, undefined, true );
}

function HackedCallbackPost( hacker )
{
	emp_vehicle = self;
	hacker thread EMP_JamEnemies( emp_vehicle.parentStruct, true );
}

function DoneEMPFx( fxTagOrigin )
{
	PlayFx( "killstreaks/fx_emp_exp_death", fxTagOrigin );
	playsoundatposition( "mpl_emp_turret_deactivate", fxTagOrigin );
}

function PlayEMPFx()
{
	emp_vehicle = self;
	emp_vehicle playloopsound( "mpl_emp_turret_loop_close" );
		
	{wait(.05);}; // workaround for a bug where the fx would not play on subsequent deployment of power cores
}

function on_timeout()
{
	emp = self;
	
	if ( isdefined( emp.vehicle ) )
	{
		fxTagOrigin = emp.vehicle GetTagorigin( "tag_fx" );
		DoneEMPFx( fxTagOrigin );
	}
	ShutdownEMP( emp );
}

function OnCancelPlacement( emp )
{
	StopEMP( emp.team, emp.ownerEntNum, emp.originalTeam, emp.killstreakId );
}

function OnTurretDamage( eInflictor, attacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
{
	empDamage = 0; // emp power core is not affected by emp damage

	iDamage = self killstreaks::OnDamagePerWeapon( "emp", attacker, iDamage, iDFlags, sMeansOfDeath, weapon, self.maxhealth, undefined, self.maxhealth*0.4, undefined, empDamage, undefined, true, 1.0 );
	self.damageTaken += iDamage;
	
	// turret death
	if ( self.damageTaken > self.maxHealth && !isdefined( self.will_die ) )
	{
		self.will_die = true;
		self thread OnDeathAfterFrameEnd( attacker, weapon );
	}

	return iDamage;
}

function OnTurretDeath( inflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime )
{
	// currently, OnTurretDeath is not getting called, so we call OnDeath directly from OnTurretDamage
	self OnDeath( attacker, weapon );
}

function OnDeathAfterFrameEnd( attacker, weapon )
{
	waittillframeend;

	if ( isdefined( self ) )
	{
		self OnDeath( attacker, weapon );
	}
}

function OnDeath( attacker, weapon )
{
	emp_vehicle = self;
	
	fxTagOrigin = self GetTagorigin( "tag_fx" );
	DoneEMPFx( fxTagOrigin );
	if ( isdefined( attacker ) && IsPlayer( attacker ) && ( !isdefined( emp_vehicle.owner ) ||  emp_vehicle.owner util::IsEnemyPlayer( attacker ) ) )
	{
		attacker challenges::destroyScoreStreak( weapon, false, true, false );
		attacker challenges::destroyNonAirScoreStreak_PostStatsLock( weapon );
		attacker AddPlayerStat( "destroy_turret", 1 );
		attacker AddWeaponStat( weapon, "destroy_turret", 1 );
		scoreevents::processScoreEvent( "destroyed_emp", attacker, emp_vehicle.owner, weapon );
		LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_EMP", attacker.entnum );
	}

	if ( isdefined( attacker ) && isdefined( emp_vehicle.owner ) && ( attacker != emp_vehicle.owner ) )
		emp_vehicle killstreaks::play_destroyed_dialog_on_owner( "emp", emp_vehicle.parentStruct.killstreakId );
	
	ShutdownEMP( emp_vehicle.parentStruct );
}

function OnShutdown( emp )
{
	ShutdownEMP( emp );
}

function ShutdownEMP( emp )
{
	if (!isdefined( emp ) )
		return;
	
	if ( isdefined( emp.already_shutdown ) )
		return;
	
	emp.already_shutdown = true;

	if ( isdefined( emp.vehicle ) )
		emp.vehicle clientfield::set( "emp_turret_deploy", 0 );

	StopEMP( emp.team, emp.OwnerEntNum, emp.originalTeam, emp.killstreakId );
	
	if ( isdefined( emp.otherModel ) )
	{
		emp.otherModel delete();
	}
	
	if ( isdefined( emp.vehicle ) )
	{
		emp.vehicle delete();
	}
	
	emp delete();
}

function StopEMP( currentTeam, currentOwnerEntNum, originalTeam, killstreakID ) 
{
	StopEMPEffect( currentTeam, currentOwnerEntNum );
	StopEMPRule( originalTeam, killstreakID );
}
	
function StopEMPEffect( team, ownerEntNum ) 
{
	level.ActiveEMPs[ team ] = false;
	level.ActivePlayerEMPs[ ownerEntNum ] = false;
	level notify ( "emp_updated" );
}
	
function StopEMPRule( killstreakOriginalTeam, killstreakId )
{	
	killstreakrules::killstreakStop( "emp", killstreakOriginalTeam, killstreakId );
}

function HasActiveEMP()
{
	return ( level.ActivePlayerEMPs[ self.entNum ] );
}

function TeamHasActiveEMP( team )
{
	return ( level.ActiveEMPs[ team ] > 0 );
}

function EnemyEMPActive()
{
	if( level.teamBased )
	{
		foreach( team in level.teams )
		{
			if( ( team != self.team ) && TeamHasActiveEMP( team ) )
			{
				return true;
			}
		}
	}
	else
	{
		enemies = self teams::GetEnemyPlayers();
		foreach( player in enemies )
		{
			if( player HasActiveEMP() )
			{
				return true;
			}
		}
	}
	
	return false;
}

function EnemyEMPOwner()
{
	enemies = self teams::GetEnemyPlayers();
	foreach( player in enemies )
	{
		if( player HasActiveEMP() )
		{
			return player;
		}
	}

	return undefined;
}

function EMP_JamEnemies( empEnt, hacked )
{
	level endon ( "game_ended" );
	self endon( "killstreak_hacked" );
	
	if( level.teamBased )
	{
		if ( hacked ) 
		{
			level.ActiveEMPs[ empEnt.OriginalTeam ] = false;
		}
		level.ActiveEMPs[ self.team ] = true;
	}
	
	if( hacked )
	{
		level.ActivePlayerEMPs[ empEnt.originalOwnerEntNum ] = false;
	}
	level.ActivePlayerEMPs[ self.entNum ] = true;
	level notify( "emp_updated" );
	level notify( "emp_deployed" );

	VisionSetNaked( "flash_grenade", 1.5 );
	wait ( 0.1 );
	VisionSetNaked( "flash_grenade", 0 );
	VisionSetNaked( GetDvarString( "mapname" ), 5.0 );
	
	empKillstreakWeapon = GetWeapon( "emp" );
	empKillstreakWeapon.isEmpKillstreak = true;
	level killstreaks::DestroyOtherTeamsActiveVehicles( self, empKillstreakWeapon );
	level killstreaks::DestroyOtherTeamsEquipment( self, empKillstreakWeapon );
	level weaponobjects::destroy_other_teams_supplemental_watcher_objects( self, empKillstreakWeapon );
}

function EMPTracker()
{
	level endon ( "game_ended" );
	
	while( true )
	{
		level waittill( "emp_updated" );
		
		foreach ( player in level.players )
		{
			player UpdateEMP();
		}
	}
}

function UpdateEMP()
{
	player = self;
	
	enemy_emp_active = player EnemyEMPActive();
	player setEMPJammed( enemy_emp_active );

	emped = player isEMPJammed(); // ask because a perk may stop it
	player clientfield::set_to_player( "empd_monitor_distance", emped );
	
	if( emped )
	{
		player notify( "emp_jammed" );
	}
}
