#using scripts\codescripts\struct;

#using scripts\shared\callbacks_shared;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\damagefeedback_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\weapons\_tacticalinsertion;
#using scripts\shared\weapons\_weaponobjects;

    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   

#using_animtree ( "mp_trophy_system" );








	
#precache( "fx", "weapon/fx_trophy_flash" );
#precache( "fx", "weapon/fx_trophy_detonation" );
#precache( "fx", "weapon/fx_trophy_radius_indicator" );
#precache( "triggerstring", "MP_TROPHY_SYSTEM_PICKUP" );
#precache( "triggerstring", "MP_TROPHY_SYSTEM_DESTROY" );
#precache( "triggerstring", "MP_TROPHY_SYSTEM_HACKING" );
	
#namespace trophy_system;

function init_shared()
{
	level.trophyLongFlashFX = "weapon/fx_trophy_flash";
	level.trophyDetonationFX = "weapon/fx_trophy_detonation";
	level.fx_trophy_radius_indicator = "weapon/fx_trophy_radius_indicator";
	
	trophyDeployAnim = %o_trophy_deploy;
	trophySpinAnim = %o_trophy_spin;
	
	level thread register();
	
	callback::on_spawned( &createTrophySystemWatcher );
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function register()
{
	clientfield::register( "missile", "trophy_system_state", 1, 2, "int" );
	clientfield::register( "scriptmover", "trophy_system_state", 1, 2, "int" );
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function createTrophySystemWatcher() // self == player
{
	if( level.gametype == "infect" && self.team == game["attackers"] )
	{
		return;
	}

	watcher = self weaponobjects::createUseWeaponObjectWatcher( "trophy_system", self.team );
	
	watcher.onDetonateCallback =&trophySystemDetonate;
	watcher.activateSound = "wpn_claymore_alert";
	watcher.hackable = true;
	watcher.hackerToolRadius = level.equipmentHackerToolRadius;
	watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
	watcher.ownerGetsAssist = true;
	watcher.ignoreDirection = true;
	watcher.activationDelay = 0.1;
	watcher.headIcon = false;

	watcher.enemyDestroy = true;

	watcher.onSpawn =&onTrophySystemSpawn;
	watcher.onDamage =&watchTrophySystemDamage;
	watcher.onDestroyed =&onTrophySystemSmashed;

	watcher.onStun =&weaponobjects::weaponStun;
	watcher.stunTime = 1;
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function onTrophySystemSpawn( watcher, player ) // self == trophy system
{
	player endon( "death" );
	player endon( "disconnect" );
	level endon( "game_ended" );
	self endon( "death" );
	self UseAnimTree( #animtree );
	self weaponobjects::onSpawnUseWeaponObject( watcher, player );	
	self.trophySystemStationary = false;

	moveState = self util::waitTillRollingOrNotMoving();
	
	if ( moveState == "rolling" )
	{
		self SetAnim( %o_trophy_deploy, 1.0 );
		self clientfield::set( "trophy_system_state", 1 );
		
		self util::waitTillNotMoving();
	}
	
	self.trophySystemStationary = true;
	
	player AddWeaponStat( self.weapon, "used", 1 );	
		    
	self.ammo = player ammo_get( self.weapon );
	self thread trophyActive( player );
	self thread trophyWatchHack();
	
	self SetAnim( %o_trophy_deploy, 0.0 );
	self SetAnim( %o_trophy_spin, 1.0 );
	self clientfield::set( "trophy_system_state", 2 );
	
	self playsound("wpn_trophy_deploy_start");
	
	self PlayLoopSound( "wpn_trophy_spin", 0.25 );

	self setReconModelDeployed();
}

function setReconModelDeployed() // self == trophy system
{
	if ( isdefined( self.reconModelEntity ) )
	{
		self.reconModelEntity clientfield::set( "trophy_system_state", 2 );
	}
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function trophyWatchHack() // self == trophy system
{
	self endon( "death" );

	self waittill( "hacked", player );
	
	self clientfield::set( "trophy_system_state", 0 );
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function onTrophySystemSmashed( attacker ) // self == trophy system
{
	PlayFX( level._effect["tacticalInsertionFizzle"], self.origin );
	self playsound ("dst_trophy_smash");

	if( isdefined( level.playEquipmentDestroyedOnPlayer ) )
	{
		self.owner [[level.playEquipmentDestroyedOnPlayer]]( );
	}

	if ( isdefined(attacker) && self.owner util::IsEnemyPlayer( attacker ) )
	{
		attacker challenges::destroyedEquipment();
		scoreevents::processScoreEvent( "destroyed_trophy_system", attacker, self.owner );
	}

	self delete();
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function trophyActive( owner ) // self == trophy system
{
	owner endon( "disconnect" );
	self endon( "death" );
	self endon( "hacked" );

	while( true )
	{
		if ( !isdefined( self ) )
		{
			return;
		}

		if (( level.missileEntities.size < 1  ) || isdefined( self.disabled ))
		{
			wait( .05 );
			continue;
		}

		for ( index=0; index < level.missileEntities.size; index++ )
		{
			wait( .05 ); // only handle 1 missile per frame
			
			if ( !isdefined( self ) )
			{
				return;
			}

			grenade = level.missileEntities[index];
			
			if ( !isdefined(grenade) )
				continue;
			
			if ( grenade == self )
				continue;

			if ( !grenade.weapon.destroyableByTrophySystem )
			{
				continue;
			}

			switch( grenade.model )
			{
				case "t6_wpn_grenade_supply_projectile":
					continue;
			}

			if ( grenade.weapon == self.weapon )
			{
				if ( self.trophySystemStationary == false && grenade.trophySystemStationary == true ) 
				{
					continue;	
				}
			}
			
			if ( !isdefined( grenade.owner ) )
			{
				grenade.owner = GetMissileOwner( grenade );
			}

			if ( isdefined( grenade.owner ))
			{
				if ( level.teamBased )
				{
					if ( grenade.owner.team == owner.team )
					{
						continue;
					}
				}
				else
				{
					if ( grenade.owner == owner )
					{
						continue;
					}
				}

				grenadeDistanceSquared = DistanceSquared( grenade.origin, self.origin );
			
				if ( grenadeDistanceSquared < ( 512 * 512 ))
				{
					if ( BulletTracePassed( grenade.origin, self.origin + (0,0,29), false, self, grenade, false, true ) )
					{
						playFX( level.trophyLongFlashFX, self.origin + (0,0,15), ( grenade.origin - self.origin ), AnglesToUp( self.angles ) );
						
						// projectileExplode deletes the missile ent 
						// so need to update index on shuffled-down level.missileEntities[]
						owner thread projectileExplode( grenade, self );
						index--;

						//Eckert - Plays sound when destroying projectile/grenade
						self playsound ( "wpn_trophy_alert" );
						
						if ( GetDvarint( "player_sustainAmmo" ) == 0 )
						{
							self.ammo--;
							if ( self.ammo <= 0 )
							{
								self thread trophySystemDetonate();
							}
						}
						
					}
				}
			}
		}
	}

}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function projectileExplode( projectile, trophy ) // self == trophy owning player
{
	self endon( "death" );
	
	projPosition = projectile.origin;

	playFX( level.trophyDetonationFX, projPosition );
	projectile notify ( "trophy_destroyed" );

	trophy RadiusDamage( projPosition, 128, 105, 10, self );
		
	scoreevents::processScoreEvent( "trophy_defense", self );
	self challenges::trophy_defense( projPosition, 512 );
	
	if ( self util::is_item_purchased( "trophy_system" ) )
	{
		self AddPlayerStat( "destroy_explosive_with_trophy", 1 );
	}
	self AddWeaponStat( trophy.weapon, "CombatRecordStat", 1 );
	
	projectile delete();
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function trophyDestroyTacInsert( tacInsert, trophy )  // self == trophy system owner 
{
	self endon( "death" );

	tacPos = tacInsert.origin;
	playFX( level.trophyDetonationFX, tacInsert.origin );

	tacInsert thread tacticalinsertion::tacticalInsertionDestroyedByTrophySystem( self, trophy );
	trophy RadiusDamage( tacPos, 128, 105, 10, self );
		
	scoreevents::processScoreEvent( "trophy_defense", self );
	if ( self util::is_item_purchased( "trophy_system" ) )
	{
		self AddPlayerStat( "destroy_explosive_with_trophy", 1 );
	}
	self AddWeaponStat( trophy.weapon, "CombatRecordStat", 1 );
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function trophySystemDetonate(attacker, weapon, target)
{
	if ( !isdefined( weapon ) || !weapon.isEmp )
	{
		PlayFX( level._equipment_explode_fx_lg, self.origin );
	}

	if ( isdefined(attacker) && self.owner util::IsEnemyPlayer( attacker ) )
	{
		attacker challenges::destroyedEquipment( weapon );
		scoreevents::processScoreEvent( "destroyed_trophy_system", attacker, self.owner, weapon );
	}

	PlaySoundAtPosition ( "exp_trophy_system", self.origin );
	self delete();
}

//******************************************************************
//                                                                 *
//                                                                 *
//******************************************************************
function watchTrophySystemDamage( watcher ) // self == trophy system
{
	self endon( "death" );
	self endon( "hacked" );

	self SetCanDamage( true );
	damageMax = 20;

	if ( !self util::isHacked() )
	{
		self.damageTaken = 0;
	}

	self.maxhealth = 10000;
	self.health = self.maxhealth;

	self setmaxhealth( self.maxhealth );

	attacker = undefined;

	while( true )
	{
		self waittill ( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, weapon, iDFlags );

		attacker = self [[ level.figure_out_attacker ]]( attacker );

		if( !isplayer( attacker ))
		{
			continue;
		}

		if ( level.teambased )
 		{
			// if we're not hardcore and the team is the same, do not destroy
			if( !level.hardcoreMode && self.owner.team == attacker.pers["team"] && self.owner != attacker )
			{
				continue;
			}
		}

		// most equipment should be flash/concussion-able, so it'll disable for a short period of time
		// check to see if the equipment has been flashed/concussed and disable it (checking damage < 5 is a bad idea, so check the weapon name)
		// we're currently allowing the owner/teammate to flash their own
		// do damage feedback
		if ( watcher.stunTime > 0 && weapon.doStun )
		{
			self thread weaponobjects::stunStart( watcher, watcher.stunTime ); 
		}

		if ( weapon.doDamageFeedback )
		{
			// if we're not on the same team then show damage feedback
			if ( level.teambased && self.owner.team != attacker.team )
			{
				if ( damagefeedback::doDamageFeedback( weapon, attacker ) )
					attacker damagefeedback::update();
			}
			// for ffa just make sure the owner isn't the same
			else if ( !level.teambased && self.owner != attacker )
			{
				if ( damagefeedback::doDamageFeedback( weapon, attacker ) )
					attacker damagefeedback::update();
			}
		}

		if ( type == "MOD_MELEE" || weapon.isEmp || weapon.destroysEquipment )
		{
			self.damageTaken = damageMax;
		}
		else
		{
			self.damageTaken += damage;
		}

		if( self.damageTaken >= damageMax )
		{
			watcher thread weaponobjects::waitAndDetonate( self, 0.05, attacker, weapon );
			return;
		}
	}
}

function ammo_scavenger( weapon )
{	
	self ammo_reset();
}

function ammo_reset()
{
	self._trophy_system_ammo1 = undefined;
	self._trophy_system_ammo2 = undefined;
}

function ammo_get( weapon )
{
	totalAmmo = weapon.ammoCountEquipment;
		
	if ( isdefined( self._trophy_system_ammo1 ) && !self util::isHacked() )
    {
		totalAmmo = self._trophy_system_ammo1;
		self._trophy_system_ammo1 = undefined;
		
		if ( isdefined( self._trophy_system_ammo2 ) )
		{
			self._trophy_system_ammo1 = self._trophy_system_ammo2;
			self._trophy_system_ammo2 = undefined;
		}
    }
	
	return totalAmmo;
}

function ammo_weapon_pickup( ammo )
{
	if ( isdefined( ammo ) )
	{
		if ( isdefined( self._trophy_system_ammo1 ) )
		{
			self._trophy_system_ammo2 = self._trophy_system_ammo1;
			self._trophy_system_ammo1 = ammo;
		}
		else
		{
			self._trophy_system_ammo1 = ammo;
		}
	}
}

function ammo_weapon_hacked( ammo )
{
	self ammo_weapon_pickup( ammo );
}