#using scripts\codescripts\struct;

#using scripts\shared\array_shared;
#using scripts\shared\compass;
#using scripts\shared\math_shared;
#using scripts\shared\util_shared;
#using scripts\shared\exploder_shared;
#using scripts\shared\scene_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\lui_shared;

#using scripts\mp\_load;
#using scripts\mp\_util;
#using scripts\mp\_destructible;

#using scripts\mp\_nuketown_mannequin;
#using scripts\mp\mp_nuketown_x_fx;
#using scripts\mp\mp_nuketown_x_sound;

    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   









                                                           #precache( "model", "p7_dest_ntx_mannequin_male_01_black" );  #precache( "model", "p7_dest_ntx_mannequin_male_02_black" );  #precache( "model", "p7_dest_ntx_mannequin_female_01_black" );  #precache( "model", "p7_dest_ntx_mannequin_female_02_black" );  #precache( "model", "p7_dest_ntx_mannequin_female_03_black" );                                            
	
#precache( "string", "mp_nuketown_fs_endingmovie" ); //end game movie

function autoexec init()
{
	// Required for mannequins to find valid enemy positions.
	level._enableLastValidPosition = true;
}

function main()
{
	clientfield::register( "scriptmover", "nuketown_population_ones", 1, 4, "int" );
	clientfield::register( "scriptmover", "nuketown_population_tens", 1, 4, "int" );
	clientfield::register( "world", "nuketown_endgame", 1, 1, "int" );
	
	precache();
	
	mp_nuketown_x_fx::main();
	mp_nuketown_x_sound::main();
	
	level.remotemissile_kill_z = ( ( -175 ) + ( 50 ) );
	
	level.team_free_targeting = true;
	
	level.update_escort_robot_path = &update_escort_robot_path;
	
	load::main();

	compass::setupMiniMap( "compass_map_mp_nuketown_x" );
	
	// Set up the default range of the compass
	SetDvar( "compassmaxrange", "2100" );
	
	// Spawn a radius trigger to disable escorting robot from upstairs 
	level.levelescortDisable = [];
	//level.levelescortDisable[ level.levelescortDisable.size ] = Spawn( "trigger_radius", position, 0, radius, height );
	level.levelescortDisable[ level.levelescortDisable.size ] = Spawn( "trigger_radius", ( 749 , 872 , -112.5 ), 0, 150, 128 );
	level.levelescortDisable[ level.levelescortDisable.size ] = Spawn( "trigger_radius", ( 868 , 909.5 , -112.5 ), 0, 150, 128 );
	level.levelescortDisable[ level.levelescortDisable.size ] = Spawn( "trigger_radius", ( 968 , 894.5 , -112.5 ), 0, 100, 128 );
	level.levelescortDisable[ level.levelescortDisable.size ] = Spawn( "trigger_radius", ( 1009 , 902 , -112.5 ), 0, 100, 128 );

	level.end_game_video = SpawnStruct();
	level.end_game_video.name = "mp_nuketown_fs_endingmovie";
	level.end_game_video.duration = 5;

	level.headless_mannequin_count = 0;
	level.limbless_mannequin_count = 0;
	level.destructible_callbacks[ "headless"] = &mannequin_headless;
	level.destructible_callbacks[ "right_arm_lower"] = &mannequin_right_arm_lower;
	level.destructible_callbacks[ "right_arm_upper"] = &mannequin_right_arm_upper;
	level.destructible_callbacks[ "left_arm_lower"] = &mannequin_left_arm_lower;
	level.destructible_callbacks[ "left_arm_upper"] = &mannequin_left_arm_upper;
	
	level thread tU3_disable_bad_robot_wallrun_nodes();
	
	// Stockpile hub points
	level.cleanDepositPoints = Array ( ( 21.4622 , 133.075 , -65.875 ),
                                  ( 976.601 , 630.604 , -56.875 ),
                                  ( -787.35 , 508.411 , -59.875 ),
                                  ( 32.424 , 952.018 , -60.875 ) );
	
	level thread nuked_mannequin_init();
	level thread nuked_population_think();
	/#
	level nuked_endgame_init();
	#/
}

function nuked_population_think()
{
	popTensArr = getEntArray( "counter_tens" ,"targetname");
	popOnesArr = getEntArray( "counter_ones" ,"targetname");
	
	popTens = popTensArr[0];
	popOnes = popOnesArr[0];
	
	level.oldPopTensValue = 0;
	level.oldPopOnesValue = 0;
	while( 1 )
	{
		players = GetPlayers();
		actors = GetActorArray();
		count = 0;
		foreach( player in players )
		{
			if( IsAlive( player ) )
			{
				count++;
			}
		}
		
		foreach( actor in actors )
		{
			if( IsAlive( actor ) )
			{
				count++;
			}
		}
		
		level.popTensValue = int( floor( count / 10 ) );
		level.popOnesValue = count % 10;
		
		if( level.oldPopTensValue != level.popTensValue )
		{
			popTens clientfield::set( "nuketown_population_tens", level.popTensValue );
		}
		
		if( level.oldPopOnesValue != level.popOnesValue )
		{
			popOnes clientfield::set( "nuketown_population_ones", level.popOnesValue );
		}
		
		level.oldPopTensValue = level.popTensValue;
		level.oldPopOnesValue = level.popOnesValue;
		
		{wait(.05);};
	}
}

function precache()
{
	// DO ALL PRECACHING HERE
}

function nuked_endgame_init()
{
	/#
	mapname = GetDvarString( "mapname" );
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug End Game Sequence/Start Sequence\" \"set level_notify nuked_end_sequence_start \"\n" );
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug End Game Sequence/Reset Sequence\" \"set level_notify nuked_end_sequence_reset \"\n" );
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug End Game Sequence/Test Movie\" \"set level_notify nuked_test_movie \"\n" );
	level thread nuked_endgame_think();
	#/
}

function nuked_test_movie()
{
	while( 1 )
	{
		level waittill( "nuked_test_movie" );
	
		if( isDefined( level.end_game_video ) )
		{
			level lui::play_movie_with_timeout( level.end_game_video.name, "fullscreen", level.end_game_video.duration, true );
		}
	}
}

function nuked_endgame_think()
{
	level thread nuked_endgame_start();
	level thread nuked_endgame_reset();
	level thread nuked_test_movie();
}

function nuked_endgame_start()
{
	cameraStartArray = struct::get_array( "endgame_camera" );
	cameraStart = cameraStartArray[0];
	if( !isdefined( cameraStart ) )
	{
		cameraStart = SpawnStruct();
		cameraStart.origin = ( -200, -167, 15 );
		cameraStart.angles = ( 0, -81, 0 );
	}
	
	for ( ;; )
	{		
		camera = Spawn( "script_model", cameraStart.origin );
		camera.angles = cameraStart.angles;
		camera SetModel( "tag_origin" );

		level waittill( "nuked_end_sequence_start" );
		
		hiddenEntities = GetEntArray( "hide_end_game_sequence", "script_noteworthy" );
		foreach( hiddenEntity in hiddenEntities )
		{
			hiddenEntity hide();
		}
		
		clientfield::set( "nuketown_endgame", 1 );
		
		/* SET UP CAMERA */
		players = GetPlayers();
		foreach ( player in players )
		{
			player CameraSetPosition( camera );
			player CameraSetLookAt();
			player CameraActivate( true );	
			
			/* OVERRIDE ENDGAME DOF */
			player setDepthOfField( 0, 128, 7000, 10000, 6, 1.8 );			
		}
		
		wait( 2 );
		
		exploder::exploder( "nuketown_derez_explosion" );
		level thread run_scene( "p7_fxanim_mp_nukex_derez_bridge_bundle" );
		level thread run_scene( "p7_fxanim_mp_nukex_end_derezzing_tree_bundle" );
	}
}

function nuked_endgame_reset()
{
	for ( ;; )
	{	
		level waittill( "nuked_end_sequence_reset" );
		
		hiddenEntities = GetEntArray( "hide_end_game_sequence", "script_noteworthy" );
		foreach( hiddenEntity in hiddenEntities )
		{
			hiddenEntity show();
		}
		
		clientfield::set( "nuketown_endgame", 0 );
		
		exploder::stop_exploder( "nuketown_derez_explosion" );
		level thread init_scene( "p7_fxanim_mp_nukex_derez_bridge_bundle" );
		level thread init_scene( "p7_fxanim_mp_nukex_end_derezzing_tree_bundle" );
	}
}


function run_scene( str_scene )
{
	b_found = false;
	str_mode = ToLower( GetDvarString( "scene_menu_mode", "default" ) );
	a_scenes = struct::get_array( str_scene, "scriptbundlename" );
	foreach ( s_instance in a_scenes )
	{
		if ( isdefined( s_instance ) )
		{
			if ( !IsInArray( a_scenes, s_instance ) )
			{
				b_found = true;
				s_instance thread scene::play( undefined, undefined, undefined, true, undefined, str_mode );
				
			}
		}
	}
	
	if ( isdefined( level.active_scenes[ str_scene ] ) )
	{
		foreach ( s_instance in level.active_scenes[ str_scene ] )
		{
			b_found = true;
			s_instance thread scene::play( str_scene, undefined, undefined, true, undefined, str_mode );
		}
	}
}

function init_scene( str_scene )
{
	str_mode = ToLower( GetDvarString( "scene_menu_mode", "default" ) );
	b_found = false;
	a_scenes = struct::get_array( str_scene, "scriptbundlename" );
	foreach ( s_instance in a_scenes )
	{
		if ( isdefined( s_instance ) )
		{
			b_found = true;
			s_instance thread scene::init( undefined, undefined, undefined, true );
		}
	}
	
	if ( !b_found )
	{
		level.scene_test_struct thread scene::init( str_scene, undefined, undefined, true );
	}
}

function nuked_mannequin_init()
{
	keep_count = 28;
	level.mannequin_count = 0;

	destructibles = GetEntArray( "destructible", "targetname" );
	mannequins = nuked_mannequin_filter( destructibles );

	if ( mannequins.size <= 0 )
	{
		return;
	}

	ArrayRemoveValue( mannequins, undefined );
	alreadyRemoved = 0;
	for ( i = 0; i < mannequins.size; i++ )
	{
		if ( "p7_dest_ntx_mannequin_female_04_purple_ddef" == mannequins[i].destructibledef )
		{
			collision = GetEnt( mannequins[i].target, "targetname" );
			assert( IsDefined( collision ) );
	
			collision delete();
			mannequins[i] delete();
			level.mannequin_count--;
			alreadyRemoved++;
		}
		
		if ( !isdefined( mannequins[i] ) )
			continue;
	
		assert( IsDefined( mannequins[i].target ) );
		
		// Per mscronce - we never want the mannequins below to spawn in those modes as they interfere
		if( ( level.gameType == "dem" ) || ( level.gameType == "dom" ) ) 
		{
			if( mannequins[i].target == "pf1160_auto1" || mannequins[i].target == "pf1179_auto1" )
			{
				collision = GetEnt( mannequins[i].target, "targetname" );
				assert( IsDefined( collision ) );
		
				collision delete();
				mannequins[i] delete();
				level.mannequin_count--;
				alreadyRemoved++;
			}
		}
	}
	level.mannequin_count = mannequins.size;
	
	remove_count = mannequins.size - keep_count - alreadyRemoved;
	remove_count = math::clamp( remove_count, 0, remove_count );

	mannequins = array::randomize( mannequins );

	for ( i = 0; i < mannequins.size; i++ )
	{
		if ( !isdefined( mannequins[i] ) )
			continue;
		
		assert( IsDefined( mannequins[i].target ) );

		if ( i < remove_count   )
		{
			collision = GetEnt( mannequins[i].target, "targetname" );
			assert( IsDefined( collision ) );
	
			collision delete();
			mannequins[i] delete();
			level.mannequin_count--;
		}
		else
		{
			mannequins[i] DisconnectPaths();
		}
	}
	ArrayRemoveValue( mannequins, undefined );
	
	level.mannequins = mannequins;

	level waittill( "prematch_over" );
	level.mannequin_time = GetTime();
	
	debug_mannequin_init();
	
	if ( GetDvarInt( "nuketown_mannequin", 0 ) )
	{
		level thread _mannequin_constant_spawn( false );
	}
}

function debug_mannequin_init()
{
	level._mannequin_locations = [];
	level._mannequin_angles = [];
	
	destructibles = GetEntArray( "destructible", "targetname" );
	mannequins = nuked_mannequin_filter( destructibles );
	
	foreach( mannequin in mannequins )
	{
		level._mannequin_locations[ level._mannequin_locations.size ] = mannequin.origin;
		level._mannequin_angles[ level._mannequin_angles.size ] = mannequin.angles;
	}
	
	/#
	mapname = GetDvarString( "mapname" );
	
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug Mannequin/Spawn AI Mannequins V1\" \"set level_notify mannequin_force_spawn_v1 \"\n" );
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug Mannequin/Spawn AI Mannequins V2\" \"set level_notify mannequin_force_spawn_v2 \"\n" );
	AddDebugCommand( "devgui_cmd \"|" + mapname + "|/Debug Mannequin/Delete AI Mannequins\" \"set level_notify mannequin_force_cleanup \"\n" );
	
	level thread debug_mannequin_spawn_v1();
	level thread debug_mannequin_spawn_v2();
	level thread debug_mannequin_cleanup();
	#/
}

function private _mannequin_delete_destructibles()
{
	destructibles = GetEntArray( "destructible", "targetname" );
	mannequins = nuked_mannequin_filter( destructibles );
	
	foreach ( mannequin in mannequins )
	{
		mannequin ConnectPaths();
		
		collision = GetEnt( mannequin.target, "targetname" );
		
		collision Delete();
		mannequin Delete();
	}
}

function private _mannequin_force_cleanup()
{
	level notify ( "mannequin_ended" );
	
	mannequins = GetAIArchetypeArray( "mannequin" );
			
	foreach( mannequin in mannequins )
	{
		mannequin Kill();
	}
}

function private _mannequin_watch_end_spawn()
{
	level notify ( "_mannequin_watch_end_spawn" );
	level endon ( "_mannequin_watch_end_spawn" );
	while( 1 )
	{
		if( !mannequin_should_spawn() )
		{
			_mannequin_force_cleanup();
			return;
		}

		wait .05;
	}
}

function private _mannequin_force_spawn( weepingAngel )
{
	level endon ( "mannequin_ended" );
	level thread _mannequin_watch_end_spawn();
	
	if ( IsDefined( level._mannequin_locations ) )
	{
		_mannequin_delete_destructibles();
		
		for ( index = 0; index < level._mannequin_locations.size; index++ )
		{
			origin = level._mannequin_locations[ index ];
			angles = level._mannequin_angles[ index ];
			gender = ( ( RandomInt( 2 ) ) ? "male" : "female" );

			mannequin = NuketownMannequin::SpawnMannequin( origin, angles, gender, undefined, weepingAngel );

			wait .05;
		}
	}
	
	if( weepingAngel )
	{
		level thread NuketownMannequin::watch_player_looking();
	}
}

function private _mannequin_constant_spawn( weepingAngel )
{
	level endon ( "mannequin_ended" );
	
	_mannequin_force_spawn( weepingAngel );
	
	while ( true && IsDefined( level._mannequin_locations ) )
	{
		mannequins = GetAIArchetypeArray( "mannequin" );
	
		if ( mannequins.size < level._mannequin_locations.size )
		{
			index = RandomInt( level._mannequin_locations.size );
			
			origin = level._mannequin_locations[ index ];
			angles = level._mannequin_angles[ index ];
			gender = ( ( RandomInt( 2 ) ) ? "male" : "female" );

			mannequin = NuketownMannequin::SpawnMannequin( origin, angles, gender, undefined, weepingAngel );
		}
		
		wait 0.1;
	}
}

function private debug_mannequin_spawn_v1()
{
	/#
	while ( true )
	{
		level waittill ( "mannequin_force_spawn_v1" );

		_mannequin_force_cleanup();
		_mannequin_force_spawn( false );
	}
	#/
}

function private debug_mannequin_spawn_v2()
{
	/#
	while ( true )
	{
		level waittill ( "mannequin_force_spawn_v2" );

		_mannequin_force_cleanup();
		_mannequin_force_spawn( true );
	}
	#/
}

function private debug_mannequin_cleanup()
{
	/#
	while ( true )
	{
		level waittill ( "mannequin_force_cleanup" );

		_mannequin_force_cleanup();
	}
	#/
}

function nuked_mannequin_filter( destructibles )
{
	mannequins = [];

	for ( i = 0; i < destructibles.size; i++ )
	{
		destructible = destructibles[i];

		if ( IsSubStr( destructible.destructibledef, "male" ) )
		{
				mannequins[ mannequins.size ] = destructible;
				level.mannequin_count++;
			}
		}

	return mannequins;
}

function mannequin_headless( notifyType, attacker, weapon )
{
	if ( GetTime() < level.mannequin_time + GetDvarInt( "mannequin_timelimit", 120 ) * 1000 )
	{
		level.headless_mannequin_count++;
		if ( level.headless_mannequin_count == GetDvarInt( "mannequin_headless_count", 28 ) )
		{
			level thread mannequin_activate_headless();
		}
	}
}

function mannequin_valid_gamemode()
{
	if ( !GetDvarInt( "nuketown_mannequin", 1 ) )
	{
		return false;
	}
	
	if( SessionModeIsOnlineGame() && !SessionModeIsPrivateOnlineGame() )
	{
		return false;
	}
	
	if ( util::IsPropHuntGametype() )
	{
		return false;
	}
	
	return true;
}

function mannequin_should_spawn()
{
	players = GetPlayers();
	
	if( players.size > 12 )
	{
		return false;
	}
	
	return true;
}

function mannequin_activate_headless()
{
	wait( 1 );	// let the last destructible blow up
	
	if( !mannequin_valid_gamemode() )
	{
		return;
	}
	
	level thread _mannequin_constant_spawn( false );
}

function mannequin_left_arm_lower( notifyType, attacker, weapon )
{
	//mannequin_limbless( notifyType, attacker, weapon );
}

function mannequin_left_arm_upper( notifyType, attacker, weapon )
{
	mannequin_limbless( notifyType, attacker, weapon );
}

function mannequin_right_arm_lower( notifyType, attacker, weapon )
{
	//mannequin_limbless( notifyType, attacker, weapon );
}

function mannequin_right_arm_upper( notifyType, attacker, weapon )
{
	mannequin_limbless( notifyType, attacker, weapon );
}

function mannequin_limbless( notifyType, attacker, weapon )
{
	if ( GetTime() < level.mannequin_time + GetDvarInt( "mannequin_timelimit", 120 ) * 1000 )
	{
		level.limbless_mannequin_count++;
		if ( level.limbless_mannequin_count == GetDvarInt( "mannequin_limbless_count", 28 * 2 ) )
		{
			level thread mannequin_activate_limbless();
		}
	}
}

function mannequin_activate_limbless()
{
	wait( 1 );	// let the last destructible blow up
	
	if( !mannequin_valid_gamemode() )
	{
		return;
	}
	
	level thread _mannequin_constant_spawn( true );
	//util::set_lighting_state( 3 );
}

// sjakatdar TU3 (11/12/2015) - Robot (G.I. Unit) gets stuck while wallrunning using following two traversal nodes.
// There is definitely a logic issue, which I will debug further, but disabling these nodes for now. Hopefully, the real fix
// will in checked in for TU4.
function tU3_disable_bad_robot_wallrun_nodes()
{
	// Disabling all wallrun end nodes, these cause GI Units to run off into space.
	nodes = GetNodesInRadius( (-765.225, 938.762, 7.377), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (-1158.760, 1070.650, 7.377), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (-926.372, -224.916, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (-1319.91, -93.028, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (918.81, -206.969, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (1313.93, -79.594, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (736.484, 925.845, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
	
	nodes = GetNodesInRadius( (1131.5, 1053.22, 7.376), 30, 0, 10, "End" );
	SetEnableNode( nodes[0], false );
}

function update_escort_robot_path( &pathArray )
{
	ArrayInsert( pathArray, ( 929, 626, -56.875 ), 10 ); // fixes escort robot chosing to path around the "Vehicle Diagnostics" room if the door is blocked
}
