#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;

init()
{
	level.mp_prison_killstreak_duration = 25;
	/#
		//Used for tuning purposes. Please do not delete.
//		SetDvarIfUninitialized( "mp_prison_killstreak_duration", 25 );
	#/
	
	precacheLocationSelector( "map_artillery_selector" );
	precacheString( &"KILLSTREAKS_MP_PRISON" );
	
	PreCacheItem( "prison_turret_mp" );
	
	PreCacheLaser( "prison_laser" );
	
	level.mp_prison_InUse = false;
	level.prison_turrets_alive = 0;
	level.prison_turret_alarm_sfx		= "mp_prison_ks_alarm";									//TODO: request audio.
	level.prison_turret_burn_sfx		= "orbital_laser";										//TODO: request audio.
	level.prison_turret_warning_light_friendly = LoadFX( "vfx/lights/light_tracking_prison_blink_friendly" );		
	level.prison_turret_warning_light_enemy = LoadFX( "vfx/lights/light_tracking_prison_blink_enemy" );	
	level.prison_turret_laser_glow = LoadFX( "vfx/lights/prison_tracking_laser_blue" );	
	
	level.killStreakFuncs[ "mp_prison" ] = ::tryUseMpPrison;
	level.mapKillStreak = "mp_prison";
	
	if ( !IsDefined( level.sentrySettings ) )
		level.sentrySettings = [];
	
	level.sentrySettings[ "prison_turret" ] = spawnStruct();
	level.sentrySettings[ "prison_turret" ].health =				999999;		// keep it from dying anywhere in code
	level.sentrySettings[ "prison_turret" ].maxHealth =				1000;		// this is the health we'll check
	level.sentrySettings[ "prison_turret" ].burstMin =				20;
	level.sentrySettings[ "prison_turret" ].burstMax =				120;
	level.sentrySettings[ "prison_turret" ].pauseMin =				0.15;
	level.sentrySettings[ "prison_turret" ].pauseMax =				0.35;
	level.sentrySettings[ "prison_turret" ].sentryModeOn =			"sentry";
	level.sentrySettings[ "prison_turret" ].sentryModeOff =			"sentry_offline";
	level.sentrySettings[ "prison_turret" ].timeOut =				90.0;
	level.sentrySettings[ "prison_turret" ].spinupTime =			0.05;
	level.sentrySettings[ "prison_turret" ].overheatTime =			8.0;
	level.sentrySettings[ "prison_turret" ].cooldownTime =			0.1;
	level.sentrySettings[ "prison_turret" ].fxTime =				0.3;
	level.sentrySettings[ "prison_turret" ].streakName =			"sentry";
	level.sentrySettings[ "prison_turret" ].weaponInfo =			"prison_turret_mp";
	level.sentrySettings[ "prison_turret" ].modelBase =				"prison_security_laser";
	level.sentrySettings[ "prison_turret" ].modelPlacement =		"sentry_minigun_weak_obj";
	level.sentrySettings[ "prison_turret" ].modelPlacementFailed =	"sentry_minigun_weak_obj_red";
	level.sentrySettings[ "prison_turret" ].modelDestroyed =		"sentry_minigun_weak_destroyed";
	level.sentrySettings[ "prison_turret" ].hintString =			&"MP_PRISON_SENSOR_PICKUP";
	level.sentrySettings[ "prison_turret" ].headIcon =				true;
	level.sentrySettings[ "prison_turret" ].teamSplash =			"used_sentry";
	level.sentrySettings[ "prison_turret" ].shouldSplash =			false;
	level.sentrySettings[ "prison_turret" ].voDestroyed =			"sentry_destroyed";
	
	level.mapKillstreakPickupString = level.sentrySettings[ "prison_turret" ].hintString;
	
	level thread onPrisonPlayerConnect();
	
	level.prison_turrets = setupPrisonTurrets();
}

tryUseMpPrison( lifeId, modules )
{
	if ( level.mp_prison_InUse )
	{
		self iPrintLnBold( &"MP_PRISON_IN_USE" );
		return false;
	}
	
	if ( self isUsingRemote() )
	{
		return false;
	}
	
	if ( self isAirDenied() )
	{
		return false;
	}
	
	if ( self isEMPed() )
	{
		return false;
	}
	
	result = setPrisonTurretPlayer( self );
	
	if ( IsDefined( result ) && result )
	{
		self maps\mp\_matchdata::logKillstreakEvent( "mp_prison", self.origin );
	}
	
	return result;
}


setupPrisonTurrets()
{
	turrets = getentarray( "prison_turret", "targetname" );
	
	sentryType = "prison_turret";
	
	for ( i = 0; i < turrets.size; i++ )
	{
		turrets[i].spawned_turret = SpawnTurret( "misc_turret", turrets[i].origin, level.sentrySettings[ sentryType ].weaponInfo, false );
		turrets[i].spawned_turret makeTurretSolid();			//We need to make turrets solid for them to be damageable...
		turrets[i].spawned_turret sentry_initSentry( sentryType );
		turrets[i].spawned_turret.angles = turrets[i].angles;
		
		turrets[i].spawned_turret.alarm_on = false;
		turrets[i].spawned_turret.burn_on = false;
		turrets[i].spawned_turret.proxy_alarm_on = false;
		turrets[i].spawned_turret.prison_turret_active = false;
	}
	
	return turrets;
}


sentry_initSentry( sentryType )
{
	self.sentryType = sentryType;
	self.canBePlaced = true;
	
	self setModel( level.sentrySettings[ self.sentryType ].modelBase );
	self makeTurretInoperable();
	self SetDefaultDropPitch( 0.0 );	// setting this mainly prevents Turret_RestoreDefaultDropPitch() from running
	
	self setTurretModeChangeWait( true );
	self maps\mp\killstreaks\_autosentry::sentry_setInactive();
	
	self thread maps\mp\killstreaks\_autosentry::sentry_handleUse();
}



/*
=============
///ScriptDocBegin
"Name: setPrisonTurretPlayer( <player> )"
"Summary: sets the owner of the Prison turrets when a player uses the map-based killstreak."
"Module: Entity"
"CallOn: N/A"
"MandatoryArg: <player>: the player that used the killstreak"
"Example: result = setPrisonTurretPlayer( self );"
"SPMP: MP"
///ScriptDocEnd
=============
*/
setPrisonTurretPlayer( player )
{
	if( level.mp_prison_InUse )
		return false;
	
	level.mp_prison_InUse = true;
	
	//thread teamPlayerCardSplash( "mp_prison", player );
	
	for ( i = 0; i < level.prison_turrets.size; i++ )
	{
		level.prison_turrets_alive++;
		Assert( IsDefined( level.prison_turrets[i].spawned_turret ) );
		level.prison_turrets[i].spawned_turret sentry_setOwner( player );
		level.prison_turrets[i].spawned_turret.shouldSplash = false;
		level.prison_turrets[i].spawned_turret.carriedBy = player;
		level.prison_turrets[i].spawned_turret sentry_setPlaced();
//		level.prison_turrets[i].spawned_turret LaserOn();			//Was previously used to activate the laser attached to the turret when the turret stunned enemies.
		level.prison_turrets[i].spawned_turret setCanDamage( true );
		level.prison_turrets[i].spawned_turret setCanRadiusDamage( true );
		level.prison_turrets[i].spawned_turret thread sentry_handleDamage();
		level.prison_turrets[i].spawned_turret thread sentry_handleDeath();
		
		level.prison_turrets[i].spawned_turret.alarm_on = false;
		level.prison_turrets[i].spawned_turret.burn_on = false;
		level.prison_turrets[i].spawned_turret.proxy_alarm_on = false;
		level.prison_turrets[i].spawned_turret.shocking_target = false;
		level.prison_turrets[i].spawned_turret.prison_turret_active = true;
		level.prison_turrets[i].spawned_turret.numNearbyPlayers = 0;
		
//		level.prison_turrets[i].spawned_turret thread inflictPrisonTurretPressure();
		//level.prison_turrets[i].spawned_turret thread handlePrisonTurretLights(); //new model doesn't support this visually or technically -katz
		level.prison_turrets[i].spawned_turret thread prisonTurretPortableRadar();
		level.prison_turrets[i].spawned_turret thread repeatOneShotPrisonAlarm();
		level.prison_turrets[i].spawned_turret thread aud_play_announcer_warning();		
	}
	
	level thread prisonTurretTimer();
	level thread monitorPrisonKillstreakOwnership();
	level thread applyPrisonTurretRadarArrow();
	
	return true;
}


/*
=============
///ScriptDocBegin
"Name: prisonTurretTimer()"
"Summary: notifies after mp_prison_killstreak_duration is up."
"Module: Entity"
"CallOn: the level"
"Example: level thread prisonTurretTimer();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
prisonTurretTimer()
{
	level endon( "game_ended" );
	
	/#
//		level.mp_prison_killstreak_duration = GetDvarInt( "mp_prison_killstreak_duration", 25 );
	#/
	wait_time = level.mp_prison_killstreak_duration;
	
	while ( wait_time > 0 )
	{
		wait( 1 );
		maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone();
		wait_time--;
		
		//End this thread if the killstreak is no longer in use. For example, end it if all the turrets are killed.
		if ( level.mp_prison_InUse == false )
		{
			return;
		}
	}
	
	//If the killstreak ended because of time, some turrets might still be alive. Notify death for all turrets to deactivate them.
	for ( i = 0; i < level.prison_turrets.size; i++ )
	{
		level.prison_turrets[i].spawned_turret notify( "fake_prison_death" );			//Using "fake_prison_death" instead of "death" because "death" would detrimentally end some functionality taken from _autosentry.gsc.
	}
}


/*
=============
///ScriptDocBegin
"Name: sentry_setOwner( <owner> )"
"Summary: sets the owner of the spawned turret."
"Module: Entity"
"CallOn: a turret spawned by SpawnTurret()."
"MandatoryArg: <owner>: the player that used the prison killstreak"
"Example: level.prison_turrets[i]["spawned_turret"] sentry_setOwner( player );"
"SPMP: MP"
///ScriptDocEnd
=============
*/
sentry_setOwner( owner )
{
	self.owner = owner;
	
	self SetSentryOwner( self.owner );
//	self SetTurretMinimapVisible( true, self.sentryType );			//Don't want to show minimap icons for mp_prison killstreak.
	
	if ( level.teamBased && IsDefined( owner ) )
	{
		self.team = self.owner.team;
		self setTurretTeam( self.team );
	}
	
	self thread sentry_handleOwnerDisconnect();
}


/*
=============
///ScriptDocBegin
"Name: sentry_setPlaced()"
"Summary: among other things, sets the sentry turret down and puts it into play."
"Module: Entity"
"CallOn: a turret"
"Example: prison_turret["spawned_turret"] maps\mp\killstreaks\_autosentry::sentry_setPlaced();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
sentry_setPlaced()
{
	self setSentryCarrier( undefined );
	
	self.carriedBy forceUseHintOff();
	self.carriedBy = undefined;
	
	if( IsDefined( self.owner ) )
		self.owner.isCarrying = false;
	
	self sentry_setActive();
	
	self playSound( "sentry_gun_plant" );
	
	self notify ( "placed" );
}


/*
=============
///ScriptDocBegin
"Name: sentry_handleDamage()"
"Summary: handles the death of a turret spawned by SpawnTurret()"
"Module: Entity"
"CallOn: a turret spawned by SpawnTurret()."
"Example: self thread sentry_handleDamage();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
sentry_handleDamage()
{
	self endon( "fake_prison_death" );
	level endon( "game_ended" );
	
	self.health = level.sentrySettings[ self.sentryType ].health;
	self.maxHealth = level.sentrySettings[ self.sentryType ].maxHealth;
	self.damageTaken = 0; // how much damage has it taken
	
	while ( true )
	{
		self waittill( "damage", damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, iDFlags, weapon );
		
		// don't allow people to destroy equipment on their team if FF is off
		if ( !maps\mp\gametypes\_weapons::friendlyFireCheck( self.owner, attacker ) )
			continue;
		
		if ( IsDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
			self.wasDamagedFromBulletPenetration = true;
		
		modifiedDamage = 0;
		
		if( IsDefined( weapon ) )
		{
			shortWeapon = maps\mp\_utility::strip_suffix( weapon, "_lefthand" );

			switch( shortWeapon )
			{
				case "emp_grenade_mp":
				case "emp_grenade_var_mp":
					self.largeProjectileDamage = false;
					modifiedDamage = self.maxHealth + 1;
					if ( isPlayer( attacker ) )
					{
						attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "sentry" );
					}
					break;
				default:
					if ( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" )
					{
						modifiedDamage = damage * 3.5;
					}
					else
					{
						modifiedDamage = 0;
					}
					if ( IsPlayer( attacker ) )
					{
						attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "sentry" );
					}
					break;
			}
			
			maps\mp\killstreaks\_killstreaks::killstreakHit( attacker, weapon, self );
		}
		
		self.damageTaken += modifiedDamage;
		
		if ( self.damageTaken >= self.maxHealth )
		{
			thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, meansOfDeath, weapon );
			
			if ( isPlayer( attacker ) && (!IsDefined(self.owner) || attacker != self.owner) )
			{
				level thread maps\mp\gametypes\_rank::awardGameEvent( "map_killstreak_destroyed", attacker, weapon, undefined, meansOfDeath );	
			}
			
			if ( IsDefined( self.owner ) )
				self.owner thread leaderDialogOnPlayer( level.sentrySettings[ self.sentryType ].voDestroyed, undefined, undefined, self.origin );
			
			self notify( "fake_prison_death" );
			
			return;
		}
	}
}


sentry_handleDeath()
{
	self waittill ( "fake_prison_death" );
	
	// this handles cases of deletion
	if ( !IsDefined( self ) )
		return;
	
	self maps\mp\killstreaks\_autosentry::sentry_setInactive();
	self SetSentryOwner( undefined );
	self SetTurretMinimapVisible( false );
	
	//Turning off the turrets' head icons. This is added functionality for the mp_prison turrets.
	if( level.sentrySettings[ self.sentryType ].headIcon )
	{
		if ( level.teamBased )
			self maps\mp\_entityheadicons::setTeamHeadIcon( "none", (0,0,0) );
		else
			self maps\mp\_entityheadicons::setPlayerHeadIcon( "none", (0,0,0) );
	}
	
	level.prison_turrets_alive--;
	
	self setCanDamage( false );
	self setCanRadiusDamage( false );
	
//	self LaserOff();			//Used the laser attached to the turret when the turret stunned enemies.
	
	
	//Cleaning up sound and damage stuff for the turret./////////
	if ( self.alarm_on == true )
	{
//		self thread stop_loop_sound_on_entity( level.prison_turret_alarm_sfx );
		self.alarm_on = false;
	}
	if ( self.burn_on == true )
	{
//		self thread stop_loop_sound_on_entity( level.prison_turret_burn_sfx );
		self.burn_on = false;
//		StopFXOnTag( level.prison_turret_beam, self, "tag_weapon" );
	}
	if ( IsDefined( self.previous_turret_target ) )
	{
		self notify( "lost_or_changed_target" );
		self.previous_turret_target = undefined;
	}
	self.shocking_target = false;
	self.turret_on_target = undefined;
	
	if ( self.proxy_alarm_on == true )
	{
//		self thread stop_loop_sound_on_entity( level.prison_turret_alarm_sfx );
		self.proxy_alarm_on = false;
	}
	self.prison_turret_active = false;
	/////////////////////////////////////////////////////////////
}


/*
=============
///ScriptDocBegin
"Name: sentry_setActive()"
"Summary: activates the sentry turret"
"Module: Entity"
"CallOn: a turret"
"Example: self sentry_setActive();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
sentry_setActive()
{
	self SetMode( level.sentrySettings[ self.sentryType ].sentryModeOn );
	
	if( level.sentrySettings[ self.sentryType ].headIcon )
	{
		if ( level.teamBased )
			self maps\mp\_entityheadicons::setTeamHeadIcon( self.team, (0,0,25) );
		else
			self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,25) );
	}
}


/*
=============
///ScriptDocBegin
"Name: sentry_handleOwnerDisconnect()"
"Summary: notifies death for this turret (self) if its owner disconnects."
"Module: Entity"
"CallOn: a turret spawned by SpawnTurret()."
"Example: self thread sentry_handleOwnerDisconnect();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
sentry_handleOwnerDisconnect()
{
	level endon ( "game_ended" );
	self endon( "fake_prison_death" );			//Ending this thread if the turret (self) dies by other means (damage, time).
	
	self.owner waittill_any( "disconnect", "joined_team", "joined_spectators" );
	
	self notify( "fake_prison_death" );
}


/*
=============
///ScriptDocBegin
"Name: monitorPrisonKillstreakOwnership()"
"Summary: frees up the prison killstreak when the killstreak time is up or all turrets are disabled."
"Module: Entity"
"CallOn: the level"
"Example: level thread monitorPrisonKillstreakOwnership()"
"SPMP: MP"
///ScriptDocEnd
=============
*/
monitorPrisonKillstreakOwnership()
{
	level endon( "game_ended" );
	
	//If any turrets are alive or any turrets are up... wait!
	while ( level.prison_turrets_alive > 0 )
	{
		wait( 0.05 );
	}
	
	level.mp_prison_InUse = false;
	
	//Wrap up a bunch of stuff now that the killstreak is over.
	for ( i = 0; i < level.prison_turrets.size; i++ )
	{
		if ( level.prison_turrets[i].spawned_turret.proxy_alarm_on == true )
		{
//			level.prison_turrets[i].spawned_turret thread stop_loop_sound_on_entity( level.prison_turret_alarm_sfx );
			level.prison_turrets[i].spawned_turret.proxy_alarm_on = false;
		}
		
		for ( j = 0; j < level.players.size; j++ )
		{
			level.players[j].laser_tag_array[i] LaserOff();
			stopfxontag(level.prison_turret_laser_glow, level.players[j].laser_tag_array[i], "tag_laser");
			level.players[j].laser_tag_array[i] ClearLookAtTarget();
			level.players[j].laser_tag_array[i].laserFXActive = false;
		}
	}
	
	for ( k = 0; k < level.players.size; k++ )
	{
		level.players[k].numNearbyPrisonTurrets = 0;
		
		if ( level.players[k] HasPerk( "specialty_radararrow", true ) )
		{
			level.players[k] unsetPerk( "specialty_radararrow", true );
		}
		
		level.players[k] notify( "player_not_tracked" );
		//level.players[k] endPrisonTrackingOverlay();
		level.players[k].is_being_tracked = false;
	}
}


/*
=============
///ScriptDocBegin
"Name: handlePrisonTurretLights()"
"Summary: turns on/off the prison turrets lights."
"Module: Entity"
"CallOn: a prison turret"
"Example: turret thread handlePrisonTurretLights();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
handlePrisonTurretLights()
{
	PlayFXOnTag( level.prison_turret_warning_light_friendly, self, "tag_fx" );
	
	self waittill( "fake_prison_death" );
	
	StopFXOnTag( level.prison_turret_warning_light_friendly, self, "tag_fx" );
}


/*
=============
///ScriptDocBegin
"Name: prisonTurretPortableRadar()"
"Summary: creates a portable radar entity for this turret."
"Module: Entity"
"CallOn: a prison turret"
"Example: turret thread prisonTurretPortableRadar();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
prisonTurretPortableRadar()
{
	level endon( "game_ended" );
	
	self.portable_radar = spawn( "script_model", self.origin );
	self.portable_radar.team = self.team;
	/#
	self.portable_radar.targetname = "portable_radar";	// best practices to track bandwidth hogs
	#/
	
	self.portable_radar makePortableRadar( self.owner );
	
	self waittill( "fake_prison_death" );
	
	level maps\mp\gametypes\_portable_radar::deletePortableRadar( self.portable_radar );
	self.portable_radar = undefined;
}


/*
=============
///ScriptDocBegin
"Name: applyPrisonTurretRadarArrow()"
"Summary: loops through all prison turrets and all players to determine if players should be marked on the minimap"
"Module: Entity"
"CallOn: level"
"Example: level thread applyPrisonTurretRadarArrow"
"SPMP: MP"
///ScriptDocEnd
=============
*/
applyPrisonTurretRadarArrow()
{
	level endon( "game_ended" );
	
	while ( level.mp_prison_InUse )
	{
		if ( IsDefined( level.prison_turrets ) && IsDefined( level.players ) )
		{
			for ( i = 0; i < level.prison_turrets.size; i++ )
			{
				if ( level.prison_turrets[i].spawned_turret.prison_turret_active != true )
				{
					for ( j = 0; j < level.players.size; j++ )
					{
						if ( level.players[j].laser_tag_array[i].laserFXActive == true )
						{
							level.players[j].laser_tag_array[i] LaserOff();
							level.players[j].laser_tag_array[i] ClearLookAtTarget();
							level.players[j].laser_tag_array[i].laserFXActive = false;
						}
					}
					continue;
				}
				
				level.prison_turrets[i].spawned_turret.numNearbyPlayers = 0;
				
				for ( j = 0; j < level.players.size; j++ )
				{
					setLaserToOn = false;
					
					randomRange = 10;
					randomOffset = ( randomFloat( randomRange ), randomFloat( randomRange ), randomFloat( randomRange ) ) - ( 5, 5, 5 );
					if ( level.players[j] GetStance() == "stand" )
					{
						player_origin_offset = ( 0, 0, 50 ) + randomOffset;
					}
					else if ( level.players[j] GetStance() == "crouch" )
					{
						player_origin_offset = ( 0, 0, 35 ) + randomOffset;
					}
					else
					{
						player_origin_offset = ( 0, 0, 10 ) + randomOffset;
					}
					
					//TODO: get this working in free for all.
					if ( IsDefined( level.players[j] ) && IsAlive( level.players[j] ) &&
					    ( ( level.teamBased && level.players[j].team != level.prison_turrets[i].spawned_turret.team ) ||
					     ( !level.teamBased && level.players[j] != level.prison_turrets[i].spawned_turret.owner ) ) )
					{
						turret_to_player_distance = DistanceSquared( level.players[j].origin, level.prison_turrets[i].spawned_turret.origin );
						
						if ( turret_to_player_distance < 3610000 )
						{
							if ( SightTracePassed( level.prison_turrets[i].spawned_turret.origin, level.players[j].origin + player_origin_offset, false, undefined ) )
							{
								setLaserToOn = true;
							}
						}
					}
					
					if ( setLaserToOn )
					{
						// do not update laser_tag angles ! they are synchronized automatically thanks to the call to SetLookAtTarget()
						//level.players[j].laser_tag_array[i].angles = VectorToAngles( ( level.players[j].origin + player_origin_offset ) - level.prison_turrets[i].spawned_turret.origin );
						if ( level.players[j].laser_tag_array[i].laserFXActive == false )
						{
							level.players[j].laser_tag_array[i].laserFXActive = true;
							level.players[j].laser_tag_array[i] LaserOn( "prison_laser" );			//The i index corresponds directly to one of the level.prison_turret turrets.
							playfxontag(level.prison_turret_laser_glow, level.players[j].laser_tag_array[i], "tag_laser");
							level.players[j].laser_tag_array[i] SetLookAtTarget( level.players[j], "bone", "tag_eye", "randomoffset" );
						}
						
						level.players[j].numNearbyPrisonTurrets++;
						level.prison_turrets[i].spawned_turret.numNearbyPlayers++;
					}
					else if ( level.players[j].laser_tag_array[i].laserFXActive == true )
					{
						level.players[j].laser_tag_array[i].laserFXActive = false;
						level.players[j].laser_tag_array[i] LaserOff();
						stopfxontag(level.prison_turret_laser_glow, level.players[j].laser_tag_array[i], "tag_laser");
						level.players[j].laser_tag_array[i] ClearLookAtTarget();
					}
				}
				
				if ( level.prison_turrets[i].spawned_turret.numNearbyPlayers > 0 )
				{
					if ( level.prison_turrets[i].spawned_turret.proxy_alarm_on == false )
					{
//						level.prison_turrets[i].spawned_turret thread play_loop_sound_on_entity( level.prison_turret_alarm_sfx );
						level.prison_turrets[i].spawned_turret.proxy_alarm_on = true;
					}
				}
				else
				{
					if ( level.prison_turrets[i].spawned_turret.proxy_alarm_on == true )
					{
//						level.prison_turrets[i].spawned_turret thread stop_loop_sound_on_entity( level.prison_turret_alarm_sfx );
						level.prison_turrets[i].spawned_turret.proxy_alarm_on = false;
					}
				}
			}
			
			//For each player, give it the specialty_radararrow perk if it is near at least one turret.
			for ( k = 0; k < level.players.size; k++ )
			{
				if ( level.players[k].numNearbyPrisonTurrets > 0 )
				{
					level.players[k] setPerk( "specialty_radararrow", true, false );
					
					if ( level.players[k].is_being_tracked == false )
					{
						//level.players[k] thread fadeInOutPrisonTrackingOverlay();
						level.players[k].is_being_tracked = true;
					}
				}
				else
				{
					if ( level.players[k] HasPerk( "specialty_radararrow", true ) )
					{
						level.players[k] unsetPerk( "specialty_radararrow", true );
					}
					
					level.players[k] notify( "player_not_tracked" );
					//level.players[k] endPrisonTrackingOverlay();
					level.players[k].is_being_tracked = false;
				}
				
				level.players[k].numNearbyPrisonTurrets = 0;
			}
		}
		wait( 0.1 );
	}
}


/*
=============
///ScriptDocBegin
"Name: createLaserTagArray()"
"Summary: creates an array of tag_laser script_models for a player."
"Module: Entity"
"CallOn: a player"
"Example: level.players[j] createLaserTagArray();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
createLaserTagArray()
{
	if ( !IsDefined( self.laser_tag_array ) )
	{
		self.laser_tag_array = [];
		for ( i = 0; i < level.prison_turrets.size; i++ )
		{
			//laserOrigin = level.prison_turrets[i].spawned_turret GetTagOrigin( "tag_laser");
			laserOrigin = level.prison_turrets[i].spawned_turret.origin;
			self.laser_tag_array[i] = Spawn( "script_model", laserOrigin );
			self.laser_tag_array[i] SetModel( "tag_laser" );
			self.laser_tag_array[i].laserFXActive = false;
			/#
			self.laser_tag_array[i].targetname = "tag_laser";	// best practices to track bandwidth hogs
			#/
		}
	}
}


/*
=============
///ScriptDocBegin
"Name: deleteLaserTagArray()"
"Summary: deletes the array of script_models created for a player when playing in mp_prison."
"Module: Entity"
"CallOn: a player"
"Example: player deleteLaserTagArray();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
deleteLaserTagArray()
{
	if ( IsDefined( self.laser_tag_array ) )
	{
		for ( i = 0; i < level.prison_turrets.size; i++ )
		{
			self.laser_tag_array[i] ClearLookAtTarget();
			self.laser_tag_array[i] Delete();
		}
	}
}


/*
=============
///ScriptDocBegin
"Name: onPrisonPlayerConnect()"
"Summary: does stuff to a player for the mp_prison killstreak when a player connects."
"Module: Entity"
"CallOn: level"
"Example: level thread onPrisonPlayerConnect();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
onPrisonPlayerConnect()
{
	level endon( "game_ended" );
	
	while ( true )
	{
		level waittill( "connected", player );
		
		//player createPrisonTurretTrackingOverlay();
		
		player.is_being_tracked = false;
		
		player createLaserTagArray();
		
		player.numNearbyPrisonTurrets = 0;
		
		player thread onPrisonPlayerDisconnect();
		
		//TODO: set more things to zero here
	}
}


/*
=============
///ScriptDocBegin
"Name: onPrisonPlayerDisconnect()"
"Summary: does stuff to a player for the mp_prison killstreak when a player disconnects."
"Module: Entity"
"CallOn: a player"
"Example: player thread onPrisonPlayerDisconnect();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
onPrisonPlayerDisconnect()
{
	level endon( "game_ended" );
	
	self waittill( "disconnect" );
	
	self deleteLaserTagArray();
}


/*
=============
///ScriptDocBegin
"Name: createPrisonTurretTrackingOverlay()"
"Summary: create a HUD element for this player that will be used for the prison turret tracking effect."
"Module: Entity"
"CallOn: a player"
"Example: player createPrisonTurretTrackingOverlay();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
createPrisonTurretTrackingOverlay()
{
	if ( !IsDefined( self.prisonTurretTrackingOverlay ) )
	{
		self.prisonTurretTrackingOverlay = newClientHudElem( self );
		self.prisonTurretTrackingOverlay.x = -80;
		self.prisonTurretTrackingOverlay.y = -60;
		self.prisonTurretTrackingOverlay setshader( "tracking_drone_targeted_overlay", 800, 600 );
		self.prisonTurretTrackingOverlay.alignX = "left";
		self.prisonTurretTrackingOverlay.alignY = "top";
		self.prisonTurretTrackingOverlay.horzAlign = "fullscreen";
		self.prisonTurretTrackingOverlay.vertAlign = "fullscreen";
		self.prisonTurretTrackingOverlay.alpha = 0;
	}
}


/*
=============
///ScriptDocBegin
"Name: fadeInOutPrisonTrackingOverlay()"
"Summary: fades in/out the overlay used to denote prison turret tracking."
"Module: Entity"
"CallOn: a player"
"Example: level.players[k] thread fadeInOutPrisonTrackingOverlay();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
fadeInOutPrisonTrackingOverlay()
{
	level endon( "game_ended" );
	self endon( "player_not_tracked" );
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "joined_team" );
	self endon( "joined_spectators" );
	
	while ( true )
	{
		if(IsDefined(self.TurretTrackingOverlay))
		{
			brightness = randomFloatRange(0.25, 1.0);
			self.prisonTurretTrackingOverlay FadeOverTime( 0.1 );
			self.prisonTurretTrackingOverlay.color = ( brightness, brightness, brightness );
			self.prisonTurretTrackingOverlay.alpha = 1;
			wait 0.1;
		}
		wait( 0.05 );
	}
}


/*
=============
///ScriptDocBegin
"Name: endPrisonTrackingOverlay()"
"Summary: quickly fades out the prison turret tracking overlay on a player."
"Module: Entity"
"CallOn: a player"
"Example: level.players[k] endPrisonTrackingOverlay();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
endPrisonTrackingOverlay()
{
	level endon( "game_ended" );
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "joined_team" );
	self endon( "joined_spectators" );
	
	self.prisonTurretTrackingOverlay FadeOverTime( 0.2 );
	self.prisonTurretTrackingOverlay.alpha = 0.0;
}


/*
=============
///ScriptDocBegin
"Name: repeatOneShotPrisonAlarm()"
"Summary: repeatedly plays the prison turret alarm on a prison turret."
"Module: Entity"
"CallOn: a prison turret"
"Example: level.prison_turrets[i].spawned_turret thread repeatOneShotPrisonAlarm();"
"SPMP: MP"
///ScriptDocEnd
=============
*/
repeatOneShotPrisonAlarm()
{
	self endon( "fake_prison_death" );
	
	while ( level.mp_prison_InUse )
	{
		if ( self.proxy_alarm_on == true )
		{
			playSoundAtPos( self.origin, level.prison_turret_alarm_sfx );
		}
		
		wait( 4 );
	}
}


aud_play_announcer_warning()
{
	wait(2.5);
	playSoundAtPos( ( 0,0,0 ), "mp_prison_anouncer_ext" );
}
