We have upgraded to the latest version of MediaWiki and now support TLS1.2 and transcoding!
Please contact us via Discord or Twitter if you experience any problems.

Proto:Call of Duty 4: Modern Warfare (Windows)/Build 253/embassy.gsc

From The Cutting Room Floor
Jump to navigation Jump to search

This is a sub-page of Proto:Call of Duty 4: Modern Warfare (Windows)/Build 253.

/****************************************************************************
Level: 		Immediate Action (SAS Hostage Rescue)
Campaign: 	SAS
****************************************************************************/

#include maps\_utility;
#include maps\_anim;
#using_animtree("generic_human");

main()
{
	setExpFog(200, 13000, 209/255, 216/255, 222/255, 0);
	
 	//globals
 	level.maxfriendlies = 6;
	level.friendlywave_thread = ::putOnChain;
	level.followmax = 2;
	level.followmin = -1;
 	level.stopwatch = .5;											//Default time to complete objective, in minutes
	level.missionFailedQuote = &"EMBASSY_MISSION_FAILED_GENERIC";	//Generic failure message
	level.usetimer = true;	
	
	//script_origin used for all helicopter animations
	level.heliNode = getent("helicopter_origin_main", "targetname");
	level.passengers = 0;

	//Skip to vars
	//setdvar("debug_mode","1");
	//setdvar("start","");
	//setdvar("start","southoffices");
	//setdvar("start","northoffices");
	//setdvar("start","conferencehall");
	//setdvar("start","mezzanine");
	//setdvar("start","reception");
	//setdvar("start","libhall");
	//setdvar("start","end");
			
	level.debug_mode = false;		
	if ( getdvar("debug_mode") == "1" )
		level.debug_mode = true;
	
	setupPrecache();
	maps\embassy_fx::main();
	maps\_blackhawk::main("vehicle_blackhawk");
	maps\_load::main();
	maps\embassy_anim::main();
	level thread maps\embassy_amb::main();
	setupPlayer();
	setupCharacters();
	hideAll();
	level_think();
	
 	level thread debugMethod1();
 	level thread debugMethod2();
 	
 	//Open any doors that should be initially open
 	level thread open_all_doors_in_level();
 	
 	level thread battlechatter_off("allies");
	level thread battlechatter_off("axis");
	
 	//flags: objectives
 	flag_init("obj_insert_complete");
 	//flag_init("obj_window_breach_complete");
 	flag_init("obj_hostage_secure_office_1_complete");
 	flag_init("obj_nav_office_north_complete");
 	flag_init("obj_hostage_secure_office_2_complete");
  	flag_init("obj_hostage_secure_banquet_complete");
 	//flag_init("obj_banquet_hall_regroup_complete");
 	flag_init("obj_bravo_rv_complete");
 	flag_init("obj_reception_clear_complete");
 	flag_init("obj_skylight_breach_complete");
 	flag_init("obj_courtyard_cover_complete");
 	flag_init("obj_library_breach_complete");	
 	flag_init("obj_sniper_assault_complete");
 	flag_init("obj_final_boss_complete");
 	
 	//flags: navigation
 	
 	//Rooftop insertion
 	flag_init("rooftop_ai_is_ready");
 	flag_init("team_ready_to_rappel_to_roof");
 	flag_init("heli_fastrope_in_progress");
 	flag_init("helicopter_has_been_hit");
 	flag_init("player_landed_on_rooftop");
 	flag_init("rappel_point_reached");
 	flag_init("jack_has_reached_rappel_point");	
 	flag_init("gaz_has_reached_rappel_point");	
 	flag_init("jack_is_on_balcony");
 	flag_init("gaz_is_on_balcony");
 	flag_init("player_has_started_balcony_absail");
 	flag_init("window_frame_charges_placed");
 	flag_init("all_teams_start_initial_breach"); 	
 	flag_init("embassy_breached");
 	//South offices
 	flag_init("officeA_cleared");
 	flag_init("officeB1_breached");
 	flag_init("officeB1_cleared");
 	flag_init("human_shield_office_c_dead");
 	flag_init("officeD_breached");
 	flag_init("officeD_cleared");
  	flag_init("south_office_exit_reached");
  	flag_init("player_has_looked_at_south_office_door");
 	flag_init("player_has_looked_at_trig_lookat_hostage_evac_facadehall");
 	//North offices
 	flag_init("player_approaching_north_offices");
 	flag_init("player_has_looked_at_trig_lookat_sniper_sequence");
 	flag_init("officeF_breached");
 	flag_init("officeF_cleared");
 	flag_init("officeG_door_open");
 	flag_init("obj_balcony_flank_given");
 	flag_init("officeG_reached");
 	flag_init("office_H_cleared");
 	flag_init("flanking_balcony_office_reached");
 	flag_init("flanking_balcony_reached");
	flag_init("player_is_approaching_conf_hall_door");	
	flag_init("conf_hall_door_is_open");
	//Banquet hall	
	flag_init("nav_banquet_hall_complete");	
 	flag_init("banquet_reception_cleared");
 	flag_init("banquet_doors_barricaded");
 	flag_init("banquet_wall_first_explosive_planted");
 	flag_init("banquet_wall_second_explosive_planted");
 	flag_init("kitchen_door_breached");
 	//Drawing room and Reception
 	flag_init("stairwell_reached");
 	flag_init("drawaing_room_exit_breached");
 	flag_init("skylight_access_door_reached");
 	flag_init("skylight_rooftop_reached");
 	flag_init("all_guys_ready_to_rappel_at_skylight");	
 	flag_init("skylight_breach_command_given");
 	flag_init("courtyard_cover_navigate_complete");
 	flag_init("all_guys_ready_at_elevator");
 	flag_init("elevator_ready_to_be_pried_open");
 	flag_init("elevator_shaft_reached");
 	flag_init("elevator_rooftop_reached");
 	//Library
 	flag_init("library_foyer_reached");
	flag_init("player_approaching_foyer_sidedoor");
	flag_init("player_approaching_foyer_frontdoor");
 	flag_init("library_foyer_cleared");
 	flag_init("library_breach_objective_given");
 	flag_init("library_breached");
 	flag_init("library_final_humanshield_spawned");
 	flag_init("player_on_library_floor");
 	//Sniper
 	flag_init("jack_ready_by_roof_access");
 	flag_init("player_has_sniper_rifle");
 	flag_init("stairwell_ladder_reached");
 	flag_init("vent_entrance_reached");
 	flag_init("sniper_position_reached");
 	flag_init("sniper_order_given");
 	flag_init ("player_killed_correct_sniper");
 		  	
 	//flags: other
 	flag_init("timer_expired");
 	  
 	//skip to a point in the level
 	skipToString = getdvar("start");
 	if ( (skipToString == "start") || (skipToString == "") )
 	{
 		AA_level_start_init();
 	}
 	else
 	{
 		level thread skipWarp(skipToString); 		
 	}
 		 
}

/****************************************************/
/**************** LEVEL START (ROOFTOP) FUNCTIONS****/
/****************************************************/
AA_level_start_init()
{
	level thread maps\_introscreen::introscreen_delay(&"EMBASSY_TITLE", &"EMBASSY_INFO", &"EMBASSY_PLACE", &"EMBASSY_DATE", 2, 2, 1);
	
	//level thread ambient_rooftop_negotiator_conversation();
	level thread rooftop_character_setup();
	level thread body_dump();	
	level thread helicopter_ride();	
	level thread heli_rappel();
	level thread fastrope_heli_think();
	//level thread rooftop_hostile();
	level thread trigger_roof_reach();
	level thread trigger_balcony_1();
	level thread trigger_balcony_2();
	level thread trigger_balcony_3();
	level thread balcony_rappel_gaz();
	level thread balcony_rappel_jack();
	level thread trigger_use_fastrope_roof_think();
	level thread group_absail_sequence();
	level thread setup_enemies_office_a();
}

rooftop_character_setup()
{
	//setup chopper guys
	level.aIntro_chopper_dudes = level spawnGroup(getEntArray("friendlies_heli_intro", "targetname"));
	level.pilot = getDudeFromArray(level.aIntro_chopper_dudes, "heli_intro_pilot");
	level.pilot.animname = "pilot";
	level.copilot = getDudeFromArray(level.aIntro_chopper_dudes, "heli_intro_copilot");
	level.copilot.animname = "copilot";
		
	level.gammaSquad = getentarray("gammaSquad", "targetname");
	level.zetaSquad = getentarray("zetaSquad", "targetname"); 
	
	//add other chopper dudes to other rappelling squads
	aGammaDudes = getDudesFromArray(level.aIntro_chopper_dudes, "gammaSquad");
	aZetaDudes = getDudesFromArray(level.aIntro_chopper_dudes, "zetaSquad");
	for(i=0;i<aGammaDudes.size;i++)
		level.gammaSquad = array_add(level.gammaSquad, aGammaDudes[i]);
	for(i=0;i<aZetaDudes.size;i++)
		level.zetaSquad = array_add(level.zetaSquad, aZetaDudes[i]);	
	
	array_thread(level.gammaSquad, ::invulnerable,true);
	array_thread(level.zetaSquad, ::invulnerable,true);

	flag_set("rooftop_ai_is_ready");
}




body_dump()
{
	wait(1.5);
	//sierra
	//"Body is being..they are dumping the body out of the front window."
	level thread dialogue_radio_thread ("embassy_sierra_bodybeingdumped");	
	
	wait(2.5);

	//crowd
	//"<sound of crowd screaming and sobbing>"
	level thread dialogue_radio_thread ("embassy_crowd_screams");	
	
	wait(1);
	//jack
	//"Bloody christ, they've killed a hostage"
	level.jack thread queue_anim("embassy_jack_theykilledahostage");	

	wait(2);
	//cmd
	//"Roger, Sierra One. Hold your fire. We have clearance to execute IA. All call signs, I have control. Commence your run in."
	dialogue_radio_thread("embassy_cmd_clearencetoexecute");	
				
	//gaz
	//"Right, that's in then. Stand to, lads. We?ll be assaulting the middle floor."
	//level.gaz dialogue_thread("embassy_gaz_herewegolads");	
	
	wait(1);
	//gaz
	//Alpha One going dark. 2 seconds.	
	level.gaz thread queue_anim("embassy_gaz_goingdark");	
	
	//wait(1);
	//gaz
	//"Andy, you're going to be first man into every room. Take the flashbangs. You'll be the one making noise."
	//level.gaz thread dialogue_thread ("embassy_gaz_helibreachinstruct1");	

	//sierra
	//"I may have visual on X Ray One."
	//dialogue_radio_thread ("embassy_sierra_visualofxrayone");	
	
	//sierra
	//"Confirmed. That was X Ray One at the window. Male...approximately 6?2...fifteen stone..."
	//dialogue_radio_thread("embassy_sierra_thatwasxray1");		
}

helicopter_ride()
{
	flag_wait("rooftop_ai_is_ready");
	
	//setup helicopter
	eHeli_intro = blackhawk_spawn("heli_intro_start");
	//eHeli_intro = getent("heli_intro", "targetname");
	
	eHeli_intro useAnimTree(#animtree);
	eHeli_intro.animname = "blackhawk";			
	vStartingPosition = getstartorigin( level.heliNode.origin, level.heliNode.angles, level.scr_anim["blackhawk"]["heli_intro_start"]);
	aStartingAngles = getstartangles( level.heliNode.origin, level.heliNode.angles, level.scr_anim["blackhawk"]["heli_intro_start"]);
	eHeli_intro.origin = vStartingPosition;
	eHeli_intro.angles = aStartingAngles;
	
	
	level.heliNode thread anim_loop_solo (eHeli_intro, "heli_intro_start_loop", undefined, "stop_idle");
	
	//put player in chopper
	
	//vPlayerSeat = eHeli_intro getTagOrigin("tag_guy7");
	//vPlayerAngles = eHeli_intro getTagAngles("tag_guy7");
	//level.player setorigin(vPlayerSeat);
	//level.player setplayerangles(vPlayerAngles);
//	level.player playerlinktodelta( <linkto entity>, <tag>, <viewpercentag fraction>, <right arc>, <left arc>, <top arc>, <bottom arc> )
	level.player playerlinktodelta(eHeli_intro, "tag_guy7", 1, 55, 55, 5, 28);
	wait .1;
	level.player setplayerangles((30, 45, 0));	
	//level.player setorigin(level.player.origin + (0,0,100));


	level thread playerWeaponTempRemove();	
	level.player allowLean(false);
	level.player allowStand(false);
	
	//put guys on tags
	level.gaz thread putDudeOnHeliTag(eHeli_intro, "tag_detach");
	level.jack thread putDudeOnHeliTag(eHeli_intro, "tag_detach");
	for(i=0;i<level.aIntro_chopper_dudes.size;i++)
		level.aIntro_chopper_dudes[i] thread putDudeOnHeliTag(eHeli_intro, "tag_detach");
		
	
	wait(4);	
	
	//helicopter move in
	level.heliNode notify ("stop_idle");	
	level.heliNode thread anim_single_solo (eHeli_intro, "heli_intro_start");
	
	//wait till heli reaches roof, then hover	
	eHeli_intro waittillmatch("single anim", "end");
	
	flag_set("team_ready_to_rappel_to_roof");
	
	level.heliNode thread anim_loop_solo (eHeli_intro, "heli_intro_idle", undefined, "stop_idle");
	
	flag_wait("player_landed_on_rooftop");
	
	level.heliNode notify ("stop_idle");
	level.heliNode anim_single_solo (eHeli_intro, "heli_intro_end");

	eHeli_intro delete();
}

putDudeOnHeliTag(eHeli, sTagName)
{

	org = eHeli getTagOrigin(sTagName);
	angles = eHeli getTagangles(sTagName);
	self teleport( org, angles );
	self linkto(eHeli, sTagName, (0,0,0), (0,0,0));
	
	//give different animname if it's the pilot or copilot
	if (!isdefined(self.animname))
	{
		level.passengers ++;
		self.animname = "passenger" + level.passengers;	
	}
		
	eHeli thread anim_loop_solo(self, "heli_seat_idle", sTagName, "stop_idle");
	
	self waittill ("rappelling");
	
	eHeli notify ("stop_idle");
	
}	

heli_rappel()
{
	flag_wait("team_ready_to_rappel_to_roof");
	//gaz
	//"Command. This is Alpha One at the insertion point."
	//level.gaz dialogue_thread("embassy_gaz_atinsertionpoint");
	
	autosave_by_name ("heli ride complete");
	
	//cmd
	//All call signs standby. Standby...Go! Go! Go!"	
	dialogue_radio_thread("embassy_cmd_insertiongo");

	level thread obj_insert();
	
	//gaz
	//"Go! Get those ropes out!"
	//level.gaz thread dialogue_thread("embassy_gaz_getropesout");
	
	level notify ("team_ready_to_rappel_from_heli");
	
	flag_set("heli_fastrope_in_progress");	
}

fastrope_heli_think()
{
	level waittill ("team_ready_to_rappel_from_heli");
	
	//squad rappels
	level.aIntro_chopper_dudes = array_add(level.aIntro_chopper_dudes, level.gaz);
	level.aIntro_chopper_dudes = array_add(level.aIntro_chopper_dudes, level.jack);

	for(i=0;i<level.aIntro_chopper_dudes.size;i++)
		level.aIntro_chopper_dudes[i] thread heli_rappel_think();

	wait(1.4);
		
	//show fastrope and USE trigger
	trigger_use_fastrope = getent("trigger_use_fastrope", "targetname");
	trigger_use_fastrope show();
	trigger_use_fastrope trigger_on();
	trigger_use_fastrope setHintString( &"EMBASSY_HINTSTR_FASTROPE");
	
	//wait until hits "use" key
	trigger_use_fastrope waittill("trigger");
	trigger_use_fastrope trigger_off();
	
	level.player unlink();		
	eWarp = getent("origin_fastrope_start", "targetname");
	level.player setorigin (eWarp.origin);
	level.player setplayerangles (eWarp.angles);
	level.player linkto(eWarp);
	
	wait(.5);
	
	fMoveTime = 3.8;
	eEndRappelPoint = getent("origin_fastrope_end", "targetname");
	eWarp moveto( eEndRappelPoint.origin, fMoveTime, .5, .5 );
	wait (fMoveTime);
	
	level.player unlink();
	level.player notify ("restore_player_weapons");
	level.player allowLean(true);
	level.player allowStand(true);	
	
}

heli_rappel_think()
{
	self endon ("death");
	
	wait(randomfloatrange(.5,4.5));
	
	if (!isdefined (self))
		return;
		
	if(!isalive(self))
		return;	
	
	//stop looping idle anim and fastrope in
	self unlink();
	self notify  ("rappelling");
	
	self set_animname ("guy");	
	//self thread anim_loop_solo(self, "fastrope_loop", undefined, "stop_idle");

	//wait(3);

	//self notify ("stop_idle");
	
	//self anim_single_solo (self, "fastrope_land");	 
	self anim_single_solo (self, "fastrope_full");	 
	
	
	
	self reset_animname();	
}

ambient_rooftop_negotiator_conversation()
{
	flag_wait("helicopter_has_been_hit");
	
	wait(3);
	
	//cmd
	//"All call signs, keep it quiet until insertion is complete."	
	dialogue_radio_thread("embassy_cmd_keepitquiet");

	//neg
	//"We don?t want a bloodbath here, Salim, so let?s...let?s just talk about"	
	dialogue_radio_thread("embassy_neg_nobloodbath");	

	//mbg
	//"What is that sound? <foreign language telling other terrorist to go investigate>"	
	dialogue_radio_thread("embassy_mbg_whatisthatsound");	

	//neg
	//"Now...Salim...tell me exactly what you need...we do not want any more hostages to be harmed"
	dialogue_radio_thread("embassy_neg_tellmewhatyouneed");	

	//mbg
	//"There is...we hear sound coming from the roof..."	
	dialogue_radio_thread("embassy_mbg_soundsonroof");	

	//neg
	//"Salim...there is nothing on the rooftop. Salim...(off microphone) blast, we?ve lost radio contact"	
	dialogue_radio_thread("embassy_neg_nosoundsonroof");	
}


trigger_roof_reach()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trigger_roof_reach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//gaz
	//"Let's move. They're getting our ropes setup at the last balcony."
	level.gaz thread queue_anim("embassy_gaz_gettoropes");
	
	//Force gaz and jack to fastrope area near balcony
	flag_set("player_landed_on_rooftop");
		
	wait(3);
	
	//cmd
	//"This is command. Alpha One, your LOE is balcony three-three."
	dialogue_radio_thread("embassy_cmd_locationofentry");	
	
}

balcony_rappel_gaz()
{
	flag_wait("player_landed_on_rooftop");
	
	// Have guy go to rappel point and wait
	level.gaz goToNode("nodes_squad_roof_gaz");

	level.gaz waittill ("goal");
	flag_set ("gaz_has_reached_rappel_point");	
	
	// Wait till player starts rappeling, then have friendly go down
	flag_wait("player_has_started_balcony_absail");

	
	level.gaz thread rappel_balcony("origin_rappel_balcony_3a");
	
	//gaz
	//"Remember, weapons hold until my signal. No firing until we've breached the building."
	level.gaz thread queue_anim("embassy_gaz_weaponsholdtillbreach");	
	flag_set("gaz_is_on_balcony");
}

balcony_rappel_jack()
{
	flag_wait("player_landed_on_rooftop");
	
	// Have guy go to rappel point and wait
	level.jack goToNode("nodes_squad_roof_jack");

	level.jack waittill ("goal");
	flag_set ("jack_has_reached_rappel_point");	
	
	// Wait till player starts rappeling, then have friendly go down
	flag_wait("player_has_started_balcony_absail");
	
	wait(.5);
	level.jack thread rappel_balcony("origin_rappel_balcony_3b");
	
	level.jack waittill ("balcony_rappel_finished");
	flag_set("jack_is_on_balcony");
}

trigger_balcony_1()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trigger_balcony_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//play a random line of reminder dialogue
	
	//frnd
	//"You're with Gaz's team, you're at the last set of ropes to the south."	
	guy = get_closest_ally();
	if (isdefined(guy))
		guy thread queue_anim("embassy_frnd_gettoropes1");	
}

trigger_balcony_2()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trigger_balcony_2", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//play a random line of reminder dialogue
	
	//frnd
	//"Get back with your team. Last set of ropes to the south. Get into position, mate, the clock's ticking!"
	guy = get_closest_ally();
	if (isdefined(guy))
		guy thread queue_anim("embassy_frnd_gettoropes2");	
}

trigger_balcony_3()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trigger_balcony_3", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	flag_set("rappel_point_reached");
	
	//jack
	//"Grab the rope, Andy. We'll absail down to the balcony below."	
	level.jack thread queue_anim("embassy_jack_grabtherope1");	
		
	// Remind the player to grab the rope if he hasn't gone yet
	wait(8);	
	
	//jack
	//"Get on the bloody rope Andy, we haven't much time."
	if (!flag("player_has_started_balcony_absail"))
		level.jack thread queue_anim("embassy_jack_grabtherope2");		
}


setup_enemies_office_a()
{
	flag_wait("rappel_point_reached");
	//spawn hostiles in office A
	level.spawned_hostiles_office_a = level spawnGroup(getEntArray("hostiles_office_a", "targetname"));
	array_thread(level.spawned_hostiles_office_a, ::setCQBbehavior, true);	
	
	level.spawned_hostages_office_a = level spawnGroup(getEntArray("hostages_office_a", "targetname"));
		
	//Have everyone ignore eachother
	ignoreEverybody(true);
}


trigger_use_fastrope_roof_think()
{
	trigger_use_fastrope_roof = getEnt( "trigger_use_fastrope_roof", "targetname" ); 
	trigger_use_fastrope_roof show();
	trigger_use_fastrope_roof trigger_on();
	trigger_use_fastrope_roof setHintString( &"EMBASSY_HINTSTR_FASTROPE");

	//wait until hits "use" key
	trigger_use_fastrope_roof waittill("trigger");
	trigger_use_fastrope_roof trigger_off();
	
	flag_set("player_has_started_balcony_absail");	
	
	//Take player weapons away
	level thread playerWeaponTempRemove();
	
	eWarp = getent("origin_rappel_balcony_start", "targetname");
	level.player setorigin (eWarp.origin);
	level.player setplayerangles (eWarp.angles);
	level.player linkto(eWarp);
	
	wait(.5);
	
	fMoveTime = 1.8;
	eEndRappelPoint = getent("origin_rappel_balcony_end", "targetname");
	eWarp moveto( eEndRappelPoint.origin, fMoveTime, .5, .5 );
	wait (fMoveTime);
	
	level.player unlink();
	level.player notify ("restore_player_weapons");

}

group_absail_sequence()
{
	flag_wait("player_has_started_balcony_absail");
	
	level thread AA_southOffices_init();
	
	//Make 3 guys from Gamma and 3 guys from Zeta rappel
	level thread group_rappel(level.gammasquad, "origin_rappel_balcony_1_");
	level thread group_rappel(level.zetasquad, "origin_rappel_balcony_2_");
}

group_rappel(aArrayOfDudes, sPrefixOfOrigin)
{
	// loop through 3 times
	for(i=0;i<3;i++)
	{
		//find the origin they will be rappeling from
		sRappelOrigin = sPrefixOfOrigin + i;
				
		wait (randomfloatrange(.25,1.5));
		
		assertEx(isdefined(aArrayOfDudes[i]), "Rappeling guy doesn't exist.");
		
		aArrayOfDudes[i] thread rappel_balcony(sRappelOrigin);
		
	}
}


/****************************************************/
/**************** SOUTH OFFICES FUNCTIONS**************/
/****************************************************/
AA_southOffices_init()
{
	level thread trig_enter_balcony();
	level thread frnd_plants_explosives();
	level thread gaz_takes_cover();
	level thread all_teams_breach_embassy();
	level thread officeA_fight_start();
	level thread trig_enter_officeA();
	level thread trig_exit_officeA();
	level thread trig_enter_officeB1();
	level thread trig_enter_officeB2();
	level thread trig_officeC_approach();
	level thread trig_office_south_exit_approach();	
	level thread proceed_to_north_offices();	
}

trig_enter_balcony()
{
	
	//wait for trigger, then disable it
	trigger = getEnt( "trig_enter_balcony", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//level.gaz dialogue_thread("embassy_gaz_framechargewindow");	
	
	//level thread obj_window_breach();
	
	flag_wait("window_frame_charges_placed");
		
	dialogue_radio_thread("embassy_cmd_executeia");	
	
	//gaz
	//"Blow it!"
	level.gaz queue_anim("embassy_gaz_blowwindow");	
	
	
	//level thread window_breach_think();	
	//blow the window and update objectives
	level thread window_breach_explosion();
	//flag_set ("obj_window_breach_complete");
	
	flag_set("obj_insert_complete");
	autosave_by_name ("insertion complete");
	wait(1);
	
	flag_set("all_teams_start_initial_breach");
	
	//delete all guys left behind on roof
	level thread npcDelete("volume_rooftop_offices_south", "all");	
	
	wait(1);
	
	level thread obj_hostage_secure_office_1();	
}

gaz_takes_cover()
{
	flag_wait("gaz_is_on_balcony");
	//Gaz goes to other nodes away from window
	
	level.gaz thread goToNode("balcony_cover_1");
}
frnd_plants_explosives()
{
	level endon ("embassy_breached");
	
	flag_wait("jack_is_on_balcony");
	
	eOrg = getent("origin_windowbreach_officeA_2", "targetname");
	level.jack thread set_explosives(eOrg, undefined, false, 1);
	level.jack waittill ("explosives_set");
	
//	eOrg = getent("origin_windowbreach_officeA_1", "targetname");
//	level.jack thread set_explosives(eOrg, undefined, false, 1);
//	level.jack waittill ("explosives_set");	
			
	level.jack thread goToNode("balcony_cover_2");
	
	flag_set("window_frame_charges_placed");
	
	//warn player to get the hell away from windows
	iprintlnbold (&"EMBASSY_EXPLOSIVES_PLANTED");
//	eTrig_expl_danger_balcony = getent("trig_expl_danger_balcony", "targetname");
//	while (true)
//	{
//		wait(0.05);
//		if ( level.player isTouching(eTrig_expl_danger_balcony) )
//		{
//			
//		}	
//		else
//			iprintlnbold ("");
//	}	
}


all_teams_breach_embassy()
{
	flag_wait("all_teams_start_initial_breach");
	
	//Just have dudes enter, then delete them, will respawn later
	
	level thread blow_window("officeC");
	
	array_thread(level.zetasquad, ::goToNodeAndDelete, "node_volume_officeC");
	wait(1);
	level thread blow_window("officeD");	
	array_thread(level.gammasquad, ::goToNodeAndDelete, "node_volume_officeD");
	
}

blow_window(sRoomName)
{
	aWindowExploder = getentarray("exploder_window_" + sRoomName, "targetname");	
	assert(isdefined(aWindowExploder));
	iExploderNumber = aWindowExploder[0].script_exploder;
	
	maps\_utility::exploder(iExploderNumber);	
	aWindowExploder[0] thread play_sound_in_space("rocket_explode_default");		
}

//window_breach_think()
//{
//	//setup hint trigger 	
//	trig_use_window_breach = getent("trig_use_window_breach", "targetname");
//	trig_use_window_breach trigger_on();
//	trig_use_window_breach setHintString( &"EMBASSY_HINTSTR_DETONATE");
//	trig_use_window_breach usetriggerrequirelookat();
//
//	//wait until hits "use" key
//	trig_use_window_breach waittill("trigger");
//	trig_use_window_breach trigger_off();
//
//	//blow the window and update objectives
//	level thread window_breach_explosion();
//	flag_set ("obj_window_breach_complete");
//
//}

window_breach_explosion()
{
	//spawn and kill a couple dudes by the windows
	//level spawnGroup(getEntArray("hostiles_office_a_dead", "targetname"));
	level thread blow_window("officeA");
	earthquake (0.6, 2, level.player.origin, 1000);
	level notify ("embassy_breached");
	flag_set ("embassy_breached");
}

trig_enter_officeA()
{
	//wait for trigger, then disable it
	trigger = getEnt("trig_enter_officeA", "targetname"); trigger waittill ( "trigger" ); trigger trigger_off();
	
}

officeA_fight_start()
{

	flag_wait ("embassy_breached");
	//flag_wait ("obj_window_breach_complete");
	
	//remove clip brush to allow entry by mantle
	blockerEnable(getent("blocker_balcony_entry", "targetname"), 0);
	
	//Gaz
	//Weapons free!
	level.gaz thread queue_anim("embassy_gaz_weaponsfree");	
	
	ignoreEverybody(false);
	
	//Have enemies get surprised
	aHostiles = getAIarrayTouchingVolume("axis", "volume_officeA");
	array_thread( aHostiles, ::enemy_surprised );

	
	//wait till all hostiles dead
	waittill_aigroupcleared("hostiles_office_a");
	level.gaz thread queue_anim("embassy_gaz_allclearmoveon3");
	
	flag_set("officeA_cleared");

	//kill all the friendlies in office C & D...just to make sure
	level thread npcDelete("volume_officeC", "allies");
	level thread npcDelete("volume_officeD", "allies");	
	
	//spawn a guy in the hallway and have him chill
	level.friendly_window_southoffices01_buddy = level spawnDude(getEnt("friendly_window_southoffices01_buddy", "script_noteworthy"));

	//Hostiles in next office
	spawned_hostiles_office_b = level spawnGroup(getEntArray("hostiles_office_b", "targetname"));
	hostages_office_b = level spawnGroup(getEntArray("hostages_office_b", "targetname"));
	array_thread(spawned_hostiles_office_b, ::setCQBbehavior, true);
	
	//open door to hallway
	level.gaz thread door_NPC_open("door_officeA", 1, 2);
	level.jack thread goToNode("node_door_officeA");
	
	level.gaz waittill("door_kicked");
	level.jack thread goToNode("friendlychain_exterior_officeB1");

	//frnd
	//"Let's move it along gentlemen. Take this office back here."
	level.friendly_window_southoffices01_buddy.animname = "guy";
	level.friendly_window_southoffices01_buddy thread queue_anim("embassy_frnd_letsmoveoffices");
	
	level.gaz waittill ("door_has_been_opened");	
	

	
	level.jack notify ("goal");	
	//Setup breach of the next room
	aFriendlies = [];
	aFriendlies[0] = level.gaz;
	aFriendlies[1] = level.jack;
	

		
	level thread breach_room("officeB1", aFriendlies, 0);
}

trig_exit_officeA()
{
	//wait for trigger, then disable it
	trigger = getEnt("trig_exit_officeA", "targetname"); trigger waittill ( "trigger" ); trigger trigger_off();

	//Guy crashes through window
	friendly_window_southoffices01 = spawnDude(getEnt("friendly_window_southoffices01", "script_noteworthy"));
	friendly_window_southoffices01 thread window_rappel_smash("window_southoffices01");	
	
	friendly_window_southoffices01 waittill ("window_rappel_finished");
	
	//have the two guys go into office A to evac the hostages
	aFriendlies = [];
	aFriendlies[0] = level.friendly_window_southoffices01_buddy;
	aFriendlies[1] = friendly_window_southoffices01;
	level thread hostage_evac("officeA", aFriendlies);
}


officeB1_fight()	//Called from the global breach function
{	
	//wait for all hostiles dead
	waittill_aigroupcleared("hostiles_office_b");	
	
	level.gaz thread queue_anim("embassy_gaz_allclearmoveon1");
	
	flag_set("officeB1_cleared");
}

trig_enter_officeB1()
{
	//wait for trigger, then disable it
	trigger = getEnt("trig_enter_officeB1", "targetname"); trigger waittill ( "trigger" ); trigger trigger_off();
}

trig_enter_officeB2()
{
	//wait for trigger, then disable it
	trigger = getEnt("trig_enter_officeB2", "targetname"); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//spawn dude in hallway who will eventually block the way past the human shield
	level.eFriendly_soutoffices_blocker = spawnDude(getent("friendly_soutoffices_blocker", "targetname"));
	level.eFriendly_soutoffices_blocker invulnerable(true);
	level.eFriendly_soutoffices_blocker thread NPC_Blocker("node_blocker_southoffices_1");	
		
	//Office C: Dead friendlies and hostiles
	level spawnGroup(getEntArray("hostiles_office_c", "targetname"));
	level spawnGroup(getEntArray("friendlies_office_c", "targetname"));	

}



trig_officeC_approach()
{
	flag_wait ("officeB1_cleared");	
	
	//wait for trigger, then disable it
	trigger = getEnt( "trig_officeC_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();


	//Office C: Human shield pair
	level thread human_shield_spawn("humanshield_southoffices_1");

	wait(0.05);
	eDoor = getent("door_officeC", "targetname");
	eDoor thread door_open(1);
	
	level waittill("human_shield_terrorist_dead");	
	
	//guy leaves blocker and guys setup for next breach
	level.eFriendly_soutoffices_blocker notify ("stop_blocking");
	
	aFriendlies = [];
	aFriendlies[0] = level.gaz;
	aFriendlies[1] = level.jack;
		
	level thread breach_room("officeD", aFriendlies, 0);	


	//spawn guys in next room
	//Office D: Dead friendlies, hostages and hostiles
	spawned_friendlies_office_d = level spawnGroup(getEntArray("friendlies_office_d", "targetname"));
	aHostages_office_d = level spawnGroup(getEntArray("hostages_office_d", "targetname"));
	spawned_hostiles_office_d = level spawnGroup(getEntArray("hostiles_office_d", "targetname"));
	array_thread(spawned_hostiles_office_d, ::setCQBbehavior, true);			
	
	//Friendly comes out of doorway to tell player to carry on		
	//eDoorGuyOfficeC = getDudeFromArray(level.spawned_friendlies_office_c, "office_c_door_guy");
	//assert(isdefined(eDoorGuyOfficeC));
	//eDoorGuyOfficeC thread door_NPC_open("door_officeC", 2, 2);
	
	//eDoorGuyOfficeC waittill ("door_has_been_opened");
	
	// Make guy block door and execute line of dialogue
	//eDoorGuyOfficeC.animname = "guy";
	
	//eDoorGuyOfficeC holdPosition(true);
	//eDoorGuyOfficeC thread queue_anim("embassy_frnd_teamisdown");	
	//eDoorGuyOfficeC holdPosition(false);
	
}

officeD_fight()	//Called from the global breach function
{	
	
	//wait for all hostiles dead
	waittill_aigroupcleared("hostiles_office_d");
	level.jack thread queue_anim("embassy_gaz_allclearmoveon3");
	
	flag_set("officeD_cleared");		
}


proceed_to_north_offices()	
{
	flag_wait("officeD_cleared");
	
	flag_set ("obj_hostage_secure_office_1_complete");
	
	
	
	//Have everyone ignore eachother
	ignoreEverybody(true);	
	
	
	//Color nodes
	triggerActivate("trig_colornodes_southhall");	



	//Gaz
	//"Command, this is Alpha One. South offices secure."	
	level.gaz queue_anim("embassy_gaz_southofficesecure");
	
	//Cmd
	//Roger that, Alpha One. RV with teams in North offices. Additional reinforcements inserting at your position.
	level thread dialogue_radio_thread("embassy_cmd_proceedtonorth");
	
	autosave_by_name ("south offices complete");
	
	AA_northOffices_init();
}

trig_lookat_southofficedoor()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_lookat_southofficedoor", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("player_has_looked_at_south_office_door");
}

trig_office_south_exit_approach()
{
	flag_wait("officeD_cleared");
		
	//wait for trigger, then disable it
	trigger = getEnt( "trig_office_south_exit_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//Wait for player to look at door
	level thread trig_lookat_southofficedoor();
	flag_wait("player_has_looked_at_south_office_door");
	
	//spawn hostiles coming through door
	hostiles_south_office_exit = level spawnGroup(getEntArray("hostiles_south_office_exit", "targetname"));	
	eHostage_south_office_exit_door = level spawnDude(getEnt("hostage_south_office_exit_door", "targetname"));

	//make hostile go to lounge then retreat
	doorHostile = hostiles_south_office_exit[0];
	doorHostile thread sprayKitchen();

	
	tempDoorHide(getent("door_office_south_exit", "targetname"));
	
	//hostage
	//"Don't shoot!"
	eHostage_south_office_exit_door thread queue_anim("embassy_hos_dontshoot");

	


	wait(1.5);
	
	//frnd
	//"Hostile! Take him out!"
	eGuy = get_closest_ally();
	if (isdefined(eGuy))
		eGuy thread queue_anim("embassy_frnd_takehimout");
	
	waittill_aigroupcleared("hostiles_south_office_exit");
	
	//force squad to next positions asap
	level.gaz thread forceToNode("squad_north_offices_start_1");
	level.jack thread forceToNode("squad_north_offices_start_2");
}

sprayKitchen()
{
	self endon ("death");
	self.animname = "guy";
	self.ignoreme = true;
	self.ignoresuppression = true;

	self animscripts\shared::putGunInHand ("none");


	eNode = getnode("node_office_south_exit_lounge", "targetname");
	//anim_single_solo (guy, anime, tag, node, tag_entity)
	self anim_reach_solo (self, "terrorist_fakeout", undefined, eNode);
	self anim_single_solo (self, "terrorist_fakeout", undefined, eNode);
	
	level thread teamIgnoreMe("allies", false);
	self stopanimscripted();
	self animscripts\shared::putGunInHand ("right");
	
	wait(1.5);
	
	self.ignoreme = false;
}


/****************************************************/
/**************** NORTH OFFICES FUNCTIONS************/
/****************************************************/
AA_northOffices_init()
{
	level thread obj_nav_office_north();
	level thread trig_south_office_exit_door();
	level thread trig_facadehall_enter();
	level thread trig_lookat_hostage_evac_facadehall();
	level thread trig_facadehall_approach();
	level thread trig_office_north_setup();
	level thread trig_north_office_approach();
	level thread trig_office_north_reached();
	level thread trig_sniper_sequence();
	level thread sniper_door_sequence();
	level thread trig_enter_officeF();
	level thread trig_exit_officeF();
	level thread trig_officeG_approach();
	level thread trig_delete_leftover_ai();
	level thread trig_enter_officeG();
	level thread office_I_breach_and_flank();
	level thread trig_flanking_balcony_approach();
	level thread trig_flanking_balcony_reached();
	level thread office_I_breach();
	level thread trig_conf_door_setup();
	level thread trig_conferenceHall_door_approach();
}


trig_south_office_exit_door()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_south_office_exit_door", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	flag_set("south_office_exit_reached");
	
	//spawn hostage evac friendlies in facade hall
	aSpawned_friendlies_hostage_evac_facadehall = level spawnGroup(getEntArray("friendlies_hostage_evac_facadehall", "targetname"));
	aHostages_evac_facadehall  = level spawnGroup(getEntArray("hostages_evac_facadehall", "targetname"));
		
	//wait till player looks at trigger, then have them do their thing
	flag_wait("player_has_looked_at_trig_lookat_hostage_evac_facadehall");
	
	array_thread(aSpawned_friendlies_hostage_evac_facadehall, ::goToNodeAndDelete, "node_delete_facade_hallway_1");
	array_thread(aHostages_evac_facadehall, ::goToNodeAndDelete, "node_delete_facade_hallway_1");	
	
	//frnd
	//"This way people. Let's move."	
	guy = aSpawned_friendlies_hostage_evac_facadehall[0];
	guy.animname = "guy";
	guy thread queue_anim("embassy_frnd_thiswayletsmove");
		
}

trig_facadehall_approach()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_facadehall_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	friendly_window_facadetransition01 = spawnDude(getEnt("friendly_window_facadetransition01", "script_noteworthy"));
	node = getnode(friendly_window_facadetransition01.target, "targetname");
	friendly_window_facadetransition01 thread window_rappel_smash("window_facadetran01", node);		
}
trig_lookat_hostage_evac_facadehall()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_lookat_hostage_evac_facadehall", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("player_has_looked_at_trig_lookat_hostage_evac_facadehall");

}

trig_facadehall_enter()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_facadehall_enter", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	level thread npcDelete("volume_southoffices", "all");	
	
	//Guys smash through windows
	friendly_window_facadetransition03 = spawnDude(getEnt("friendly_window_facadetransition03", "script_noteworthy"));
	node = getnode(friendly_window_facadetransition03.target, "targetname");
	friendly_window_facadetransition03 thread window_rappel_smash("window_facadetran03", node);		
	wait(.5);
	
	friendly_window_facadetransition02 = spawnDude(getEnt("friendly_window_facadetransition02", "script_noteworthy"));
	node = getnode(friendly_window_facadetransition02.target, "targetname");
	friendly_window_facadetransition02 thread window_rappel_smash("window_facadetran02", node);	

	wait(1);
	
	friendly_window_facadetransition04 = spawnDude(getEnt("friendly_window_facadetransition04", "script_noteworthy"));
	node = getnode(friendly_window_facadetransition04.target, "targetname");
	friendly_window_facadetransition04 thread window_rappel_smash("window_facadetran04", node);	

}

trig_office_north_setup()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_office_north_setup", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();		
	
	//ignoreEverybody(true);
}

trig_north_office_approach()
{
	trigger = getEnt( "trig_north_office_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("player_approaching_north_offices");
}
trig_office_north_reached()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_office_north_reached", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	//start scripted ambient sequence across barricades
	//level thread north_offices_ambient_battle();
	
	//Setup breach of the next room
	aFriendlies = [];
	aFriendlies[0] = level.gaz;
	aFriendlies[1] = level.jack;
	
	level.spawned_hostiles_office_f = level spawnGroup(getEntArray("hostiles_office_f", "targetname"));	
	array_thread(level.spawned_hostiles_office_f, ::setCQBbehavior, true);
	aHostages_office_f = level spawnGroup(getEntArray("hostages_office_f", "targetname"));	
	
	//have retreaters hold position for now
	//array_Thread(level.spawned_hostiles_office_f, ::goToVolume, "volume_officeF");
	
	level thread breach_room("officeF", aFriendlies, 0);		
	
	//update objectives
	flag_set ("obj_nav_office_north_complete");
	
	autosave_by_name ("north offices navigation complete");

	wait(2);
	level thread obj_hostage_secure_office_2();
}

trig_sniper_sequence()
{
	trigger = getEnt( "trig_sniper_sequence", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	//sets the flag in case the player still hasn't looked at it
	
	flag_set ("player_has_looked_at_trig_lookat_sniper_sequence");		
}

sniper_door_sequence()
{
		//Setup Friendly
		friendly_sniper_door_sequence = spawnDude(getent("friendly_sniper_door_sequence", "targetname"));
		friendly_sniper_door_sequence.animname= "guy";
		//Setup Terrorist
		hostile_door_sniper = spawnDude(getent("hostile_door_sniper", "targetname")); 
		hostile_door_sniper.animname = "guy";
		hostile_door_sniper invulnerable(true);
		hostile_door_sniper.ignoreme = true;
		hostile_door_sniper setFlashbangImmunity( true );
		//Setup Door
		eDoor = getent("door_officeE", "targetname");
		eAnimEnt = spawn( "script_origin", eDoor.origin);
		eAnimEnt.angles = eDoor.angles;
		//Setup Hostages
		aHostages_office_e = level spawnGroup(getEntArray("hostages_office_e", "targetname"));	
		
		//get terrorist into position to play anim
		
		eAnimEnt thread anim_reach_solo (hostile_door_sniper, "blow_back");
			
		flag_wait ("player_approaching_north_offices");
		
		//sierra 
		//"I have a confirmed X Ray at window three-two."
		level dialogue_radio_thread ("embassy_sierra_taketheshot");
		
		level thread trig_lookat_sniper_sequence();
		flag_wait ("player_has_looked_at_trig_lookat_sniper_sequence");
		
		//cmd "Take the shot, Sierra One."
		level thread dialogue_radio_thread ("embassy_cmd_taketheshot");
				
		wait(.6);
		eDoor playsound ("bullet_impact_headshot");
		eDoor thread door_open(1);
		
		wait(.19);
		//Sniper is blown through door
		eAnimEnt anim_single_solo (hostile_door_sniper, "blow_back");
		
		
		eAnimEnt thread anim_loop_solo(hostile_door_sniper, "blow_back_dead", undefined, "stop_idle");
		wait(1);
		hostile_door_sniper killEntity();		
		
		//Frnd
		//"that?s a confirmed kill, Sierra One."
		friendly_sniper_door_sequence thread queue_anim("embassy_frnd_confirmedkill");
		
		//Friendly and other idiots go into room to evac hostages
		aFriendlies = [];
		aAllFriendlies = getaiarray("allies");
		for(i=0;i<aAllFriendlies.size;i++)			//Create an array of everyone except player squad and delta team
		{
			if (isdefined(aAllFriendlies[i].script_noteworthy) && ((aAllFriendlies[i].script_noteworthy == "delta_squad") || (aAllFriendlies[i].script_noteworthy == "gaz") || (aAllFriendlies[i].script_noteworthy == "jack")))
				continue;
			else
				aFriendlies[aFriendlies.size] = aAllFriendlies[i];
		}
		
		level thread hostage_evac("officeE", aFriendlies);
}

trig_lookat_sniper_sequence()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_lookat_sniper_sequence", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set ("player_has_looked_at_trig_lookat_sniper_sequence");	
}


officeF_fight()		//called from the global breach function once door is breached
{


	//Have some hostiles retreat to hallway behind
	aRetreaters = getDudesFromArray(level.spawned_hostiles_office_f, "officeF_retreaters");
	level thread retreatToNodes(aRetreaters, "nodes_officeF_retreat");
	
	waittill_aigroupcleared("hostiles_office_f");
	
	level.gaz thread queue_anim("embassy_gaz_allclearmoveon3");
	
	flag_set("officeF_cleared");
	
	//have friendlies go to nodes and yell at human shield guy
	level thread human_shield_friendlies("nodes_frnd_humanshield_northoffices_1");

	triggerEnable("trig_officeG_approach", true);
}

trig_enter_officeF()
{
	trigger = getEnt( "trig_enter_officeF", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

}

trig_exit_officeF()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_exit_officeF", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
}


trig_delete_leftover_ai()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_delete_leftover_ai", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	level thread npcDelete("volume_northoffices_1", "all");	
	
	
}
trig_officeG_approach()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_officeG_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//Office G: Human shield pair
	level thread human_shield_spawn("humanshield_northoffices_1");
	wait(0.05);
	eDoor = getent("door_officeG", "targetname");
	eDoor thread door_open(1);
	
	level waittill("human_shield_terrorist_dead");		
	
	//colornodes
	triggerActivate("trig_colornodes_officeG");
	
	//spawn hostiles across the way	
	level spawnGroup(getEntArray("hostiles_officeH", "targetname"));
	
	waittill_aigroupcleared("hostiles_officeH");
	
	flag_set("office_H_cleared");
	
	//friendlies go setup ex
	
	// dude opens door
//	friendly_officeG_doorguy = spawnDude(getent("friendly_officeG_doorguy", "targetname"));
//	friendly_officeG_doorguy invulnerable(true);
//	friendly_officeG_doorguy.ignoreme = true;
//	friendly_officeG_doorguy.animname = "guy";
//	friendly_officeG_doorguy thread door_NPC_open("door_officeG", 2);

	//Jack
	//Hold your fire!	
	//level.jack thread queue_anim("embassy_jack_holdyourfire");
	
//	friendly_officeG_doorguy waittill ("door_has_been_opened");
//	
//	
//	friendly_officeG_doorguy holdPosition(true);
//	
//	//frnd
//	//Just in time, chaps.
//	friendly_officeG_doorguy queue_anim("embassy_frnd_yourejustintimechaps");
//	
//	//frnd
//	//"We've got a group across the hall pinning us down. I need a man to assist a flanking maneuver from the balcony"
//	friendly_officeG_doorguy queue_anim("embassy_frnd_pinneddown");
//
//	//gaz
//	//"You're up Andy"	
//	level.gaz queue_anim("embassy_gaz_youreup");	


	
	//level thread obj_balcony_flank();
	//flag_set("obj_balcony_flank_given");
	
	//friendly_officeG_doorguy holdPosition(false);
	//friendly_officeG_doorguy thread goToNode("node_officeG_doorcover");
	
	//flag_set("officeG_door_open");
	
	//flag_wait("officeG_reached");

	//frnd
	//"Get moving! We'll cover you while you cross the hallway"	
	//friendly_officeG_doorguy queue_anim("embassy_frnd_coverwhilecrosshall");
	
	//wait(1);
	
	//frnd
	//"Go! Go! Go! Get to the balcony"
	//friendly_officeG_doorguy queue_anim("embassy_frnd_gettothebalcony");		
}

trig_enter_officeG()
{
	//wait for trigger, then disable it
	trigger = getEnt( "trig_enter_officeG", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
}

north_offices_ambient_battle()
{
	flag_wait("officeG_reached");
}

friendlies_go_to_conf_hall_door()
{
	level.gaz thread goToNode("node_conf_hall_door_1");
	level.jack thread goToNode("node_conf_hall_door_2");
}

trig_flanking_balcony_approach()
{
	trigger = getEnt( "trig_flanking_balcony_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	flag_set("flanking_balcony_office_reached");	
	
	flag_wait("office_H_cleared");
	
	//window spawners
	level spawnGroup(getEntArray("friendlies_officeH", "targetname"));
	
}

office_I_breach_and_flank()
{
	flag_wait("office_H_cleared");
	
	level thread obj_balcony_flank();
	
	blockerEnable(getent("blocker_balconyflank_1", "targetname"), 0);
	
	level.gaz thread forceToNode("node_officeI_breach_1");
	level.jack thread set_explosives(getent("origin_northoffice_breach", "targetname"), undefined, true, 0);
	level.jack waittill ("explosives_set");
	level.jack thread forceToNode("node_officeI_breach_2");
}


trig_flanking_balcony_reached()
{
	trigger = getEnt( "trig_flanking_balcony_reached", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	flag_set("flanking_balcony_reached");	
	
	flag_wait("office_H_cleared");

	
}

office_I_breach()
{
	flag_wait("flanking_balcony_reached");	

	//spawn hostiles in office I
	level.hostiles_office_i = level spawnGroup(getEntArray("hostiles_office_i", "targetname"));
	aHostages_office_i = level spawnGroup(getEntArray("hostages_office_i", "targetname"));
	
	ignoreEverybody(false);

	//wait for player to look at wall
	trigger = getEnt( "trig_lookat_office_i_breach", "targetname" ); 
	trigger waittill ( "trigger" ); 
	trigger trigger_off();	
	
	//blow the wall
	maps\_utility::exploder(16);	
	getent("origin_northoffice_breach","targetname") thread play_sound_in_space("rocket_explode_default");
	earthquake (0.6, 2, level.player.origin, 1000);
	
	//blow the door
	eDoor = getent("door_officeI", "targetname");
	eDoor thread door_open(1);	
	
	//damage any guys within the radius
	
	
	
	//colornodes
	triggerActivate("trig_colornodes_office_i");
			
	waittill_aigroupcleared("hostiles_office_i");	

	//update objectives
	flag_set ("obj_hostage_secure_office_2_complete");	

	//have friendlies move to next door and await player
	level thread friendlies_go_to_conf_hall_door();
	
	//gaz
	//"Command, this is Alpha One. North offices have been secured."	
	level.gaz queue_anim("embassy_gaz_northofficessecured");
	
	//cmd
	//"Roger Alpha One. Proceed to the Banquet Hall and secure remaining hostages."	
	dialogue_radio_thread("embassy_cmd_gettobanquet");
			
	autosave_by_name ("north offices complete");
		
	triggerEnable("trig_conferenceHall_door_approach", true);	
	
	wait(2);
	level thread obj_hostage_secure_banquet();	
}

//
//balcony_ladder_dude_think()
//{
//	self endon ("death");
//	
//	self.animname = "guy";
//	self holdPosition(true);
//	
//	
//	flag_wait("flanking_balcony_office_reached");	
//
//	//frnd
//	//(whispered) Over here, Andy!	
//	self queue_anim("embassy_frnd_balconyoverhere");
//	
//	flag_wait("flanking_balcony_reached");
//
//	//frnd
//	//"Alright mate, lead the way and keep low."	
//	self queue_anim("embassy_frnd_balconyleadtheway");
//	
//	self holdPosition(false);
//	
//}


trig_conf_door_setup()
{
	trigger = getEnt( "trig_conf_door_setup", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//Setup guy who will kick down the door to conference area
	friendly_conf_door_kicker = spawnDude(getent("friendly_conf_door_kicker", "script_noteworthy"));
	friendly_conf_door_kicker.animname = "guy";
	friendly_conf_door_kicker holdPosition(true);
		
	flag_wait("player_is_approaching_conf_hall_door");
	
	//gaz
	//"Let's move."
	level.gaz thread queue_anim("embassy_gaz_letsmove");
	
	friendly_conf_door_kicker holdPosition(false);
	
	friendly_conf_door_kicker thread door_NPC_open("door_conf_hall", 1, 2);
	
	friendly_conf_door_kicker waittill ("door_has_been_opened");
			
	flag_set("conf_hall_door_is_open");
	
	//frnd
	//"They're retreating! Take them out!"	
	friendly_conf_door_kicker.animname = "guy";
	friendly_conf_door_kicker thread queue_anim("embassy_frnd_banquetretreat");
	
}

trig_conferenceHall_door_approach()
{
	trigger = getEnt( "trig_conferenceHall_door_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//delete npcs from all previous areas
	level thread npcDelete("volume_all_up_to_confhall", "all", false);
		
	flag_set("player_is_approaching_conf_hall_door");
		
	level thread AA_banquet_reception_init();

	
	//Wait till friendlies breach door
	
	flag_wait("conf_hall_door_is_open");
	
	//Window friendlies
	level spawnDude(getEnt("friendly_window_confhall01", "script_noteworthy"));
	wait(.6);	
	level spawnDude(getEnt("friendly_window_confhall02", "script_noteworthy"));
}

/****************************************************/
/**************** BANQUET RECEPTION FUNCTIONS****************/
/****************************************************/
AA_banquet_reception_init()
{
	level thread trig_conferenceHall_advance_1();
	level thread trig_conferenceHall_advance_2();
	level thread trig_conferenceHall_advance_3();
	level thread hostiles_retreat_to_banquet_hall();
	level thread trig_enter_banquet_reception();
	level thread trig_approach_banquet_reception_stairs();
	level thread trig_enter_banquet_reception_floor();
	level thread trig_barricade_banquet_door();
	level thread banquet_wall_breach();
	level thread trig_enter_banquet_breach();
	level thread trig_enter_banquet_halfway();
	level thread trig_enter_banquet_stairway();
	level thread trig_enter_banquet_upper_level_left();
	level thread trig_enter_banquet_upper_level_right();
}

trig_conferenceHall_advance_1()
{
	trigger = getEnt( "trig_conferenceHall_advance_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	

}

trig_conferenceHall_advance_2()
{
	trigger = getEnt( "trig_conferenceHall_advance_2", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//Window friendlies
	level spawnDude(getEnt("friendly_window_confhall03", "script_noteworthy"));
	wait(1);
	level spawnDude(getEnt("friendly_window_confhall04", "script_noteworthy"));
	
	//frnd
	//"Watch your fire, watch your fire. We still have hostages unaccounted for."	
	eGuy = get_closest_ally();
	if (isdefined(eGuy))
		eGuy thread queue_anim("embassy_frnd_watchyourfire");	
}

trig_conferenceHall_advance_3()
{
	trigger = getEnt( "trig_conferenceHall_advance_3", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//spawn a window guy
	level spawnDude(getEnt("friendly_window_confhall06", "script_noteworthy"));
}


hostiles_retreat_to_banquet_hall()
{
	spawned_hostiles_conference_hall = level spawnGroup(getEntArray("hostiles_conference_hall", "targetname"));
	spawned_hostiles_conference_hall_retreat = level spawnGroup(getEntArray("hostiles_conference_hall_retreat", "targetname"));
	
	level thread retreatToVolume(spawned_hostiles_conference_hall_retreat, "volume_banquet_lower");	
}

trig_enter_banquet_reception()
{
	trigger = getEnt( "trig_enter_banquet_reception", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
		

		
	flag_set("nav_banquet_hall_complete");

	//frnd
	//"Get down there! Don't let them get that door shut!"
	eGuy = get_closest_ally();
	if (isdefined(eGuy))
		eGuy thread queue_anim("embassy_frnd_dontletdoorshut");	
	

	
	spawned_hostiles_banquet_reception = level spawnGroup(getEntArray("hostiles_banquet_reception", "targetname"));	
	spawned_hostiles_banquet_reception_retreat = level spawnGroup(getEntArray("hostiles_banquet_reception_retreat", "targetname"));	
	
	level thread retreatToVolume(spawned_hostiles_banquet_reception_retreat, "volume_banquet_lower");
	
	//Wait until there are no more hostiles
	aHostilesLower = getAIarrayTouchingVolume("axis", "volume_banquet_reception_lower");
	waittill_dead(aHostilesLower);
	
	aHostilesUpper = getAIarrayTouchingVolume("axis", "volume_banquet_reception_upper");
	waittill_dead(aHostilesUpper);
	
	flag_set("banquet_reception_cleared");	
	
	//activate the trigger to close banquet doors	
	if ( !flag( "banquet_doors_barricaded" ) )
	{
		trig = getent("trig_barricade_banquet_door", "targetname");
		trig notify("trigger");		
	}


}

trig_approach_banquet_reception_stairs()
{
	trigger = getEnt( "trig_approach_banquet_reception_stairs", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	

}


trig_barricade_banquet_door()
{
	trigWait("trig_barricade_banquet_door");
	
	flag_set("banquet_doors_barricaded");
	
	door = getent("door_banquet_hall", "targetname");
	door show();
	door solid();
	if (door.spawnflags & 1)
		door disconnectpaths();
		
	

	//delete all the hostiles inside the banquet hall
	level thread npcDelete("volume_banquet_upper", "all", false);
	level thread npcDelete("volume_banquet_lower", "all", false);

	//frnd
	//"They've barricaded themselves in, sir."
	eGuy = get_closest_ally();
	if (isdefined(eGuy))
		eGuy thread queue_anim("embassy_frnd_banquetbarricaded");			
	
}

trig_enter_banquet_reception_floor()
{
	trigger = getEnt( "trig_enter_banquet_reception_floor", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//kill all the hostiles left behind in the conference hall (if any)
	level thread npcDelete("volume_conference_hall", "all", true);
}

banquet_wall_breach()
{
	flag_wait("banquet_reception_cleared");	
	flag_wait("banquet_doors_barricaded");
	

	// Jack goes to check door
	eDoor = getent("origin_door_banquet_hall", "targetname");
	level.jack thread door_check(eDoor, 3);
	
	
	level.gaz thread forceToNode("node_banquet_door");
	
	wait(1);	
	
	//Gaz
	//Jack, check the door. Get that fiberoptic under there and tell me what's what.
	//level.gaz thread dialogue_thread("embassy_gaz_checkbanquetdoor");

	//gaz
	//"They'll be expecting us up the middle. Get charges on either side of the main door."	
	level.gaz thread queue_anim("embassy_gaz_placecharges");	
	level thread banquet_breach_dudes();
	
	level.jack waittill ("door_check_reached");
	
	
	wait(2);
	level.jack notify ("door_check_signal");	
	
	level.jack waittill ("door_check_signals_complete");


	
	level.jack notify ("door_check_stop");
}
	
banquet_breach_dudes()
{
	//Get 2 dudes who are not Gaz or Jack
	aExcluders = [];
	aExcluders[0] = level.jack;
	aExcluders[1] = level.gaz;	
	eBreach_Guy_01 = get_closest_ai_exclude (level.player getorigin(), "allies", aExcluders);
	aExcluders = [];
	aExcluders[0] = level.jack;
	aExcluders[1] = level.gaz;
	aExcluders[2] = eBreach_Guy_01;
	eBreach_Guy_02 = get_closest_ai_exclude (level.player getorigin(), "allies", aExcluders);
	assert(isdefined(eBreach_Guy_01));
	assert(isdefined(eBreach_Guy_02));
	
	//Have each guy go plant explosives on breach points
	level thread banquet_breach_1(eBreach_Guy_01);
	level thread banquet_breach_2(eBreach_Guy_02);

	flag_wait("banquet_wall_first_explosive_planted");
	flag_wait("banquet_wall_second_explosive_planted");
	
	//spawn guys inside banquet hall
	spawned_hostiles_banquet_hall = level spawnGroup(getEntArray("hostiles_banquet_hall", "targetname"));
		
	wait(2);
	
	//jack
	//"Stand back everyone. Three, two one."
	level.jack queue_anim("embassy_jack_standbackbanquet");

	//blow up the breaches
	maps\_utility::exploder(2);	
	earthquake (0.6, 2, level.player.origin, 1000);
	getent("origin_breach_banquet_hall_r","targetname") thread play_sound_in_space("rocket_explode_default");

	maps\_utility::exploder(3);
	getent("origin_breach_banquet_hall_l","targetname") thread play_sound_in_space("rocket_explode_default");

	badplace_delete("badplace_banquet_r");
	badplace_delete("badplace_banquet_l");
	
	level thread banquet_hall_fight();	
}	


banquet_breach_1(eGuy)
{
	eGuy thread set_explosives(getent("origin_breach_banquet_hall_r", "targetname"), "badplace_banquet_r", true, 0);
	eGuy waittill ("explosives_set");
 	flag_set("banquet_wall_first_explosive_planted");
}
banquet_breach_2(eGuy)
{
	eGuy thread set_explosives(getent("origin_breach_banquet_hall_l", "targetname"), "badplace_banquet_l", true, 0);
	eGuy waittill ("explosives_set");
 	flag_set("banquet_wall_second_explosive_planted");
}

banquet_hall_fight()
{


	//gaz
	//"Move! Move! Move!"	
	level.gaz thread queue_anim("embassy_gaz_movemovemove");	
	
	//Update colornodes
	triggerActivate("trig_colornodes_banquethall");
}


trig_enter_banquet_breach()
{
	trigger = getEnt( "trig_enter_banquet_breach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//stop spawning dudes and wait for all ai to be dead
	wait(4);
	aHostilesLower = getAIarrayTouchingVolume("axis", "volume_banquet_lower");
	waittill_dead (aHostilesLower);
	
	aHostilesUpper = getAIarrayTouchingVolume("axis", "volume_banquet_upper");
	waittill_dead (aHostilesUpper);
	
	flag_set ("obj_hostage_secure_banquet_complete");
	
	level thread AA_kitchen_stairwell_init();	
}

trig_enter_banquet_halfway()
{
	trigWait("trig_enter_banquet_halfway");
	
	//cmd
	//"This is Command. Additional reinforcements inserting at your position."
	level thread dialogue_radio_thread("embassy_cmd_additionalforces1");
	
	//spawn reinforcements from skylight
	level spawnDude(getEnt("friendly_skylight_banquet01", "script_noteworthy"));
	wait(.75);
	level spawnDude(getEnt("friendly_skylight_banquet02", "script_noteworthy"));
	wait(1.75);
	level spawnDude(getEnt("friendly_skylight_banquet03", "script_noteworthy"));	
}
	
trig_enter_banquet_stairway()
{
	trigWait("trig_enter_banquet_stairway");

}

trig_enter_banquet_upper_level_left()
{
	trigWait("trig_enter_banquet_upper_level_left");
	triggerEnable("trig_enter_banquet_upper_level_right", false);
	
	//spawn reinforcements from windows
	spawnDude(getEnt("friendly_window_banquet01", "script_noteworthy"));
	wait(.5);
	spawnDude(getEnt("friendly_window_banquet02", "script_noteworthy"));
}

trig_enter_banquet_upper_level_right()
{
	trigWait("trig_enter_banquet_upper_level_right");
	triggerEnable("trig_enter_banquet_upper_level_left", false);
	
	//spawn reinforcements from windows
	spawnDude(getEnt("friendly_window_banquet03", "script_noteworthy"));
	wait(.75);
	spawnDude(getEnt("friendly_window_banquet04", "script_noteworthy"));		
}

/****************************************************/
/**************** KITCHEN STAIRWELL FUNCTIONS****************/
/****************************************************/
AA_kitchen_stairwell_init()
{
	level thread banquet_briefing();
	level thread trig_kitchen_door_approach();
	level thread trig_enter_hallway_kitchen();
	level thread trig_enter_stairwell_kitchen();
	level thread trig_enter_stairwell_area_1();
	level thread trig_approach_mezzanine_door();

}

banquet_briefing()
{
	//Have all guys school circle near stairs
//	aSoldiers = getaiarray("allies");
//	level thread schoolcircle("banquet", aSoldiers, level.gaz);
//
//	wait(1);
	
//	level thread obj_banquet_hall_regroup();
//	level thread trig_banquet_hall_regroup();
	//gaz
	
//	//"Good work lads. We?ve got a heli coming in to evacuate the Yanks."
//	level.gaz dialogue_thread("embassy_gaz_helievaccoming");
//	
//	//Gaz
//	//Regroup on me, lads. Come on let's move.
//	level.gaz dialogue_thread("embassy_gaz_banquetregroup");	
	
	//flag_wait ("obj_banquet_hall_regroup_complete");	


	//colornodes
	triggerActivate("trig_colornodes_banquethall_after");
	
	autosave_by_name ("banquet complete");

	//gaz
	//"Command, this is Alpha One. All hostages secured in banquet hall and kitchen. Zero X Rays taken prisoner."	
	level.gaz queue_anim("embassy_gaz_banquetcleared");	

	//cmd
	//"Understood, Alpha One. Bravo One, what is your status?"	
	dialogue_radio_thread("embassy_cmd_bravowhatsyourstatus1");	

//	wait(2);
//	
//	//cmd
//	//"Bravo One, what is your status? Come in Bravo One."
//	dialogue_radio_thread("embassy_cmd_bravowhatsyourstatus2");	
	
	level thread explosion_rocks_building();

	wait(1);
	
	//brv1
	//"This is Bravo One. Hostage reception is blocked. We?re pinned down with a dozen or so hostages in tow...we cannot effectively return fire. Receiving heavy rpg fire."
	dialogue_radio_thread("embassy_brv1_receptionblocked");	

	//cmd
	//"Roger that. Alpha One, you are to RV immediately with Bravo One. Proceed to the drawing room area opposite hostage reception. Eliminate all X Rays to allow Bravo to proceed with exfil."
	dialogue_radio_thread("embassy_cmd_gettodrawingroom");

	level thread obj_bravo_rv();	

	//gaz
	//"Alright lads, you heard the man, let's get a move on."
	level.gaz thread queue_anim("embassy_gaz_letsgettodrawingroom");		

	level thread breachSetup("kitchenhall");
	level waittill ("kitchenhall_ready_to_be_breached");
	
	triggerEnable("trig_kitchen_door_approach", true);			
}

//trig_banquet_hall_regroup()
//{
//	trigger = getEnt( "trig_banquet_hall_regroup", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
//	
//	flag_set ("obj_banquet_hall_regroup_complete");	
//	
//}

//schoolcircle(sArea, aSoldiers, eLeader)
//{
//	aCircleNodes = getnodearray("node_schoolcircle_" + sArea, "targetname");
//	
//	eLeader thread forceToNode ("node_schoolcircle_speaker_" + sArea);
//	
//	for(i=0;i<aSoldiers.size;i++)
//	{
//		aSoldiers[i] setgoalnode(aCircleNodes[i]);
//	}
//}

explosion_rocks_building()
{
	earthquake (0.6, 2, level.player.origin, 1000);
	getent("volume_drawing_room","targetname") thread play_sound_in_space("rocket_explode_default");

}

trig_kitchen_door_approach()
{
	trigger = getEnt( "trig_kitchen_door_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	spawned_hostiles_kitchen_hall = level spawnGroup(getEntArray("hostiles_kitchen_hall", "targetname"));

	//gaz
	//"Remember lads, check those corners"
	level.gaz thread queue_anim("embassy_gaz_checkcorners1");
	
	tempDoorHide(getent("door_kitchenhall", "targetname"));
	ignoreEverybody(false);
	flag_set("kitchen_door_breached");	
	

}
trig_enter_hallway_kitchen()
{
	trigger = getEnt( "trig_enter_hallway_kitchen", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

}
trig_enter_stairwell_kitchen()
{
	trigger = getEnt( "trig_enter_stairwell_kitchen", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	
	//jack
	//"Check your corners. Check your corners"
	level.jack thread queue_anim("embassy_jack_checkcorners1");	
	
	//delete all inside the banquet hall
	level thread npcDelete("volume_banquet_upper", "all", false);
	level thread npcDelete("volume_banquet_lower", "all", false);	
	
}

trig_enter_stairwell_area_1()
{
	trigger = getEnt( "trig_enter_stairwell_area_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("stairwell_reached");

	spawned_hostiles_stairwell = level spawnGroup(getEntArray("hostiles_stairwell", "targetname"));
}

trig_approach_bravo()
{

	trigWait("trig_approach_bravo");
	
	
}

trig_approach_mezzanine_door()
{
	trigger = getEnt( "trig_approach_mezzanine_door", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	


	
	level thread ai_setup_drawing_room();		
	level thread AA_bravo_area_init();
	
	level waittill ("ai_setup_drawing_room_complete");	
	
	
	
	level.bravo_stairwell holdPosition(false);	
	wait(.5);
	
	
	level.bravo_stairwell thread door_NPC_open("door_mezzanine", 2, 2);
	level.bravo_stairwell waittill ("door_has_been_opened");
	
	//kill remaining hostiles in stairwell
	level thread npcDelete("volume_stairwell", "axis", true);
	
	level.bravo_stairwell holdPosition(true);	
	
	level.player.ignoreme = true;	
	
	//brv2
	//"Glad to see you boys. Come with me, Bravo can?t exfil until we take out that RPG. Let's move."
	level.bravo_stairwell queue_anim("embassy_brv2_gladtoseeyou");	
	
	level.bravo_stairwell holdPosition(false);	

	flag_set("obj_bravo_rv_complete");
	
	//activate next trigger to update friendly color nodes
	wait(.5);
	triggerActivate("trig_enter_mezzanine");
	
	autosave_by_name ("bravo rv complete");
	
	wait(2);

	level thread obj_reception_clear();
}

ai_setup_drawing_room()
{
	//spwan bravo team
	level.aFriendlies_bravo = level spawnGroup(getEntArray("friendlies_bravo", "targetname"));
	array_thread(level.aFriendlies_bravo, ::makeUnaware,true);
	array_thread(level.aFriendlies_bravo, ::invulnerable,true);
	level.bravo_courtyard = getDudeFromArray(level.aFriendlies_bravo, "bravo_courtyard");
	level.bravo_leader = getDudeFromArray(level.aFriendlies_bravo, "bravo_leader");
	level.bravo_leader.animname = "brv1";
		
	//spawn bravo guys at mezzanine level
	level.bravo_stairwell = level spawnDude(getEnt("bravo_stairwell", "targetname"));
	level.bravo_stairwell invulnerable(true);
	level.bravo_stairwell.animname = "guy";
	//level.bravo_stairwell holdPosition(true);	
	
//	level.bravo_backdraft = level spawnDude(getEnt("bravo_backdraft", "targetname"));
//	level.bravo_backdraft.animname = "guy";
//	level.bravo_backdraft makeUnaware(true);
//	level.bravo_backdraft invulnerable(true);
//	level.bravo_backdraft holdPosition(true);	
	
	level.bravo_mezzanine_1 = level spawnDude(getEnt("bravo_mezzanine_1", "targetname"));	
	level.bravo_mezzanine_1 invulnerable(true);
	
	//have squad be unaware and ignored for the time being
	aSquad = getSquadArray();
	array_thread(aSquad, ::makeUnaware,true);
	
	//spawn hostiles on other side of courtyard
	flood_spawn(getEntArray("hostiles_reception", "targetname"));
	
	level notify ("ai_setup_drawing_room_complete");
}
/****************************************************/
/**************** BRAVO AREA FUNCTIONS***************/
/****************************************************/

AA_bravo_area_init()
{
	level thread trig_bravo_approach();
	level thread trig_drawing_room_statue();
	level thread trig_mezzanine_to_roof_door_approach();
	level thread trig_courtyard_hallway_enter();
	level thread trig_rooftop_door_approach();
	level thread trig_rooftop_door_exit();
	level thread trig_rooftop_reached();
	level thread trig_reception_floor_entered();
}

trig_bravo_approach()
{
	trigWait("trig_bravo_approach");
	
	//brv 1
	//Get back with your team and take out those RPGs!	
	level.bravo_leader thread queue_anim("embassy_brv1_gettoreception");
	
}
trig_drawing_room_statue()
{
	trigWait("trig_drawing_room_statue");
	
	//statue blows up from RPG hit
	maps\_utility::exploder(30);	
	level.player play_sound_in_space("rocket_explode_default");
	earthquake (0.6, 2, level.player.origin, 1000);
	
}

trig_mezzanine_to_roof_door_approach()
{
	trigger = getEnt( "trig_mezzanine_to_roof_door_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//brv3
	//"This way, gents."
//	level.bravo_backdraft holdPosition(false);
//	level.bravo_backdraft thread dialogue_thread("embassy_brv3_thiswaydoorexplode");	
//	level.bravo_backdraft thread forceToNode("node_backdraft_door");
	//wait(1);
	
	//brv2
	//"Hold up Fatboy, we need to check the door for explosives!"
	//level.bravo_stairwell thread dialogue_thread("embassy_brv2_holdupcheckthedoor");		
	
	//level.bravo_backdraft waittill ("goal");
	
	//maps\_utility::exploder(5);	
	//earthquake (0.6, 2, level.player.origin, 1000);
	//getent("door_backdraft","targetname") thread play_sound_in_space("rocket_explode_default");	
	
	//level.bravo_backdraft invulnerable(false);
	//level.bravo_backdraft thread killEntity();
		
	//Jack goes in first so he can check the next door
	eDoor = getent("door_roof_access", "targetname");
	level.jack thread door_check(eDoor, 4);
			
	wait(1);
	//Gaz
	// Bloody Christ. Booby trap. Jack, get a camera under the next door. 
	//level.gaz thread dialogue_thread("embassy_gaz_checkthenextdoor");
		

	level.jack waittill ("door_check_reached");
	
	wait(2);
	flag_wait("skylight_access_door_reached");
	
	level.jack notify ("door_check_signal");	
	level.jack waittill ("door_check_signals_complete");

	//jack
	//"Door is clear."
	level.jack thread queue_anim("embassy_jack_doorisclear");
	level.jack notify ("door_check_stop");
	level.jack waittill ("door_check_complete");
	
	//Jack kicks in the door
	level.jack thread door_NPC_open("door_roof_access", 0, 2);
	level.jack waittill ("door_has_been_opened");

	
	//Have everyone go to the skylight and get in place
	level.guysReadyAtSkylight = 0;
	aSquad = getSquadArray();
	aRappelPoints = getentarray("origin_skylight_breach_1", "targetname");
	iSquadRappelIndex = 0;
	
	
	for(i=0;i<aSquad.size;i++)
	{
		
		if ( (isdefined(aSquad[i].script_noteworthy)) && (aSquad[i].script_noteworthy == "gaz") )
		{
			eRappelPoint = getent("origin_skylight_breach_gaz", "targetname");

		}
		else
		{
			eRappelPoint = aRappelPoints[iSquadRappelIndex];
			iSquadRappelIndex ++;
		}

		
		aSquad[i] thread skylight_rappel(eRappelPoint);
		aSquad[i] thread guysReadyAtSkylight_monitor();
	}		
}

guysReadyAtSkylight_monitor()
{
	self waittill ("ready_to_rappel_at_skylight");
	
	level.guysReadyAtSkylight ++;
	
	if (level.guysReadyAtSkylight == 4)
		flag_set("all_guys_ready_to_rappel_at_skylight");	
}


skylight_rappel(eAnimEnt)
{
	self endon ("death");	
	
	self set_animname ("guy");	
	self.ignoreme = true;	
	self pushplayer(true);
	
	ender = "stop_idle";
	
	// Get to the skylight and wait
	self setFlashbangImmunity( true );
	eAnimEnt anim_reach_solo(self, "rappel_skylight_mount");
	self notify ("ready_to_rappel_at_skylight");
	
	eAnimEnt thread anim_loop_solo (self, "rappel_skylight_idle", undefined, ender);
		
	flag_wait("skylight_breach_command_given");
	
	wait (randomfloatrange(.25,1.75));
	
	eAnimEnt notify (ender);
	eAnimEnt thread anim_single_solo (self, "rappel_skylight_drop");	
	self waittillmatch("single anim", "end");
	
	self reset_animname();	
	self.ignoreme = false;	
	self pushplayer(false);
}



trig_courtyard_hallway_enter()
{
	trigger = getEnt( "trig_courtyard_hallway_enter", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("drawaing_room_exit_breached");
}

trig_rooftop_door_approach()
{
	trigger = getEnt( "trig_rooftop_door_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("skylight_access_door_reached");

}

trig_rooftop_door_exit()
{
	trigger = getEnt( "trig_rooftop_door_exit", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
}

trig_rooftop_reached()
{
	trigger = getEnt( "trig_rooftop_reached", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("skylight_rooftop_reached");
	
	level thread obj_skylight_breach();

	//Gaz
	//Right. Grab a rope and get into position. Andy, you're over here near me.	
	level.gaz thread queue_anim("embassy_gaz_skylightgetready1");	
	
	level thread trig_use_skylight_get_into_position_think();
}


trig_use_skylight_get_into_position_think()
{
	triggerEnable("trig_use_skylight_get_into_position", true);
	
	//setup hint trigger 	
	trig_use_skylight_get_into_position = getent("trig_use_skylight_get_into_position", "targetname");
	trig_use_skylight_get_into_position setHintString( &"EMBASSY_HINTSTR_ROPE_GRAB");
	trig_use_skylight_get_into_position usetriggerrequirelookat();

	//wait until hits "use" key
	trig_use_skylight_get_into_position waittill("trigger");
	trig_use_skylight_get_into_position trigger_off();	
	
	//Take player weapons away
	level thread playerWeaponTempRemove();
	
	//Put player into position
	eWarp = getent("origin_obj_skylight_breach", "targetname");
	level.player setorigin (eWarp.origin);
	level.player setplayerangles (eWarp.angles);
	level.player linkto(eWarp);
	
	//Move to rappel point
	level.eSkylightRappelStart = getent("origin_obj_skylight_breach_drop", "targetname");
	fMoveTime = .5;
	eWarp moveto( level.eSkylightRappelStart.origin, fMoveTime, .1, .1 );
	wait (fMoveTime);
	level.player unlink();
	level.player linkto(level.eSkylightRappelStart);
	
	//Gaz
	//Right, on three. One....two....3	
	level.gaz queue_anim("embassy_gaz_skylightonthree");	

	//Allow player to press the use trigger 
	level thread trig_use_skylight_breach_think();
	
	//Gaz
	//Go! Go! Go!
	level.gaz thread queue_anim("embassy_gaz_skylightgogogo");	
	
	//blow the window and update objectives
	maps\_utility::exploder(6);	
	earthquake (0.6, 2, level.player.origin, 1000);
	getent("origin_obj_skylight_breach","targetname") thread play_sound_in_space("rocket_explode_default");
	
	flag_set("skylight_breach_command_given");
	
	flag_set ("obj_skylight_breach_complete");
	
	level thread reception_shootout();	
}

trig_use_skylight_breach_think()
{

	triggerEnable("trig_use_skylight_breach", true);
	
	//setup hint trigger 	
	trig_use_skylight_breach = getent("trig_use_skylight_breach", "targetname");
	trig_use_skylight_breach setHintString( &"EMBASSY_HINTSTR_ROPE_RAPPEL");

	//wait until hits "use" key
	trig_use_skylight_breach waittill("trigger");
	trig_use_skylight_breach trigger_off();	
	
	// HACK - make the user rappel
	fMoveTime = 1.8;
	eEndRappelPoint = getent("origin_obj_skylight_breach_end", "targetname");
	level.eSkylightRappelStart moveto( eEndRappelPoint.origin, fMoveTime, .5, .5 );
	wait (fMoveTime);
	
	level.player unlink();
	level.player notify ("restore_player_weapons");
	
	level.player.ignoreme = false;	
}

reception_shootout()
{
	
	aSquad = getSquadArray();
	array_thread(aSquad, ::makeUnaware,false);
}

trig_reception_floor_entered()
{
	trigger = getEnt( "trig_reception_floor_entered", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//wait for remaining ai to be dead
	aHostiles = getAIarrayTouchingVolume("axis", "volume_reception");
	waittill_dead (aHostiles);
	
	flag_set("obj_reception_clear_complete");
		
	autosave_by_name ("reception assault complete");
	
	level thread AA_elevator_assault_init();	
}
/****************************************************/
/**************** ELEVATOR ASSAULT FUNCTIONS ****************/
/****************************************************/

AA_elevator_assault_init()
{
	level thread courtyard_sniper_sequence();
	level thread trig_courtyard_cover();
	level thread trig_enter_elevator_shaft();
	level thread trig_ladder_dismount();
	level thread trig_enter_elevator_rooftop();
	level thread trig_squad_advance_rooftop_1();
	level thread trig_squad_advance_rooftop_2();
	level thread trig_squad_advance_rooftop_3();
	level thread trig_enter_library_foyer();
	level thread foyer_door_slam();
	level thread trig_approach_library_sidehall();
	level thread trig_foyer_frontdoor_approach();
	level thread trig_foyer_sidedoor_approach();
}

courtyard_sniper_sequence()
{
	//brv1
	//"Thanks, Alpha. We owe you boys a pint."
	dialogue_radio_thread("embassy_brv1_weoweyouapint");

	//Gaz
	//Hold up, Bravo, we'll cover your crossing from here. 
	triggerActivate("trig_colornodes_courtyard_cover");	
	level.gaz queue_anim("embassy_gaz_courtyardcover");	
//	
//	//Gaz
//	//Andy, get into position and keep your eyes peeled for hostiles
//	level.gaz thread dialogue_thread("embassy_gaz_covercommand1");
//	
//	
//	
//	level notify("courtyard_objective_given");
//	level thread obj_courtyard_cover();
//	
//	level courtyard_cover_nag();
//
//	//Player is in position
//	flag_set("courtyard_cover_navigate_complete");
//	
//	// Bravo begins navigating across
//	for(i=0;i<level.aFriendlies_bravo.size;i++)
//	{
//		wait (randomfloatrange(0.5, 1.5));
//		level.aFriendlies_bravo[i] thread goToNode("node_courtyard");
//	}
//	
	//Spawn dudes on roof
	flood_spawn(getEntArray("hostiles_library_roof", "targetname"));

	wait(1);
	aHostiles_library_roof = getAIarrayTouchingVolume("axis", "volume_library_roof");
	for(i=0;i<aHostiles_library_roof.size;i++)
	{
		aHostiles_library_roof[i].favoriteenemy =  level.bravo_courtyard;
		aHostiles_library_roof[i].ignoreme = true;
	} 
		
	//Jack 
	//Movement! Upper rooftop!
	level.jack thread queue_anim("embassy_jack_movementupper");	
	
	wait(1);
	
	//gaz
	//"Sniper! Upper floor!"
	level.gaz thread queue_anim("embassy_gaz_sniperupperfloor");		
	wait(1);
	
	//jack
	//"Everyone! Take cover!"
	level.jack thread queue_anim("embassy_jack_takecover");	

//	wait(.75);
//	//Gaz
//	//Abort Bravo! Go back! Go back!
//	level.gaz thread dialogue_thread("emabssy_gaz_abortbravo");	
//
//	//Bravo heads back
//	for(i=0;i<level.aFriendlies_bravo.size;i++)
//	{
//		level.aFriendlies_bravo[i] notify ("goal");
//		wait (randomfloatrange(0.5, 1.5));
//		level.aFriendlies_bravo[i] thread goToNodeAndDelete("node_courtyard_retreat");
//	}
//		
//	//gaz
//	//"Command, this is Alpha One, we have men down. Sniper in upper offices above the courtyard."
//	level.gaz dialogue_thread("embassy_gaz_sniperinupperoffices");	
//	
//	//cmd
//	//"Roger, Alpha One. Sierra group does not have a view. Repeat, snipers cannot pinpoint enemy location. Proceed immediately to flush out hostiles in upper offices."
//	dialogue_radio_thread("embassy_cmd_proceedtolibrary");	
//	
//	flag_set("obj_courtyard_cover_complete");	
	
	wait(4);
	
	//gaz
	//"Right, our jobs not done yet, lads. 
	//level.gaz dialogue_thread("embassy_gaz_jobsnotdone");	
	
	//gaz
	//Bravo won?t be able to exfil these hostages through that courtyard with a sniper hanging about. 
	level.gaz queue_anim("embassy_gaz_mustfindsniper");
	
	//gaz
	//Let?s get up there and have a look. Get these elevator doors open."
	level.gaz thread queue_anim("embassy_gaz_elevatorcmd");		
	
	autosave_by_name ("elevator ascent");
		
	level thread obj_sniper_assault();
	
	level thread elevator_door_open();	
	
	
	flag_wait("elevator_rooftop_reached");
	aHostiles_library_roof = getAIarrayTouchingVolume("axis", "volume_library_roof");
	for(i=0;i<aHostiles_library_roof.size;i++)
	{
		if (!isalive(aHostiles_library_roof[i]))
			return;
		aHostiles_library_roof[i].favoriteenemy =  level.player;
		aHostiles_library_roof[i].ignoreme = false;
	} 
}

courtyard_cover_nag()
{
	level endon ("courtyard_cover_navigate_complete");
	
	//Gaz nags player till he gets his ass in gear
	i = 2;
	while ( !flag("courtyard_cover_navigate_complete") )
	{
		level.gaz thread queue_anim("embassy_gaz_covercommand" + i);
		i++;
		if (i > 3)
			i = 2;
		wait (randomfloatrange(6.3, 10));		
	}
}


trig_courtyard_cover()
{
	level waittill("courtyard_objective_given");
	trigger = getEnt( "trig_courtyard_cover", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	flag_set("courtyard_cover_navigate_complete");
	level notify ("courtyard_cover_navigate_complete");
	
}
elevator_door_open()
{
	level thread elevator_doors_think();
	
	
	level.guysAtElevator = 0;
	aElevatorGuys = [];
	aElevatorGuys[0] = level.gaz;
	aElevatorGuys[1] = level.bravo_stairwell;
	aElevatorGuys[2] = level.jack;
	
	for(i=0;i<aElevatorGuys.size;i++)
	{
		aElevatorGuys[i] thread elevator_door_open_think();
		aElevatorGuys[i] thread guysReadyAtElevator_monitor();
	}
	
	flag_wait ("elevator_ready_to_be_pried_open");
	
	
	level waittill ("elevator_sequence_complete");
	
	//jack
	//"Got it!"	
	level.jack thread queue_anim("embassy_jack_elevatordooropen");	
	
		
	//colornodes
	triggerEnable("trig_colornodes_roof", true);
	triggerActivate("trig_colornodes_roof");
		
	level waittill ("elevator_doors_open");	
	
	//brv
	//"Right!, up the elevator shaft, let's go! Let's go!"
	level.bravo_stairwell thread queue_anim("embassy_brv_getuptheshaft");	
	
}

elevator_doors_think()
{
	eDoorLeft = getent("door_elevator_l", "targetname");
	eDoorRight = getent("door_elevator_r", "targetname");
	eDoorLeftOrigin = getent(eDoorLeft.target, "targetname");
	eDoorRightOrigin = getent(eDoorRight.target, "targetname");
	eDoorLeftOriginEnd = getent(eDoorLeftOrigin.target, "targetname");
	eDoorRightOriginEnd = getent(eDoorRightOrigin.target, "targetname");
	
	//Link doors to respective origins
	eDoorLeft linkto (eDoorLeftOrigin);
	eDoorRight linkto (eDoorRightOrigin);
	
	// Wait till guys in position AND player is looking over there
	flag_wait ("all_guys_ready_at_elevator");
	waittill_trigger_look("trig_lookat_elevator");
	
	flag_set("elevator_ready_to_be_pried_open");
	wait(1);
	//Open door halfway and move back
	eDoorLeftOrigin movex( -14, 1.5, .5, .5 );
	eDoorRightOrigin movex( 14, 1.5, .5, .5 );
	wait(1.5);
	eDoorLeftOrigin movex( 14, .5, 0, 0 );
	eDoorRightOrigin movex( -14, .5, 0, 0 );
	
	level waittill ("elevator_sequence_complete");
	
	wait(3.5);
	
	eDoorLeftOrigin movex( -64, 3, .5, .5 );
	eDoorRightOrigin movex( 64, 3, .5, .5 );
	
	wait(3);

	eDoorLeft connectpaths();
	eDoorRight connectpaths();
		
	level notify ("elevator_doors_open");
}

guysReadyAtElevator_monitor()
{
	self waittill ("ready_to_open_elevator");
	
	level.guysAtElevator ++;
	
	if (level.guysAtElevator == 3)
		flag_set("all_guys_ready_at_elevator");	
}

waittill_trigger_look(sTrigger)
{
	eTrig = getent(sTrigger, "targetname");assert(isdefined(eTrig));
	eTrig waittill ( "trigger" ); eTrig trigger_off();
}

elevator_door_open_think()
{
	self endon ("death");
	
	eAnimEnt = getent("origin_elevator_middle", "targetname");
	
	self setFlashbangImmunity( true );
	eAnimEnt anim_reach_solo(self, "elevator_pry_idle_start");
	self notify ("ready_to_open_elevator");
	
	eAnimEnt thread anim_loop_solo (self, "elevator_pry_idle", undefined, "stop_idle");
	
	flag_wait ("elevator_ready_to_be_pried_open");
	
	eAnimEnt notify ("stop_idle");
	eAnimEnt thread anim_single_solo (self, "elevator_pry");
	
	self waittillmatch("single anim", "end");
	
	level notify ("elevator_sequence_complete");		
}

trig_enter_elevator_shaft()
{
	trigger = getEnt( "trig_enter_elevator_shaft", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("elevator_shaft_reached");
}
	
//trigger_use_ladder_dismount()
//{
//	//setup hint trigger 	
//	trigger_use_ladder_dismount = getEnt( "trigger_use_ladder_dismount", "targetname" ); 
//	trigger_use_ladder_dismount setHintString( &"EMBASSY_HINTSTR_LADDER_DISMOUNT");
//
//	//wait until hits "use" key
//	trigger_use_ladder_dismount waittill("trigger");
//	trigger_use_ladder_dismount trigger_off();
//	
//	//custom animation of player moving to rooftop
//	//teleport squad up to roof
//	aSquadNodes = getnodearray("squadWarp_library", "targetname");
//	level thread skipWarpSquad("library");
//	
//	//delete bravo back in drawing room for now in case any left
//	level thread npcDelete("volume_drawing_room", "allies");	
//	
//	//delete barricade so they can exfil later
//	eBarricade_reception_1 = getent("barricade_reception_1", "targetname");
//	eBarricade_reception_1 hideMe();
//	
//	//create death trigger at bottom of shaft and delete ladder
//	eElevator_ladder = getent("elevator_ladder", "targetname");
//	eElevator_ladder hideMe();
//	eTrig_hurt_elevator = getent("trig_hurt_elevator", "targetname");
//	eTrig_hurt_elevator trigger_on();
//	
//}

trig_ladder_dismount()
{
	trigger = getEnt( "trig_ladder_dismount", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//delete bravo back in drawing room for now in case any left
	level thread npcDelete("volume_drawing_room", "allies");	

	//delete barricade so they can exfil later
	eBarricade_reception_1 = getent("barricade_reception_1", "targetname");
	eBarricade_reception_1 hideMe();
	
	//create death trigger at bottom of shaft and delete ladder
//	eElevator_ladder = getent("elevator_ladder", "targetname");
//	eElevator_ladder hideMe();
//	eTrig_hurt_elevator = getent("trig_hurt_elevator", "targetname");
//	eTrig_hurt_elevator trigger_on();
	
}


trig_enter_elevator_rooftop()
{
	trigger = getEnt( "trig_enter_elevator_rooftop", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("elevator_rooftop_reached");
	
	flood_spawn(getentarray("hostiles_library_foyer", "targetname"));
	
	//Make other dudes vulnerable, but give them a fair amount of health
	level.bravo_stairwell.health = 500;
	level.bravo_mezzanine_1.health = 500;
	level.bravo_stairwell invulnerable(false);
	level.bravo_mezzanine_1 invulnerable(false);
	
}

trig_squad_advance_rooftop_1()
{
	trigger = getEnt( "trig_squad_advance_rooftop_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
}

trig_squad_advance_rooftop_2()
{
	trigger = getEnt( "trig_squad_advance_rooftop_2", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
}

trig_squad_advance_rooftop_3()
{
	trigger = getEnt( "trig_squad_advance_rooftop_3", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();

	//setip C4 in bathroom
	eC4trigger = getent("trig_use_foyer_c4", "targetname");
	eC4trigger thread c4_think();
	
	flood_spawn(getentarray("hostiles_library_foyer2", "targetname"));
}

trig_enter_library_foyer()
{
	trigger = getEnt( "trig_enter_library_foyer", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("library_foyer_reached");
}

trig_foyer_frontdoor_approach()
{
	
	trigger = getEnt( "trig_foyer_frontdoor_approach", "targetname" );
	trigger trigger_on();
	trigger waittill ( "trigger" ); 
	trigger trigger_off();
	
	
	flag_set("player_approaching_foyer_frontdoor");
	
	level thread door_close("door_libraryfoyer");
}
trig_foyer_sidedoor_approach()
{
	trigger = getEnt( "trig_foyer_sidedoor_approach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	flag_set("player_approaching_foyer_sidedoor");
}

foyer_door_slam()
{
	// Wait till all ai dead, or player is really close to door
	while ( (!flag("library_foyer_cleared")) && (!flag("player_approaching_foyer_sidedoor")) )
	{
		wait (0.05);
	}
	
	level thread door_close("door_libraryhallway");
	
	
}

trig_approach_library_sidehall()
{
	trigger = getEnt( "trig_approach_library_sidehall", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//spawn guys running across hall to library
	aHostiles_library_door = level spawnGroup(getEntArray("hostiles_library_door", "targetname"));
	array_thread(aHostiles_library_door, ::goToNodeAndDelete, "node_library_delete");	
	
	flag_wait("player_approaching_foyer_sidedoor");
	wait(.5);
	npcDelete("volume_library", "all");	
	
	//stop spawning dudes and wait for all ai to be dead
	aHostiles = getAIarrayTouchingVolume("axis", "volume_library_and_foyer");
	waittill_dead (aHostiles);
		
	flag_set("library_foyer_cleared");

	level thread AA_lib_assault_init();

}

/****************************************************************************
    LIBRARY ASSAULT
****************************************************************************/
	
AA_lib_assault_init()
{	
	level thread library_door_breach();
	level thread library_shootout();	
	level thread trig_enter_library_breach();
	level thread trig_lib_advance_1();
}

library_door_breach()
{
	
//	//Send jack to check door and get friendlies to proper positions
//	triggerActivate("trig_colornodes_foyerbreach");
//	
//	eDoor = getent("origin_library_camera_check", "targetname");
//	level.jack thread door_check(eDoor, 4);
//	level.jack waittill ("door_check_reached");
//	wait(2);
//	flag_wait("player_approaching_foyer_sidedoor");
//	level.jack notify ("door_check_signal");	
//	level.jack waittill ("door_check_signals_complete");
//	level.jack notify ("door_check_stop");
//	level.jack waittill ("door_check_complete");
//	
//	//jack
//	//"Can?t tell if it?s booby-trapped. However I do see 3 bad guys clustered right around the corner there."	
//	level.jack dialogue_thread("embassy_jack_librarydoorbreach");
	
	
	//gaz
	//"Andy, get a charge on that position."
	level.gaz queue_anim("embassy_gaz_breachlibrarywall2");	
	flag_set("library_breach_objective_given");
	level thread obj_library_breach();
	
	
	//spawn guys inside library and have them stay put
	level thread ai_setup_library_interior();
	
	//setup C4 on wall
	eC4trigger = getent("trig_use_library_c4", "targetname");
	eC4trigger thread c4_think();
	
	eC4trigger waittill ("c4_has_been_detonated");

	//Kill the guys at the door
	level.library_breach_dude_1 killEntity();
	level.library_breach_dude_2 killEntity();
	
	flag_set ("obj_library_breach_complete");
	flag_set("library_breached");	
		
	//have friendlies go to nodes and yell at human shield guy
	level thread human_shield_friendlies("nodes_frnd_humanshield_library_1");
	
}

ai_setup_library_interior()
{
	//get names for the 2 guys who will be breach fodder
	level.library_breach_dude_1 = level spawnDude(getEnt("library_breach_dude_1", "script_noteworthy"));
	level.library_breach_dude_2 = level spawnDude(getEnt("library_breach_dude_2", "script_noteworthy"));
	
	//1st Human shield pair
	level thread human_shield_spawn("humanshield_library_1");
	
	level waittill("human_shield_terrorist_dead");
	
	//have friendlies go to nodes and yell at human shield guy
	level thread human_shield_friendlies("nodes_frnd_humanshield_library_2");
	

}

trig_enter_library_breach()
{
	trigger = getEnt( "trig_enter_library_breach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
}

library_shootout()
{
	flag_wait ("library_breached");
	

	
	//wait till last human shield pair is spawned
	flag_wait("library_final_humanshield_spawned");
	
	//Wait until there are no more hostiles
	aHostiles = getAIarrayTouchingVolume("axis", "volume_library");
	waittill_dead(aHostiles);
	
	flag_set ("obj_sniper_assault_complete");
	
	autosave_by_name ("library assault complete");
	
	level thread AA_final_battle_init();
}

trig_lib_advance_1()
{
	trigger = getEnt( "trig_lib_advance_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	
	//spawn next human shield pair
	level thread human_shield_spawn("humanshield_library_2");	
	
	//wait till this terrorist dies, then activate next trigger/thread
	level waittill ("human_shield_terrorist_dead");
	
	//colornodes
	triggerActivate("trig_lib_advance_2");
	
	//gaz
	//"Sniper is on the upper balcony. Get up there and sort him out, Andy."
	level.gaz thread queue_anim("embassy_gaz_gettoupperbalcony");
	
	//Last human shield pair
	level thread human_shield_spawn("humanshield_library_3");	
	flag_set("library_final_humanshield_spawned");
	
	//last hostiles
	level spawnGroup(getEntArray("hostiles_library_wave1", "targetname"));	
}

/****************************************************/
/**************** FINAL BATTLE FUNCTIONS ************/
/****************************************************/


AA_final_battle_init()
{
	level thread library_aftermath();
	level thread exit_library();
	level thread trigger_library_floor();
	level thread trig_exit_library_door();
	level thread trig_exit_library_breach();
	level thread trig_approach_library_stairwell();
	//level thread trig_use_sniperrifle_think();
	level thread trig_stairwell_roofaccess_reached();
	level thread trig_enter_vent_roof();
	level thread trig_enter_vent();
	level thread trig_enter_vent_section_1();
	level thread trig_enter_vent_sniper_section();
}

library_aftermath()
{

	//spawn some more friendlies outside in the foyer
	aFriendlies_reinforcements_library = level spawnGroup(getEntArray("friendlies_reinforcements_library", "targetname"));	
	
	//make Gaz go to stairwell and Jack by doorway	
	level thread jack_goes_to_stairwell();
	level.gaz thread forceToNode("node_gaz_library");
			
	//gaz
	//"This is Alpha One, Bravo One you are all clear for Exfil."	
	level.gaz queue_anim("embassy_gaz_bravoonecleartoexfil");	
	
	level thread bravo_exfil();
	
	//brv1
	//"Thanks, Alpha One. Proceeding across courtyard to hostage reception."
	dialogue_radio_thread("embassy_brv1_thanksalpha");

	//gaz
	//"That?s Bravo One exfiling to you, Command."	
	level.gaz queue_anim("embassy_gaz_bravoexfiling");	


	iprintlnbold (&"EMBASSY_HINTSTR_LEVELEND");

	
	//cmd
	//"Negotiations with lead X Ray have gone south...standby."
	//dialogue_radio_thread("embassy_cmd_negotiationsgonebad");
	
	//neg
	//"We are trying to accommodate you but..."
	//dialogue_radio_thread("embassy_neg_tryingtohelp");
	
	//mbg
	//"No! Enough! I still have plenty of Americans to execute. You will bring helicopter now!"
	//dialogue_radio_thread("embassy_mbg_bringheli");	
	
	//neg
	//"Calm down. Now let?s just be reasonable..."
	//dialogue_radio_thread("embassy_neg_calmdown");
	
	//mbg
	//"That?s one hostage dead. I will continue to execute one hostage every 60 seconds until the helicopter arrives..."
	//dialogue_radio_thread("embassy_mbg_executehostage");	
	
	//cmd
	//"Alpha One, you are closest to the position. We'll bring in the heli but DO NOT let the X Rays get mobile. Repeat, hostiles must NOT get mobile."
	//dialogue_radio_thread("embassy_cmd_finalsniperinstructions1");	
	
	//gaz
	//"Andy! You?re up! Need your sniper skills! Get over to the stairwell, we need to get topside."
	//level.gaz thread dialogue_thread("embassy_gaz_gettostairwell");		
	//level thread gaz_goes_to_stairwell();
	//level thread obj_final_boss();
}
bravo_exfil()
{
	aFriendlies_bravo = level spawnGroup(getEntArray("friendlies_bravo", "targetname"));
	for(i=0;i<aFriendlies_bravo.size;i++)
	{
		wait(randomfloatrange(.5, 1.9));
		aFriendlies_bravo[i] goToNodeAndDelete("node_delete_reception");
	}
}


trigger_library_floor()
{
	trigger = getEnt( "trigger_library_floor", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	flag_set("player_on_library_floor");
}

trig_exit_library_door()
{
	level endon ("library_exited");
	trigger = getEnt( "trig_exit_library_door", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();
	level notify ("library_exited");
}
trig_exit_library_breach()
{
	level endon ("library_exited");
	trigger = getEnt( "trig_exit_library_breach", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	level notify ("library_exited");	
}

jack_goes_to_stairwell()
{
	//Jack goes to stairwell door and blocks it
	level.jack thread forceToNode("node_bathroom_door");
	level.jack waittill ("goal");
	
	//Make Jack block the door till player takes rifle
	level.jack.dontavoidplayer = true;
	level.jack pushplayer(true);	
	
	flag_set("jack_ready_by_roof_access");
	
	//Wait till player takes rifle, then step aside
	//flag_wait("player_has_sniper_rifle");	
	
	
	level.jack.dontavoidplayer = false;
	level.jack pushplayer(false);	
	//blockerEnable(getent("door_stairwell_top_blocker", "targetname"), 0);

	level.jack goToNode("node_bathroom_door2");
}

gaz_goes_to_stairwell()
{
	level.gaz thread door_NPC_open("door_libraryfoyer_2", 1, 1);
	level.gaz waittill ("door_has_been_opened");
	level.gaz thread forceToNode("node_bathroom_vent1");
	

	
	level.gaz waittill ("goal");
	triggerEnable("trig_approach_library_stairwell", true);
}	


trig_approach_library_stairwell()
{
	trigger = getEnt( "trig_approach_library_stairwell", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();

	//jack
	//"Better take this."
	level.jack thread queue_anim("embassy_jack_takesniperrifle");	
	
	
}

trig_use_sniperrifle_think()
{
	flag_wait("jack_ready_by_roof_access");
	
	//turn on trigger and wait for user to hit "use" key
	eTrig_use_sniperrifle = getent("trig_use_sniperrifle", "targetname");	
	eTrig_use_sniperrifle trigger_on();
	eTrig_use_sniperrifle setHintString(&"EMBASSY_HINTSTR_TAKERIFLE");
	eTrig_use_sniperrifle waittill("trigger");
	eTrig_use_sniperrifle trigger_off();

	level.player takeallweapons();	
	level.player giveWeapon("m14_scoped");
	level.player giveWeapon("beretta");
	level.player switchToWeapon("m14_scoped");	
	
	flag_set("player_has_sniper_rifle");		
}

exit_library()
{
	level waittill ("library_exited");
}


trig_stairwell_roofaccess_reached()
{
	trigger = getEnt( "trig_stairwell_roofaccess_reached", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	flag_set("stairwell_ladder_reached");
		
	//Gaz heads into vent
	tempDoorHide(getent("door_vent_bathroom", "targetname"));	
	level.gaz setPosture("crouch");
	level.gaz thread forceToNode("node_friendly_sniper_position");	
	
	//gaz
	//"Right, Andy, Lets get up to the roof and see what we can see"
	level.gaz thread queue_anim("embassy_gaz_letsgettoroof");

	//flag_wait("vent_entrance_reached");

	//gaz
	//"Ok, this is what we want. Follow me."
	//level.gaz thread dialogue_thread("embassy_gaz_ventbash");		
	
	
	//level.gaz thread forceToNode("node_friendly_sniper_position");
	level.gaz waittill ("goal");
	
	level.gaz setPosture("prone");
	
}

trig_enter_vent_roof()
{
	trigger = getEnt( "trig_enter_vent_roof", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("vent_entrance_reached");
}

trig_enter_vent()
{
	trigger = getEnt( "trig_enter_vent", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	
	//cmd
	//"We?ll only have one chance here, Alpha One. Both hostiles need to be taken out at the same time."
	dialogue_radio_thread("embassy_cmd_finalsniperinstructions2");
	
}
trig_enter_vent_section_1()
{
	trigger = getEnt( "trig_enter_vent_section_1", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	

	//gaz
	//"I?ll take up position here and we?ll stay in radio contact. Get into position to get a better angle. We?ll need to hit them at the same time."
	level.gaz thread queue_anim("embassy_gaz_getinposition");	
}
trig_enter_vent_sniper_section()
{
	trigger = getEnt( "trig_enter_vent_sniper_section", "targetname" ); trigger waittill ( "trigger" ); trigger trigger_off();	
	flag_set("sniper_position_reached");

	autosave_by_name ("final sniper sequence");
	wait(1);
	//gaz
	//"Right, don?t fire until I give you the OK. We need to take out both X Rays at the same time otherwise we risk losing hostages"
	level.gaz queue_anim("embassy_gaz_sniperinstruct1");
	
	wait(1.5);
	
	level.hostile_final_snipe_1 = spawnDude(getent("hostile_final_snipe_1", "targetname"));
	level.hostile_final_snipe_1 thread hostile_final_snipe_1_think();
	level.hostile_final_snipe_1 thread door_NPC_open("door_roofend", 1, 2);
	level.hostile_final_snipe_1 waittill ("door_has_been_opened");
	level.hostile_final_snipe_1 thread forceToNode("node_final_snipe_1");
	
	//have everyone ignore eachother 
	ignoreEverybody(true);
	
	//gaz
	//"That?s X Ray One mobile on the rooftop. Hold your fire."
	level.gaz queue_anim("embassy_gaz_sniperinstruct2");	
	
	//start heli on its path
	triggerActivate("trig_heli_end_start");	
	
	wait(2);
	//gaz
	//"Waiting on X Ray Two. Helicopter on approach."
	level.gaz queue_anim("embassy_gaz_sniperinstruct3");	
	
	wait(1.5);
	//gaz
	//"That?s the heli landing on the rooftop. Still no sign of X Ray Two. Hold your fire, Andy."
	level.gaz queue_anim("embassy_gaz_sniperinstruct4");	
	
	wait(3.5);
	//gaz
	//"Bloody hell! He?s shot the pilot. Hold your fire Andy, we need to wait for X Ray Two. Hostage safety is priority One."	
	level.gaz queue_anim("embassy_gaz_sniperinstruct5");	

	wait(2);
	level.hostile_final_snipe_2 = spawnDude(getent("hostile_final_snipe_2", "targetname"));
	level.hostile_final_snipe_2 thread hostile_final_snipe_2_think();

	//have everyone ignore eachother 
	ignoreEverybody(true);
	
	wait(1);
	//gaz
	//"That?s it, Andy. We?ll take them on my signal. You take the one on the right, I?ll take the one on the left."
	level.gaz queue_anim("embassy_gaz_sniperinstruct6");	

	wait(3);
	
	flag_set("sniper_order_given");
	level notify ("sniper_order_given");
	
	//gaz
	//"Now, Andy! Take him out!"
	level.gaz queue_anim("embassy_gaz_takehimoutnow");	
	
	flag_wait ("player_killed_correct_sniper");
	flag_set ("obj_final_boss_complete");
	
	//gaz
	//"Nice one, Andy. Good work... Command, this is Alpha One. All X Rays are down. Zero hostage casualties."
	level.gaz queue_anim("embassy_gaz_snipercomplete");	
	
	//cmd
	//"Roger that, Alpha One. All call signs, evacuate the building. Get back to Incident Control and have a brew. Job well done, lads, job well done."
	dialogue_radio_thread("embassy_cmd_jobwelldone");		
	
}

hostile_final_snipe_1_think()
{
	self thread final_snipe_death_monitor();
	
	level endon ("sniper_order_given");
	
	self waittill ("damage",amount,attacker);
	if (attacker == level.player)
		thread snipe_missionfail(1);
}

hostile_final_snipe_2_think()
{

	self waittill ("damage",amount,attacker);
	
	if (attacker == level.player)
		thread snipe_missionfail(0);
}

final_snipe_death_monitor()
{
	level endon ("mission failed");
	
	flag_wait("sniper_order_given");
	
	self waittillDeathOrPainDeath();
	
	flag_set ("player_killed_correct_sniper");
	
	wait(1);
	
	level.hostile_final_snipe_2 killEntity();	
}


snipe_missionfail(iFailureMessage)
{
	level.player endon ("death");

	level notify ("mission failed");

	aFailureMessage = [];
	aFailureMessage[0]["failure_message"] = "@EMBASSY_MISSION_FAILED_SNIPE_WRONG";	
	aFailureMessage[1]["failure_message"] = "@EMBASSY_MISSION_FAILED_SNIPE_TOO_EARLY";		
	aFailureMessage[2]["failure_message"] = "@EMBASSY_FAILED_SNIPE_WAIT";	
	sFailureMessage	= aFailureMessage[iFailureMessage]["failure_message"];

	setDvar("ui_deadquote", sFailureMessage);
	maps\_utility::missionFailedWrapper();
}


/****************************************************/
/**************** OBJECTIVE FUNCTIONS****************/
/****************************************************/
obj_insert()
{
	objective_number = 0;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 1;
		level thread startTimer();
	}
	
	obj_position = getent ("origin_obj_insertion_point_roof", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_INSERT", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("rappel_point_reached");
	new_position = getent ("origin_obj_insertion_point_balcony", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait ("obj_insert_complete");
	
	objective_state (objective_number, "done");

	if (level.usetimer)
	{
		level thread killTimer();
	}	
}
//obj_window_breach()
//{
//	objective_number = 1;
//
//	
//	obj_position = getent ("origin_obj_window_breach", "targetname");
//	objective_add(objective_number, "active", &"EMBASSY_OBJ_WINDOW_BREACH", obj_position.origin);
//	objective_current (objective_number);
//		
//	flag_wait ("obj_window_breach_complete");
//	
//	objective_state (objective_number, "done");
//		
//}
obj_hostage_secure_office_1()
{
	objective_number = 2;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 1.5;
		level thread startTimer();
	}
	obj_position = getent ("origin_obj_officeA_interior", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_HOSTAGE_SECURE_OFFICE_1", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("officeA_cleared");
	new_position = getent ("origin_obj_officeB_door", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("officeB1_cleared");
	new_position = getent ("origin_obj_officeD_door", "targetname");
	objective_position(objective_number, new_position.origin);
	
		
	flag_wait ("obj_hostage_secure_office_1_complete");
	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}

obj_nav_office_north()
{
	objective_number = 3;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = .5;
		level thread startTimer();	
	}
	obj_position = getent ("origin_obj_south_office_exit", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_NAV_OFFICE_NORTH", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("south_office_exit_reached");
	new_position = getent ("origin_obj_north_offices", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait ("obj_nav_office_north_complete");
	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}

obj_hostage_secure_office_2()
{
	objective_number = 4;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 2;
		level thread startTimer();
	}
	obj_position = getent ("origin_obj_officeF_door", "targetname"); 
	objective_add(objective_number, "active", &"EMBASSY_OBJ_HOSTAGE_SECURE_OFFICE_2", obj_position.origin);
	objective_current (objective_number);

	flag_wait("officeF_breached");
	new_position = getent ("origin_obj_officeF_interior", "targetname");
	objective_position(objective_number, new_position.origin);
		
	flag_wait("officeF_cleared");
	new_position = getent ("origin_obj_balcony_flank", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("flanking_balcony_reached");
	new_position = getent ("origin_obj_officeI_interior", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait ("obj_hostage_secure_office_2_complete");
	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}

obj_balcony_flank()
{
	objective_number = 5;
	obj_position = getent ("origin_obj_balcony_flank", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_BALCONY_FLANK", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("obj_hostage_secure_office_2_complete");

	objective_state (objective_number, "done");
	
}

//obj_nav_banquet_hall()
//{
//	objective_number = 6;
//	obj_position = getent ("origin_obj_nav_banquet_hall", "targetname");
//	objective_add(objective_number, "active", &"EMBASSY_OBJ_NAV_BANQUET_HALL", obj_position.origin);
//	objective_current (objective_number);
//	
//	flag_wait ("obj_nav_banquet_hall_complete");
//	
//	objective_state (objective_number, "done");
//}

obj_hostage_secure_banquet()
{
	objective_number = 7;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 2;
		level thread startTimer();
	}
	obj_position = getent ("origin_obj_nav_banquet_hall", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_HOSTAGE_SECURE_BANQUET", obj_position.origin);	
	
	flag_wait ("nav_banquet_hall_complete");
	
	obj_position = getent ("origin_obj_banquet_reception_interior", "targetname");
	objective_current (objective_number);

	flag_wait("banquet_reception_cleared");
	new_position = getent ("origin_obj_banquet_hall_interior", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait ("obj_hostage_secure_banquet_complete");	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}


//obj_banquet_hall_regroup()
//{
//	objective_number = 8;
//	obj_position = getent ("origin_obj_banquet_hall_regroup", "targetname");
//	objective_add(objective_number, "active", &"EMBASSY_OBJ_BANQUET_HALL_REGROUP", obj_position.origin);
//	objective_current (objective_number);
//	
//	flag_wait ("obj_banquet_hall_regroup_complete");	
//	
//	objective_state (objective_number, "done");
//}


obj_bravo_rv()
{
	objective_number = 9;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 1;
		level thread startTimer();
	}
	obj_position = getent ("origin_obj_kitchen_door", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_BRAVO_RV", obj_position.origin);
	objective_current (objective_number);

	flag_wait("kitchen_door_breached");
	new_position = getent ("origin_obj_stairwell_kitchen", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("stairwell_reached");
	new_position = getent ("origin_obj_drawing_room_door", "targetname");
	objective_position(objective_number, new_position.origin);	
		
	flag_wait ("obj_bravo_rv_complete");
	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}
obj_reception_clear()
{
	objective_number = 10;
	
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 1;
		level thread startTimer();
	}
	obj_position = getent ("origin_obj_drawing_room_breach_door", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_RECEPTION_CLEAR", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("drawaing_room_exit_breached");
	new_position = getent ("origin_obj_skylight_access_door", "targetname");
	objective_position(objective_number, new_position.origin);

	flag_wait("skylight_access_door_reached");
	new_position = getent ("origin_obj_skylight_roof", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("skylight_rooftop_reached");
	new_position = getent ("origin_obj_skylight_breach", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait ("obj_skylight_breach_complete");
	new_position = getent ("origin_obj_reception_interior", "targetname");
	objective_position(objective_number, new_position.origin);
	objective_current (objective_number);
	
	flag_wait("obj_reception_clear_complete");
	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}
obj_skylight_breach()
{
	objective_number = 11;
	obj_position = getent ("origin_obj_skylight_breach", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_SKYLIGHT_BREACH", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait ("obj_skylight_breach_complete");
	
	objective_state (objective_number, "done");
}


obj_courtyard_cover()
{
	objective_number = 12;
	obj_position = getent ("origin_obj_courtyard_cover", "targetname");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_COURTYARD_COVER", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait ("obj_courtyard_cover_complete");
	
	objective_state (objective_number, "done");
}

obj_sniper_assault()
{
	//Timed objective
	if (level.usetimer)
	{
		level.stopwatch = 2.5;
		level thread startTimer();
	}
	objective_number = 13;
	obj_position = getent ("origin_obj_elevator_shaft", "targetname");
	
	objective_add(objective_number, "active", &"EMBASSY_OBJ_SNIPER_ASSAULT", obj_position.origin);
	objective_current (objective_number);

	flag_wait("elevator_shaft_reached");
	new_position = getent ("origin_obj_elevator_rooftop", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("elevator_rooftop_reached");
	new_position = getent ("origin_obj_library_hallway", "targetname");
	objective_position(objective_number, new_position.origin);

	flag_wait("player_approaching_foyer_frontdoor");
	new_position = getent ("origin_obj_library_sidehall", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("library_breach_objective_given");
	new_position = getent ("origin_obj_library_breach", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("library_breached");
	new_position = getent ("origin_obj_library_interior", "targetname");
	objective_position(objective_number, new_position.origin);
	objective_current (objective_number);
		
	flag_wait ("obj_sniper_assault_complete");	
	objective_state (objective_number, "done");
	
	if (level.usetimer)
		level thread killTimer();
}

obj_library_breach()
{
	objective_number = 14;
	obj_position = getent ("origin_obj_library_breach", "targetname");
	flag_set("library_breach_objective_given");
	objective_add(objective_number, "active", &"EMBASSY_OBJ_LIBRARY_BREACH", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait ("obj_library_breach_complete");	
	objective_state (objective_number, "done");
}

obj_final_boss()
{	
	objective_number = 15;
	obj_position = getent ("origin_obj_stairwell_ladder", "targetname");
	
	objective_add(objective_number, "active", &"EMBASSY_OBJ_FINAL_BOSS", obj_position.origin);
	objective_current (objective_number);
	
	flag_wait("stairwell_ladder_reached");
	new_position = getent ("origin_obj_vent_entrance", "targetname");
	objective_position(objective_number, new_position.origin);
	
	flag_wait("vent_entrance_reached");
	new_position = getent ("origin_obj_vent_sniper_position", "targetname");
	objective_position(objective_number, new_position.origin);

	flag_wait("sniper_position_reached");
	new_position = getent ("origin_obj_final_boss", "targetname");
	objective_position(objective_number, new_position.origin);
		
	flag_wait ("obj_final_boss_complete");
	
	objective_state (objective_number, "done");
}

/****************************************************************************
    UTILITY FUNCTIONS
****************************************************************************/
AA_Utility()
{
	//Empty function just for easy access in Ultraedit
}


level_think()
{
	//disable/hide any stuff that needs to be disabled
	//level.eWeapon_sniper_final = getent("weapon_sniper_final", "targetname");
	//level.eWeapon_sniper_final hide();
}

/****************************************************************************
    UTILITY FUNCTIONS: HELICOPTERS
****************************************************************************/
blackhawk_spawn(sStartingAnim)
{
	//get starting location for animation
	vStartingOrigin = getstartorigin( level.heliNode.origin, level.heliNode.angles, level.scr_anim["blackhawk"][sStartingAnim]);
	aStartingAngles = getstartangles( level.heliNode.origin, level.heliNode.angles, level.scr_anim["blackhawk"][sStartingAnim]);
	//spawn the heli and put it in the right place
	eBlackhawk = spawn("script_model", (0,0,0));
	eBlackhawk setmodel("vehicle_blackhawk");
	eBlackhawk.angles = aStartingAngles;
	eBlackhawk.origin = vStartingOrigin;
	eBlackhawk.animnme = "blackhawk";
	
	return eBlackhawk;
}

trigWait(sTrig)
{
	trigger = getEnt(sTrig, "targetname" ); 
	trigger waittill ( "trigger" ); 
	trigger trigger_off();
}

blockerEnable(eBlocker, iBool)
{
	switch(iBool)
	{
	case 0:
		eBlocker hide();
		eBlocker notsolid();
		if (eBlocker.spawnflags & 1)
			eBlocker connectpaths();
		break;
	case 1:
		eBlocker show();
		eBlocker solid();
		if (eBlocker.spawnflags & 1)
			eBlocker disconnectpaths();
		break;		
	}
}

c4_think()
{
	// Variables
	eOrigin = getent(self.target, "targetname");assert(isdefined(eOrigin));
	eExploder = getent(eOrigin.target, "targetname");assert(isdefined(eExploder));
	iExploderNum = eExploder.script_exploder;assert(isdefined(iExploderNum));
	
	//spawn a c4 objective model
	eC4obj = spawn("script_model", eOrigin.origin + (0,0,0));
	eC4obj.angles = eOrigin.angles;
	eC4obj setmodel(level.c4model);	
	
	//turn on the trigger and wait
	self trigger_on();
	self setHintString( &"EMBASSY_HINTSTR_DETONATE");
	self usetriggerrequirelookat();
	self waittill("trigger");
	self trigger_off();	
	
	//swap out obj model with real C4 model - TODO
	
	
	//wait for player to hit detonator - TODO
	
		
	//blow up the exploder
	maps\_utility::exploder(iExploderNum);	
	earthquake (0.6, 2, eOrigin.origin, 1000);
	eOrigin thread play_sound_in_space("rocket_explode_default");
	
	//delete c4 model
	eC4obj delete();
	
	self notify ("c4_has_been_detonated");
		
}

//------------set a guy to never be suppressed and have CQB behavior---------------
setCQBbehavior(bool)
{
	self endon ("death");
	
	self.ignoreSuppression = bool;		
}

getAIarrayTouchingVolume(sTeamName, sVolumeName)
{
	if (sTeamName == "all")
		aTeam = getaiarray();
	else
		aTeam = getaiarray(sTeamName);
	eVolume = getent(sVolumeName, "targetname");
	assertEx(isDefined(eVolume), sVolumeName + " does not exist" );
	
	aGuysTouchingVolume = [];
	for(i=0;i<aTeam.size;i++)
	{
		if (aTeam[i] isTouching(eVolume))
			aGuysTouchingVolume[aGuysTouchingVolume.size] = aTeam[i];
	}
	
	return aGuysTouchingVolume;	
}




rappel_balcony(sAnimEnt, eNode)
{
	self endon ("death");
	
	self setgoalpos(self.origin);
	
	eAnimEnt = getent(sAnimEnt, "targetname");
	assertEx(isDefined(sAnimEnt), "Need to specify a valid script_origin for the rappel sequence");	
	
	self set_animname ("guy");
	
	eAnimEnt thread anim_single_solo (self, "rappel_balcony_1");
	
	self waittillmatch("single anim", "end");
	
	self reset_animname();	
		
	self notify ("balcony_rappel_finished");
	
	//Send the little bastard to a node if one is provided
	if (isdefined(eNode))
	{
		self.goalradius = eNode.radius;
		self setgoalnode(eNode);
	}
	else
		self setgoalpos(self.origin);
		 
}



window_rappel_smash(sWindowName, eNode, bIsBalconyOrSkylight)
{
	
	self endon ("death");
	
	//give a little more health since they are coming in blind
	self.health = 500;
	//make invulnerable until on ground
	self invulnerable(true);
	
	if (!isdefined(bIsBalconyOrSkylight))
		bIsBalconyOrSkylight = false;
	
	self.ignoreme = true;
	
	
	eWindow = undefined;
	eWindow_anim_ent = undefined;
	sAnim = "";
	
	//find window name if it's a window smash
	if (bIsBalconyOrSkylight == false)  //Window tarzaner...will be targeting window, which will target origin
	{
		eWindow = getent(sWindowName, "targetname");
		eWindow_anim_ent = getent(eWindow.target, "targetname");
		assertEx(isDefined(eWindow), "There is no window with this targetname");	
		assertEx(isDefined(eWindow_anim_ent), "Window needs to target a valid script_origin.");			
	}
	else  //Balcony or skylight spawner...will be targeting origin directly
	{
		eWindow_anim_ent = getent(self.target, "targetname");
	}

	
	if ( !isdefined( self.old_animname ) )
		self.old_animname = self.animname;
	self.animname = "guy";	

	if (bIsBalconyOrSkylight == true)
	{
		//decide which anim to play
		if (issubstr(eWindow_anim_ent.script_noteworthy, "skylight_banquet"))
			sAnim = "rappel_skylight_drop";	
		else
			sAnim = "rappel_balcony_1";		
	}
		
	else  //Not a balcony or skylight...play the regular window smash tarzan
		sAnim = "rappel";
	
	
	//Play the damned animation already
	eWindow_anim_ent thread anim_single_solo (self, sAnim);
		
	
	if (bIsBalconyOrSkylight == false)
	{
		self waittillmatch("single anim", "kick");
		eWindow thread window_smash();		
	}

	self waittillmatch("single anim", "end");
	
	self.animname = self.old_animname;
	
	self notify ("window_rappel_finished");
	
	self.ignoreme = false;
	self invulnerable(false);
	
	//Check if the origin is targeting a node
	if ( (!isDefined(eNode)) && (isdefined(eWindow_anim_ent.target)) )
	{
		eNode = getnode(eWindow_anim_ent.target, "targetname");
		assertEx(isDefined(eNode), "The window origin is not targeting a valid node");
	}
	
	//Send the little bastard to a node if one is provided
	if (isdefined(eNode))
	{
		self.goalradius = eNode.radius;
		self setgoalnode(eNode);
	}
}

window_smash()
{
	self playsound ("glass_break");
	self hide();
	self notsolid();
	if (self.spawnflags & 1)
		self connectpaths();

}


// delete all ai touching a given volume - specify 'all' 'axis' 'allies' or 'neutral'
npcDelete(sVolumeName, sNPCtype, boolKill, aExclude)
{
	// For now, always exclude Jack and Gaz just to be sure
	if(!isdefined(aExclude))
	{
		aExclude = [];
		aExclude[0] = level.gaz;
		aExclude[1] = level.jack;
	}
	
	volume = getEnt( sVolumeName, "targetname" );		
	assertEx(isdefined(volume), sVolumeName + " volume does not exist");
	
	if (!isdefined(boolKill))
		boolKill = false;
	
	ai = undefined;
	if (sNPCtype == "all")
		ai = getaiarray();
	else
		ai = getaiarray(sNPCtype);
	assertEx(isdefined(ai), "Need to specify 'all' 'axis' 'allies' or 'neutral' for this function");
	
	//If an array was passed of dudes to exclude, remove them from the array
	if (isdefined(aExclude))
	{
		for(i=0;i<aExclude.size;i++)
		{
		if (is_in_array(ai, aExclude[i]))
			ai = array_remove(ai, aExclude[i]);
		}		
	}
	
	
	for(i=0;i<ai.size;i++)
	{
		if(ai[i] isTouching(volume))
			{
				//regardless of what we do, turn off magic bullet shield
				ai[i] invulnerable(false);
				//decide weather to kill or delete
				if (boolKill == true)
					ai[i] dodamage (ai[i].health + 100, (0,0,0));
				else
					ai[i] delete();
			}
			
	}
}



retreatToVolume(aGuys, sVolumeName)
{
	goalVolume = getEnt( sVolumeName, "targetname" );
	goalNode = getNode( goalVolume.target, "targetname" );
	assert(isDefined(goalVolume));
	assert(isDefined(goalNode));
			
	for(i=0;i<aGuys.size;i++)
	{
		aGuys[i] setGoalNode( goalNode );
		aGuys[i] setGoalVolume( goalVolume );
		aGuys[i].goalradius = goalNode.radius;
	}
}

retreatToNodes(aGuys, sNodes)
{
	aNodes = getnodearray(sNodes, "targetname");
	assert(isdefined(aNodes));
	
	for(i=0;i<aGuys.size;i++)
	{
		if (!isdefined(aGuys[i]))
			return;
		if (!isalive(aGuys[i]))
			return;
		if(isdefined(aNodes[i]))
		{
			aGuys[i] setgoalnode (aNodes[i]);
		}
		else
			assertmsg("not enough nodes for retreaters");
	}
}


getDudeFromArray(aSpawnArray, sScript_Noteworthy)
{
	dude = undefined;
	//loop through the array and find the guy with that script_noteworthy	
	for(i=0;i<aSpawnArray.size;i++)
	{
		if (isDefined(aSpawnArray[i].script_noteworthy) && aSpawnArray[i].script_noteworthy == sScript_Noteworthy)
			dude = aSpawnArray[i];			
	}
	
	assertEX(isdefined(dude), sScript_Noteworthy + " does not exist in this array");
	//Return a reference to the guy
	return dude;
}

getDudesFromArray(aSpawnArray, sScript_Noteworthy)
{
	aDudes = [];
	//loop through the array and find the guy with that script_noteworthy	
	for(i=0;i<aSpawnArray.size;i++)
	{
		if (isDefined(aSpawnArray[i].script_noteworthy) && aSpawnArray[i].script_noteworthy == sScript_Noteworthy)
			aDudes[aDudes.size] = aSpawnArray[i];			
	}

	return aDudes;
}




breachSetup(room)
{
	//get node names on either side of door
	nodeLeft = getNode(room + "_breach_1", "script_noteworthy");
	assertEX(isdefined(nodeLeft), room + "_breach_1 does not exist");
	nodeRight = getNode(room + "_breach_2", "script_noteworthy");
	assertEX(isdefined(nodeRight), room + "_breach_1 does not exist");
	
	//make squad unaware and send them to positions
	aSquad = getSquadArray();
	array_thread(aSquad, ::makeUnaware,true);

	old_goalradius_gaz = level.gaz.goalradius;
	old_goalradius_jack = level.jack.goalradius;
	
	level.gaz.goalradius = 8;
	level.gaz setgoalnode(nodeLeft);
	level.gaz pushplayer(true);

	level.jack.goalradius = 8;
	level.jack setgoalnode(nodeRight);
	level.jack pushplayer(true);
	
	level.gaz waittill("goal");
	level.jack waittill("goal");
	level.gaz pushplayer(false);
	level.jack pushplayer(false);	
		
	array_thread(aSquad, ::makeUnaware,false);	
	level notify (room + "_ready_to_be_breached");
	
	level.gaz.goalradius = old_goalradius_gaz;
	level.jack.goalradius = old_goalradius_jack;	
}





goToNode(sNode)
{
	self endon ("death");
	
	node = getnode(sNode, "targetname");
	assertEx(isdefined(node), sNode + "node does not exist");
	
	self setGoalRadius(node.radius);	
	self setgoalnode(node);
	
	self waittill ("goal");
	self resetGoalRadius();
}

goToNodeAndDelete(sNode)
{
	if (!isdefined(self))
		return;
	if (!isalive(self))
		return;
		
	self endon ("death");
	
	node = getnode(sNode, "targetname");
	assert(isdefined(node));
	
	self setgoalnode(node);
	self setGoalRadius(node.radius);	
	
	self waittill ("goal");
	
	self delete();
}

goToNodeAndWait(sNode)
{
	if (!isdefined(self))
		return;
	if (!isalive(self))
		return;
		
	self endon ("death");
	
	eNode = getnode(sNode, "targetname");
	assert(isdefined(eNode));
	
	self setgoalnode(eNode);
	self setGoalRadius(eNode.radius);	
	
	self waittill ("goal");
	
	self set_animname("guy");
	self holdPosition(true);
	
	self waittill ("stop_waiting_at_node");
	
	self holdPosition(false);
	self resetGoalRadius();
	
}


NPC_Blocker(sNode)
{
	self endon ("death");
	
	eNode = getnode(sNode, "targetname");
	eBlocker = getent(eNode.target, "targetname");
	eNodeAfter = getnode(eBlocker.target, "targetname");
	assert(isdefined(eNode));
	assert(isdefined(eBlocker));

	self setGoalRadius(8);		
	self makeUnaware(true);
	self pushplayer(true);

	self setgoalnode(eNode);
	
	self waittill("goal");
	blockerEnable(eBlocker, 1);
	
	self waittill ("stop_blocking");
	
	blockerEnable(eBlocker, 0);
	self makeUnaware(false);
	self pushplayer(false);
	
	self resetGoalRadius();
	self waittill ("goal");
	
	if (isdefined(eNodeAfter))
		self setgoalnode(eNodeAfter);
}

forceToNode(sNode)
{
	self endon ("death");
	
	self setGoalRadius(8);
		
	node = getnode(sNode, "targetname");
	assertEx(isdefined(node), sNode + "node does not exist");
	self makeUnaware(true);
	self pushplayer(true);

	self setgoalnode(node);
	
	self waittill("goal");
	
	self makeUnaware(false);
	self pushplayer(false);
	
	self resetGoalRadius();

}

triggerEnable(triggerName, bool)
{
	assertEX(isdefined(bool), "Must specify true/false parameter for triggerEnable() function");
	trig = getent(triggername, "targetname");
	assertEx(isDefined(trig), triggerName + " does not exist");
	if (bool == true)
		trig trigger_on();
	else
		trig trigger_off();
}

triggerActivate(sTriggerName)	// Activate a trigger, then delete it
{
	eTrig = getent(sTriggerName, "targetname");
	assert(isdefined(eTrig));
	eTrig notify ("trigger");
	eTrig trigger_off();
	
}

friendlyChainUpdate(chainName)
{
	newChain = getnode(chainName,"targetname");
	assertEx(isDefined(newChain), chainName + " friendlychain does not exist");	
	level.player setFriendlyChain(newChain);
	
	//loop through all spawned ai with the targetname "squad" and put them in an array "aSquad"
	aSquad = getSquadArray();

	//Put the whole squad on the friendlychain	
	array_thread(aSquad, ::putOnChain);
}

getSquadArray()
{
	//loop through all spawned ai with the targetname and script_noteworthy "squad" and put them in an array "aSquad"
	aSquad = [];

	aExistingAllies = getaiarray();		//needs to be all AI since some friendlies may be set to unaware or "neutral"
	for(i=0;i<aExistingAllies.size;i++)
	{
		//check to see that both targetname AND script_noteworthy don't BOTH have "squad
		if (isDefined(aExistingAllies[i].targetname) && isDefined(aExistingAllies[i].script_noteworthy))
		{
			if (aExistingAllies[i].targetname == "squad" && aExistingAllies[i].script_noteworthy == "squad")
				assertmsg("AI cannot have both 'targetname' and 'script_noteworthy' set to 'squad'....it'll screw things up");
		}
			
		//check targetname
		if (isDefined(aExistingAllies[i].targetname) && aExistingAllies[i].targetname == "squad")
			aSquad[aSquad.size] = aExistingAllies[i];
		
		//check script_noteworthy
		else if (isDefined(aExistingAllies[i].script_noteworthy) && aExistingAllies[i].script_noteworthy == "squad")
			aSquad[aSquad.size] = aExistingAllies[i];
		
	}

	return aSquad;
}

putOnChain(guy)
{
	if (!isdefined (guy))
		guy = self;
		
	guy.followmin = level.followmin;
	guy.followmax = level.followmax;
	guy setgoalentity (level.player);
}

makeUnaware(bool)
{
	if (bool == true)
	{
		self set_forcegoal();
		self.grenadeawareness = 0;
		self.ignoreme = true;
		level thread print3Dthread(self, "unaware and ignored");
	}
	else
	{
		self unset_forcegoal();
		self.grenadeawareness = 1;
		self.ignoreme = false;	
		level thread print3Dthread(self, "");	
	}
}

tempDoorHide(door)
{
	assert(isdefined(door));
	door hide();
	door notsolid();
	door connectpaths();
}

/****************************************************************************
    UTILITY FUNCTIONS: HOSTAGE HUMAN SHIELD
****************************************************************************/

human_shield_spawn(sTargetname)
{
	//Spawn pair and get pointers to them
	aShieldPair = level spawnGroup(getEntArray(sTargetname, "targetname"));
	assertEx(aShieldPair.size == 2, "Human shield array must have exactly 2 members");
	eTerrorist = undefined;
	eHostage = undefined;
	
	for(i=0;i<aShieldPair.size;i++)
	{
		aShieldPair[i].ignoreme = true;
		
		if (aShieldPair[i].team == "axis")
			eTerrorist = aShieldPair[i];			
		else
			eHostage = aShieldPair[i];
	}
	//get the node where they will play animations
	eTargetNode = getnode(eTerrorist.target, "targetname");
	
	//Have terrorist and hostage setup and play looping anims
	eHostage thread human_shield_think("hostage", eTargetNode);
	eTerrorist thread human_shield_think("terrorist", eTargetNode);
	
	//deal with player shooting hostage
	eHostage thread kill_hostage_human_shield_mission_fail_think(eTerrorist);
	
	//deal with player shooting terrorist
	eTerrorist thread human_shield_ter_wound_think(eHostage);
	eTerrorist thread human_shield_ter_kill_think(eHostage);
	eTerrorist thread human_shield_ter_death_monitor();
	
	//deal with player approaching terrorist (blindfire)
	eTerrorist thread human_shield_blindfire_think(eHostage, eTargetNode);
	
}

human_shield_blindfire_think(eHostage, eNode)
{
	self endon ("human_shield_over");
	eHostage endon ("human_shield_over");
	
	iDialogueNum = 0;
	
	while (true)
	{
		wait(0.05);
		
		vPlayerOrg = level.player.origin;
		vEnemyOrg = self.origin;
		if (distance (vPlayerOrg, vEnemyOrg) < 200)
		{
			iDialogueNum ++;
			//when player is within range, play blindfire and dialogue			
			//self thread dialogue_thread("embassy_ter_humanshieldbackoff" + iDialogueNum);
			
			self notify("stop_idle");
			self thread anim_single_solo (self, "human_shield_duck_blindfire", undefined, eNode); 
			self.allowdeath = true;
			
			eHostage notify("stop_idle");
			eHostage thread anim_single_solo (eHostage, "human_shield_duck_blindfire", undefined, eNode); 
			self.allowdeath = true;
			
			self waittillmatch("single anim", "end");
			
			//go back to playing looping anim
			self thread anim_loop_solo(self, "human_shield_idle", undefined, "stop_idle", eNode);
			self.allowdeath = true;
			eHostage thread anim_loop_solo(eHostage, "human_shield_idle", undefined, "stop_idle", eNode);
			eHostage.allowdeath = true;
			
			//reset dialogue num to zero if at end
			if (iDialogueNum == 4)
				iDialogueNum = 0;
			
			wait(randomfloatrange(1.5, 3));
		}
	}

}


kill_hostage_human_shield_mission_fail_think(eTerrorist)
{
	self endon ("human_shield_over");
	
	//self = hostage
	level endon ("mission failed");
	
	self waittill ("death", attacker);
	
	self notify ("stop_idle");
	
	if (!isdefined (attacker))
			return;
	if (attacker == level.player)	
	{
		level thread killhostage_missionfail();
		eTerrorist thread human_shield_reset_ai("terrorist", 2); //<----2 is the number that cooresponds to appropriate anim to play b4 restoring normal AI
	}		
}

human_shield_ter_wound_think(eHostage)
{
	self endon ("death");
		
	self waittill ("damage",amount,attacker);
	
	if (!isdefined (self))
		return;
	
	//restore ai on both terrorist and hostage
	self thread human_shield_reset_ai("terrorist", 1); //<----1 is the number that cooresponds to appropriate anim to play b4 restoring normal AI
	eHostage thread human_shield_reset_ai("hostage", 1);
}

human_shield_ter_kill_think(eHostage)
{
	self endon ("human_shield_over");
	
	self waittillDeathOrPainDeath();

	//restore default AI on hostage
	eHostage thread human_shield_reset_ai("hostage", 0);  //<----0 is the number that cooresponds to appropriate anim to play b4 restoring normal AI (running away)		
}

human_shield_ter_death_monitor()
{
	self waittillDeathOrPainDeath();
	
	level notify ("human_shield_terrorist_dead");
}


waittillDeathOrPainDeath()
{
	self endon ("death");
	self waittill ("pain_death"); // pain that ends in death
}

human_shield_think(sAItype, eTargetNode)
{
	//Setup AI of terrorist and hostage and play looping anim
	self endon ("death");
	
	self.pushplayer = true;
	
	switch(sAItype)
	{
	case "hostage":
		self.animname = "hostage";
		self set_deathanim(%hostage_human_shield_host_death);
		self.team = "neutral";
		self.pacifist = 1;
		self.health = 200;	
		self.pathenemyfightdist = 8;
		self.pathenemylookahead = 8;
		self.maxsightdistsqrd = 1;	
		self setFlashbangImmunity( true );
		break;
	case "terrorist":
		self.animname = "guy";
		self set_deathanim(%terrorist_human_shield_ter_death);
		self setFlashbangImmunity( true );
		//self animscripts\shared::putGunInHand ("none");
		
		break;
	}

	//Play looping human shield animation
	self thread anim_loop_solo(self, "human_shield_idle", undefined, "stop_idle", eTargetNode);
	self.allowdeath = true;
	
	
	
	
}


human_shield_flashbang_think()
{
	
}

human_shield_proximity_think()
{
	
}

human_shield_reset_ai(sAItype, iAnim)
{
	self notify ("human_shield_over");
	
	if (!isdefined (self))
		return;
	
	self endon ("death");

	self reset_deathanim();
	self.pushplayer = false;
	
	//Decide which anim to play (if any)
	aAnim = [];
	aAnim[0]["ending_anim"] = "human_shield_ter_death";		//terrorist is dead, hostage runs away (HOSTAGE ONLY)
	aAnim[1]["ending_anim"] = "human_shield_ter_pain";		//terrorist wounded, hostage runs away
	aAnim[2]["ending_anim"] = "human_shield_host_death";	//hostage killed, terrorist recolis    (TERRORIST ONLY)
	sAnim	= aAnim[iAnim]["ending_anim"];
		
	//play the animation if there is one, then go back into normal AI
	if (isdefined(iAnim))
	{
		self notify ("stop_idle");
		self thread anim_single_solo (self, sAnim, undefined);
		self.allowdeath = true;
		self waittillmatch("single anim", "end");
	}
		
	switch(sAItype)
	{
	case "hostage":
		//put hostage-specific stuff here
		self thread kill_hostage_mission_fail_think();
		self setGoalRadius(0);
		self.setGoalPos = self.origin;
		self allowedstances("prone");
		wait(2);
		self allowedstances("crouch","stand","prone");
		break;
	case "terrorist":
		//put terrorist-specific stuff here
		//self.ignoreme = false;
		break;
	}	
}

human_shield_friendlies(sNodeName)
{
	aFriendlies = [];
	aFriendlies[0] = level.gaz;
	aFriendlies[1] = level.jack;
	aNodes = getnodearray(sNodeName, "targetname");
	assert(isdefined(aNodes));
		
	for(i=0;i<aFriendlies.size;i++)
		aFriendlies[i] thread human_shield_frnd_think(aNodes[i]);
	
}

human_shield_frnd_think(eNode)
{
	self setGoalRadius(eNode.radius);	
	self setgoalnode(eNode);
	
	level waittill ("human_shield_terrorist_dead");
	//self waittill ("goal");
		
	self resetGoalRadius(); 
}

/****************************************************************************
    UTILITY FUNCTIONS: HOSTAGES
****************************************************************************/
hostage_think()
{
	self thread kill_hostage_mission_fail_think();
	
	self endon ("death");
	self.animname = "hostage";
	self.team = "neutral";
	self.pacifist = 1;
	self.health = 200;	
	self setFlashbangImmunity( true );
	self.pathenemyfightdist = 8;
	self.pathenemylookahead = 8;
	self.maxsightdistsqrd = 1;

	//self animscripts\shared::PutGunInHand("none");
	//self.hasWeapon = 0;
	
	eTarget = undefined;
	eTargetNode = undefined;
	sAnim_Name = undefined;
	sAnim_Name_Flinch = undefined;
		
	//check to see if hostage is targeting a node or model
	if (isdefined(self.target))
	{
		eTarget = getent(self.target, "targetname");
		eTargetNode = getnode(self.target, "targetname");
	}
	
	// HOSTAGE PATHNODE TARGET: If the hostage is target ing a node, play a looping anim if one is specified
	if ( (isdefined(eTargetNode)) && (isdefined(eTargetNode.script_noteworthy)) )
	{
		// Figure out which anim is in the node (if any)
		switch(eTargetNode.script_noteworthy)
		{
			case "kneel":
				sAnim_Name = "hostage_knees_idle";
				sAnim_Name_Flinch = "hostage_knees_twitch";
				self thread hostage_idle_and_flinch(sAnim_Name, sAnim_Name_Flinch, eTargetNode, true);
				break;
			case "prone":
				sAnim_Name = "hostage_facedown_idle";
				sAnim_Name_Flinch = "hostage_facedown_twitch";
				self thread hostage_idle_and_flinch(sAnim_Name, sAnim_Name_Flinch, eTargetNode, true);
				break;	
			case "fetal":
				sAnim_Name = "hostage_fetal_idle";
				sAnim_Name_Flinch = "hostage_fetal_roll";
				self thread hostage_idle_and_flinch(sAnim_Name, sAnim_Name_Flinch, eTargetNode, true);
				break;	
			case "run_and_cower":
				self thread hostage_run_and_cower(eTargetNode);
				break;
		}		
	}
			

	
	
	// HOSTAGE SCRIPT_MODEL TARGET: If the hostage is targeting a model, play a looping anim if one is specified
	if ( (isdefined(eTarget)) && (eTarget.classname == "script_model") && (isdefined(eTarget.script_noteworthy)) )
	{
		// this ent is needed for animations
		eAnimEnt = spawn( "script_origin", eTarget.origin);
		eAnimEnt.angles = eTarget.angles;
		assert(isdefined(eAnimEnt));
		
		// Figure out what model the hostage is targeting, and play appropriate anim
		switch(eTarget.script_noteworthy)
		{
			case "chair":
				sAnim_Name = "hostage_chair_idle";
				sAnim_Name_Flinch = "hostage_chair_twitch";
				self thread hostage_idle_and_flinch(sAnim_Name, sAnim_Name_Flinch, eAnimEnt);
				break;
			case "table":
				//
				//
				break;	
		}	
		
	}



}



hostage_run_and_cower(eNode)
{
	self endon ("death");
	
	self.goalradius = eNode.radius;
	self setgoalnode(eNode);	
	self waittill ("goal");
	
	self holdPosition(true, "crouch");
}

hostage_idle_and_flinch(sAnim_Name, sAnim_Name_Flinch, eTarget, bIsNode)
{
	self endon ("death");
	
	if (!isdefined(bIsNode))
		bIsNode = false;
	sAnimType = undefined;
	assert(isdefined(eTarget));
	
	if (bIsNode == true)
		self thread anim_loop_solo(self, sAnim_Name, undefined, "stop_idle", eTarget);		

	else
		eTarget thread anim_loop_solo(self, sAnim_Name, undefined, "stop_idle");		

	//	anim_loop_solo( guy, anime, tag, ender, node, tag_entity )

	self.allowdeath = true;
	
	//use int to determine which flinch to play
	iFlinchNumber = 0;
	
	if (isdefined(sAnim_Name_Flinch))
	{
		while (true)
		{
			iFlinchNumber++;			
			
			wait (randomfloatrange(3.5,8));
			if (bIsNode == true)
				self notify ("stop_idle");
			else
				eTarget notify ("stop_idle");
			
			//play either the flinch or the alternate flinch
			if (iFlinchNumber == 1)
				self anim_single_solo (self, sAnim_Name_Flinch);
			else
			{
				self anim_single_solo (self, sAnim_Name_Flinch + "2");
				iFlinchNumber = 0;
			}
			
			self waittillmatch("single anim", "end");
			
			if (bIsNode == true)
				self thread anim_loop_solo(self, sAnim_Name, undefined, "stop_idle", eTarget);
			else 
				eTarget thread anim_loop_solo(self, sAnim_Name, undefined, "stop_idle");	
				
			
		}		
	}

}


kill_hostage_mission_fail_think()
{
	level endon ("mission failed");
	
	self waittill ("death", attacker);
	
	self notify ("stop_idle");
	
	if (!isdefined (attacker))
			return;
	if (attacker == level.player)
		thread killhostage_missionfail();	
}

killhostage_missionfail()
{
	level.player endon ("death");

	level notify ("mission failed");
	
	setDvar("ui_deadquote", "@EMBASSY_MISSION_FAILED_HOSTAGE_KILLED");
	maps\_utility::missionFailedWrapper();
}



/****************************************************************************
    UTILITY FUNCTIONS: SPAWNING
****************************************************************************/
spawned_dead_guy_think()
{
	self endon ("death");
	
	self invulnerable(true);
	self.ignoreme = true;
	self setFlashbangImmunity( true );
	
	eTarget = undefined;
	
	//See if he's targeting a script_origin with animation instructions
	if (isdefined(self.target))
		eTarget = getent(self.target, "targetname");
		
	if ( (isdefined(eTarget)) && (eTarget.classname == "script_origin") && (isdefined(eTarget.script_noteworthy)) )
	{
		
		sAnim = "";
		
		switch(eTarget.script_noteworthy)
		{
			case "window_death":
				sAnim = "death_pose_on_window";
				break;
			case "desk_death":
				sAnim = "death_pose_on_desk";
				break;	
			default:
				assertmsg("this dead guy is targeting a script_origin with no known animation state defined");	
		}
		
		//Make him invincible and play the looping animation
		if (sAnim != "")
		{
			self.animname = "guy";
			eTarget thread anim_loop_solo (self, sAnim, undefined, "stop_idle");
			self.allowdeath = false;	
		}
	
		
	}
	
	
	//Otherwise, just kill the little bastard
	else
		self killEntity();
	
	
	
	
}
spawnDude(eEntToSpawn)
{
	spawnedGuy = eEntToSpawn dospawn();
	spawn_failed( spawnedGuy );
	assert( isDefined( spawnedGuy ) );
	
	//Check to see if this guy is a hostage
	if ( (isdefined(spawnedGuy.script_friendname)) && (spawnedGuy.script_friendname == "Pvt. Hostage") )
		spawnedGuy thread hostage_think();
		
	//Check to see if this guy is an "ambient dead guy" 
	//(kill him as soon as he's spawned for room decor, or have him playing a cool looping death pose
	if ( (isdefined(spawnedGuy.script_noteworthy)) && (spawnedGuy.script_noteworthy == "dead") )
		spawnedGuy thread spawned_dead_guy_think();
		
	//Check to see if he is a window spawner
	if (isdefined(spawnedGuy.target))
	{
		eTarget = getent(spawnedGuy.target, "targetname");
		if ( (isdefined(eTarget)) && (isdefined(eTarget.script_noteworthy)) && (eTarget.script_noteworthy == "window" ) )
			spawnedGuy thread window_rappel_smash(eTarget.targetname);
	}
	
	//Check to see if he is a balcony_rappel spawner
	if (isdefined(spawnedGuy.target))
	{
		eTarget = getent(spawnedGuy.target, "targetname");
		if ( (isdefined(eTarget)) && (isdefined(eTarget.script_noteworthy)) && (eTarget.script_noteworthy == "balcony" ) )
			spawnedGuy thread window_rappel_smash(eTarget.targetname, undefined, true);
	}

	//Check to see if he is a skylight spawner
	if (isdefined(spawnedGuy.target))
	{
		eTarget = getent(spawnedGuy.target, "targetname");
		if ( (isdefined(eTarget)) && (isdefined(eTarget.script_noteworthy)) && (eTarget.script_noteworthy == "skylight_banquet" ) )
			spawnedGuy thread window_rappel_smash(eTarget.targetname, undefined, true);
	}
	
			
	//spawnedGuy.health = 500;
		
	return spawnedGuy;
}

	
spawnGroup(arrayToSpawn)
{
	spawnedGuys = [];
	for (i=0;i<arrayToSpawn.size;i++)
	{
		guy = spawnDude(arrayToSpawn[i]);
		spawnedGuys[spawnedGuys.size] = guy;
		
	}
	//check to ensure all the guys were spawned
	assertEx((arrayToSpawn.size == spawnedGuys.size), "Not all guys were spawned successfully");
	
	//Return an array containing all the spawned guys
	return spawnedGuys;
}




ignoreEverybody(bool)
{
	level thread teamIgnoreMe("axis", bool);
	level thread teamIgnoreMe("allies", bool);
	level.player.ignoreme = bool;	
}

teamIgnoreMe(whichTeam, bool)
{
	team = getaiarray(whichTeam);

	for(i = 0; i < team.size; i++)
		if (bool == true)
		{
			team[i].ignoreme = true;
			level thread print3Dthread(team[i], "ignored");
		}
		else
		{
			team[i].ignoreme = false;	
			level thread print3Dthread(team[i], "");
		}
}

setupPrecache()
{  
	level.c4model = "mil_tntbomb_mp";
	precacheModel(level.c4model);
	
	
	//Models and shaders
	precacheShader("hudStopwatch");
	precacheShader("hudStopwatchNeedle");	
	precacheModel("vehicle_blackhawk");
	
	//Strings: Intro screen
	precacheString(&"EMBASSY_TITLE");
	precacheString(&"EMBASSY_PLACE");
	precacheString(&"EMBASSY_DATE");
	precacheString(&"EMBASSY_INFO");
	
	//Strings: Objectives
	precacheString(&"EMBASSY_OBJ_INSERT");
	precacheString(&"EMBASSY_OBJ_WINDOW_BREACH");
	precacheString(&"EMBASSY_OBJ_HOSTAGE_SECURE_OFFICE_1");
	precacheString(&"EMBASSY_OBJ_HOSTAGE_SECURE_OFFICE_2");
	precacheString(&"EMBASSY_OBJ_BALCONY_FLANK");
	precacheString(&"EMBASSY_OBJ_NAV_BANQUET_HALL");	
	precacheString(&"EMBASSY_OBJ_HOSTAGE_SECURE_BANQUET");
	precacheString(&"EMBASSY_OBJ_BANQUET_HALL_REGROUP");
	precacheString(&"EMBASSY_OBJ_BRAVO_RV");
	precacheString(&"EMBASSY_OBJ_RECEPTION_CLEAR");
	precacheString(&"EMBASSY_OBJ_SKYLIGHT_BREACH");
	precacheString(&"EMBASSY_OBJ_COURTYARD_COVER");
	precacheString(&"EMBASSY_OBJ_SNIPER_ASSAULT");
	precacheString(&"EMBASSY_OBJ_LIBRARY_BREACH");
	precacheString(&"EMBASSY_OBJ_FINAL_BOSS");
	
	//Strings: Hints	
	precacheString(&"EMBASSY_HINTSTR_DETONATE");
	precacheString(&"EMBASSY_HINTSTR_LADDER_DISMOUNT");	
	precacheString(&"EMBASSY_HINTSTR_FASTROPE");	
	precacheString(&"EMBASSY_HINTSTR_TAKERIFLE");	
	precacheString(&"EMBASSY_HINTSTR_FLASHBANG");
	precacheString(&"EMBASSY_HINTSTR_BREACH");
	precacheString(&"EMBASSY_HINTSTR_ROPE_GRAB");
	precacheString(&"EMBASSY_HINTSTR_ROPE_RAPPEL");
	precacheString(&"EMBASSY_EXPLOSIVES_PLANTED");
		
	//Strings: Timer labels
	precacheString(&"EMBASSY_TIMER_LABEL");
	
	//Strings: Mission failure
	precacheString(&"EMBASSY_MISSION_FAILED_GENERIC");
	precacheString(&"EMBASSY_MISSION_FAILED_HOSTAGE_KILLED");
	precacheString(&"EMBASSY_MISSION_FAILED_HOSTAGE_KILLED");
	
	//Dev strings
	precacheString(&"HINTSTR_LEVELEND");
	
}

setupPlayer()
{
	level.player takeallweapons();	
	level.player giveWeapon("flash_grenade");
	level.player giveWeapon("MP5sd");
	level.player giveWeapon("beretta");
	level.player switchToWeapon("MP5sd");
	level.player setOffhandSecondaryClass( "flash" );

	//give unlimited flashbangs for now
	level.player thread unlimitedFlashbangs();
}

unlimitedFlashbangs()
{
    self endon("death");

    while(true)
    {
        level.player giveMaxAmmo("flash_grenade");
        wait(1);
    }	
}



setupCharacters()
{
	level.cmd = level.player;
	level.cmd.animname = "cmd";
	level.sierra = level.player;
	level.sierra.animname = "sierra";
	
	level.gaz = getent("gaz", "script_noteworthy");
	level.gaz.animname = "gaz";
	level.gaz.anim_disablePain = true;
	level.gaz thread maps\_utility::magic_bullet_shield();
	level.gaz.followmax = level.followmax;
	level.gaz setFlashbangImmunity( true );
	//level.gaz.interval = 0;	
	
	level.jack = getent("jack", "script_noteworthy");
	level.jack.animname = "jack";
	level.jack.anim_disablePain = true;
	level.jack thread maps\_utility::magic_bullet_shield();
	level.jack.followmax = level.followmax;
	level.jack setFlashbangImmunity( true );
	//level.jack.interval = 0;	
}

holdPosition(bool, sPostureName)
{	

	self endon ("death");
	
	if (!isdefined(self))
		return;
	if (!isalive(self))
		return;
	if (bool == true)
	{	
		if ( (isdefined(self.holdPos )) && (self.holdPos == true) )
			return;
			
		self.holdPos = true;
//		level thread print3Dthread (self, "holdPos");
//		self set_forcegoal();
//		self setGoalRadius(0);
//		self.setGoalPos = self.origin;
//		if (isdefined(sPostureName))	
//			self allowedStances (sPostureName);
		self.dontavoidplayer = true;
		self pushplayer(true);
		
		self setFlashbangImmunity( true );
		self thread anim_loop_solo (self, "stand_idle", undefined, "stop_hold_pos");
		

	}
	else
	{
		self.holdPos = false;
//		level thread print3Dthread (self, "");
//		self unset_forcegoal();
//		self resetGoalRadius();
//		self allowedStances ("stand", "crouch", "prone");
		self pushplayer(false);
		self.dontavoidplayer = false;	
		
		self notify ("stop_hold_pos");
	
	}
		

}

hideMe()
{
	switch (self.classname)
	{
		case "script_model":		
			self hide();
			break;	

		case "script_brushmodel":		
			self hide();
			self notsolid();
			if (self.spawnflags & 1)
				self connectpaths();
			break;	
	}
}

hideAll(stuffToHide)
{
	//If stuff to hide is not passed, hide everything tagged to be hidden
	if (!isDefined (stuffToHide))
		stuffToHide = getentarray("hide", "script_noteworthy");	
		
	for (i=0;i<stuffToHide.size;i++)
	{
		entity = stuffToHide[i];
		switch (entity.classname)
		{
			case "script_model":		
				entity hide();
				break;	

			case "script_brushmodel":		
				entity hide();
				entity notsolid();
				if (entity.spawnflags & 1)
					entity connectpaths();

				break;	
			
			case "trigger_multiple":
				entity trigger_off();
				break;	
				
			case "trigger_use":
				
				entity hide();
				entity trigger_off();
				break;	
				
			case "trigger_use_touch":
				
				entity hide();
				entity trigger_off();
				break;	

			case "trigger_damage":
				entity trigger_off();
				break;	
				
			case "trigger_hurt":
				entity trigger_off();
				break;	
				
			case "trigger_lookat":
				entity trigger_off();
				break;			
		}
		
	}
}

doorCameraCheck(sDoorName)
{
	sDoorNode = "node_doorCameraCheck_" + sDoorName;
	
	self thread forceToNode(sDoorNode);
	self waittill("goal"); 
	self setPosture("crouch");
	
	wait(2);
	
	level notify ("door_camera_check_complete");
	
	self setPosture("all");	
}


setPosture(posture)
{
	if (posture == "all")
		self allowedStances ("stand", "crouch", "prone");
	else
		self allowedStances (posture);		
		
}

invulnerable(bool)
{
	if (bool == false)
		self notify ("stop magic bullet shield");
	else
		self thread maps\_utility::magic_bullet_shield();	
				
	self.anim_disablePain = bool;
}

killEntity()
{	
	self endon ("death");

	if (!isdefined(self))
		return;
	if (!isalive(self))
		return;	
	
	self.allowdeath = true;
	self invulnerable(false);
	self doDamage (self.health + 1, self.origin);
}	


goToVolume(sVolumeName)
{
	self endon ("death");
	goalVolume = getEnt( sVolumeName, "targetname" );
	goalNode = getNode( goalVolume.target, "targetname" );
	assertEx(isdefined(goalVolume), "Need to specify a valid volume name vor this function");
	assertEx(isdefined(goalNode), "The volume needs to target a node for this function to work properly");
	
	self setGoalNode( goalNode );
	self setGoalVolume( goalVolume );
	self.goalradius = goalNode.radius;
}

hostage_evac(sRoomName, aFriendlies)
{
	//For now, just send to volume, have them stay put and put a message over their heads
	sVolumeName = "volume_" + sRoomName;
	for(i=0;i<aFriendlies.size;i++)
	{
		if(!isalive(aFriendlies[i]))
		{
			aFriendlies[i] thread goToVolume(sVolumeName);
			level thread print3Dthread (aFriendlies[i], "evacuating hostages");
		}
	}
		
	
}


killplayer()
{
	level.player enableHealthShield( false );
	level.player doDamage (level.player.health, level.player.origin);	//killplayer
	level.player enableHealthShield( true );
}


startTimer()
{
	//destroy any prvious timer just in case
	killTimer();

	if ( getdvar("embassy_notimer") == "1" )
		return;
	
	//destroy timer and thread if objectives completed within limit
	level endon ("kill_timer");
	
	level.hudTimerIndex = 20;

	//Timer size and positioning	
	level.timer = newHudElem();
	level.timer.alignX = "left";
	level.timer.alignY = "middle";
	level.timer.horzAlign = "right";
    level.timer.vertAlign = "top";
    if(level.xenon)
	{
		level.timer.fontScale = 2;
		level.timer.x = -225;
	}
	else
	{
		level.timer.fontScale = 1.6;    
		level.timer.x = -180;
	}
	level.timer.y = 100;
	level.timer.label = &"EMBASSY_TIMER_LABEL";
	level.timer setTimer(level.stopwatch*60);

	//Wait until timer expired
	wait (level.stopwatch * 60);
	flag_set("timer_expired");

	//Get rid of HUD element and fail the mission
	level.timer destroy();	
	
	level thread mission_failed_out_of_time();
}


mission_failed_out_of_time()
{
	level.player endon ("death");
	level endon ("kill_timer");

	level notify ("mission failed");	
	setDvar("ui_deadquote", level.missionFailedQuote);
	maps\_utility::missionFailedWrapper();	
}

killTimer()	
{
	level notify ("kill_timer");
	if (isdefined (level.timer))
		level.timer destroy();		
}
	
	
msg(string)
{
	if (level.debug_mode == false)
		return;	
	iprintlnbold(string);
}



dialogue_radio_thread(dialogue)
{
	play_sound_in_space(dialogue, level.player.origin);
	//level.radioorg playsound (sound,"sounddone");
	//level.radioorg waittill ("sounddone");
	
}


get_closest_ally()
{
	excluders = [];
	excluders[0] = level.jack;
	excluders[1] = level.gaz;
	
	guy = get_closest_ai_exclude (level.player getorigin(), "allies", excluders);

	guy.animname = "guy";
	return guy;
}

groupWarp(aGroupToBeWarped, sNodesToWarpTo)
{
	aNodes = getnodearray(sNodesToWarpTo, "targetname");
	assert(isdefined(aNodes));
	
	for(i=0;i<aGroupToBeWarped.size;i++)
	{
		if(isdefined(aNodes[i]))
		{
			aGroupToBeWarped[i] teleport (aNodes[i].origin);
		}		
	}
}

/****************************************************/
/**************** LEVEL SKIPTO FUNCTIONS**************/
/****************************************************/
skipWarp(skipToString)
{

	
	//specific setup for each skipto case

 	if (skipToString == "southoffices")
 	{
 		
 		//warp everyone to proper positions
 		level thread skipWarpSquad(skipToString);	
		rooftop_character_setup();
		level thread group_absail_sequence();
		wait(1);
		level thread balcony_rappel_gaz();
		level thread balcony_rappel_jack();
		flag_set("player_landed_on_rooftop");
		flag_set("player_has_started_balcony_absail");
		flag_set("rappel_point_reached");
		
		level thread setup_enemies_office_a();
		
 		level thread AA_southOffices_init();


 	}	
	
 	if (skipToString == "northoffices")
 	{
 		flag_set("south_office_exit_reached");
 		
		AA_northOffices_init();
		
		// warp player and 2 friendlies to south offices exit stairway
		level thread skipWarpSquad(skipToString);
		
		//force squad to next positions asap
		level.gaz thread forceToNode("squad_north_offices_start_1");
		level.jack thread forceToNode("squad_north_offices_start_2");	
		
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");	
		
 	}
  	if (skipToString == "conferencehall")
 	{
 		//Spawn guy who will kick open conf hall door
 		level thread trig_conf_door_setup();
 		trigger = getEnt( "trig_conf_door_setup", "targetname" ); trigger notify ( "trigger" ); trigger trigger_off();
 		
 		//Start thread for approaching conf hall door
 		level thread trig_conferenceHall_door_approach();
 		triggerEnable("trig_conferenceHall_door_approach", true);
 		
 		//Warp Gaz and Jack to proper positions
 		level thread skipWarpSquad(skipToString);
 			
		wait(1);
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");	
	
		//squad to positions by door
		level thread friendlies_go_to_conf_hall_door();
 	}
 	
   	if (skipToString == "mezzanine")
 	{	
 		level thread trig_approach_mezzanine_door();
 		
 		level thread skipWarpSquad(skipToString);	 		

		wait(1);
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");	
 	}
 	
 	if (skipToString == "reception")
 	{
 		//spawn all guys in drawing room
 		level thread ai_setup_drawing_room();	
 		
 		level waittill ("ai_setup_drawing_room_complete");
 		
 	 	//kill all the hostiles in reception
 		npcDelete("volume_reception", "all", true); 	
 		
		aSquad = getSquadArray();
		for(i=0; i<aSquad.size; i++)
		{
			aSquad[i] holdPosition(false);
			aSquad[i] makeUnaware(false);
		}
 
 		//warp all to proper positions
 		level thread skipWarpSquad(skipToString);	
 		
 		//start the courtyard sniper sequence and all other threads 		
 		level thread AA_elevator_assault_init();
 		
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");	
		
		//level.bravo_backdraft holdPosition(false);
		//level.bravo_backdraft killEntity();
		
 	}
  	if (skipToString == "libhall")
 	{		
 		//warp all to proper positions
 		level thread skipWarpSquad(skipToString);	
 		level thread foyer_door_slam();
 		
 		level thread AA_lib_assault_init();
 		
 		wait(1);
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");		
		
 		flag_set("library_foyer_cleared");
 		flag_set("player_approaching_foyer_sidedoor");
 		level thread door_close("door_libraryfoyer");
 	} 	
 	
  	if (skipToString == "end")
 	{		
 		//warp all to proper positions
 		level thread skipWarpSquad(skipToString);	
 		
 		level thread AA_final_battle_init();
 		
 		wait(1);
		// delete any guys left behind
		level thread npcDelete("volume_rooftop_offices_south", "all");		
		
 		flag_set("library_foyer_cleared");
 		flag_set("player_approaching_foyer_sidedoor");
 		level thread door_close("door_libraryfoyer");
 	} 	 	
}

skipWarpSquad(skipToString)
{
 	//Warp player and squad	
 	tempPlayerNode = getNode("tempWarp", "targetname");
	playerNode = getNode("playerWarp_" + skipToString, "targetname");
	squadNodes = getnodearray("squadWarp_" + skipToString, "targetname");
	
	assertEx(isDefined(playerNode), "node doesn't exist: playerWarp_" + skipToString);
	assertEx(isDefined(squadNodes), "nodes don't exist: squadWarp_" + skipToString);
	
	//warp player to temp node so he can't see
	level.player setorigin (tempPlayerNode.origin);
	
	wait(0.05);
	//now warp dudes
	squadWarp(squadNodes);
	
	wait(0.5);
	//now warp player to proper place
	level.player setorigin (playerNode.origin);
	level.player setplayerangles (playerNode.angles);
}

squadWarp(aSquadNodes)
{
	aSquad = getSquadArray();
	for(i=0; i<aSquad.size; i++)
	{
		if(isdefined(aSquadNodes[i]))
		{
			aSquad[i] teleport (aSquadNodes[i].origin);
		}
	}		
}

playerWeaponTempRemove()
{
	// Take away all player weapons
	playerWeapon[0] = level.player getweaponslotweapon("primary");
	playerWeapon[1] = level.player getweaponslotweapon("primaryb");
	playerWeapon_Ammo[0] = level.player getweaponslotammo("primary");
	playerWeapon_Ammo[1] = level.player getweaponslotammo("primaryb");
	playerWeapon_ClipAmmo[0] = level.player getweaponslotclipammo("primary");
	playerWeapon_ClipAmmo[1] = level.player getweaponslotclipammo("primaryb");
	playerCurrentWeapon = level.player getcurrentweapon();
	level.player takeWeapon(playerWeapon[0]);
	level.player takeWeapon(playerWeapon[1]);
		
	level.player waittill ("restore_player_weapons");
	
	
	// Restore all player weapons
	if (playerWeapon[0] != "none")
	{
		level.player giveWeapon(playerWeapon[0]);
		level.player setweaponslotammo("primary", playerWeapon_Ammo[0]);
		level.player setweaponslotclipammo("primary", playerWeapon_ClipAmmo[0]);
	}
	
	if (playerWeapon[1] != "none")
	{
		level.player giveWeapon(playerWeapon[1]);
		level.player setweaponslotammo("primaryb", playerWeapon_Ammo[1]);
		level.player setweaponslotclipammo("primaryb", playerWeapon_ClipAmmo[1]);
	}
	
	if (playerWeapon[0] == playerCurrentWeapon)
	{
		if (playerWeapon[0] != "none")
			level.player switchToWeapon(playerWeapon[0]);
	}
	else
	if (playerWeapon[1] == playerCurrentWeapon)
	{
		if (playerWeapon[1] != "none")
			level.player switchToWeapon(playerWeapon[1]);
	}
	
}




/****************************************************/
/**************** BREACH FUNCTIONS ******************/
/****************************************************/

breach_variable_setup(sRoomName, aFriendlies, iBreach_id)
{
	//reset all vars back to undefined
	level.friendliesReadyToBreach = 0;
	level.eTrigger_breach_approach = undefined;
	level.eDoor = undefined;
	level.eTrigger_enter = undefined;
	level.aTrigger_use_breach = undefined;
	level.eBreach_Room_Volume = undefined;

	
	//get all the names of relevant entities
	level.eBreach_Room_Volume = getent("volume_" + sRoomName, "targetname");	
	level.eTrigger_breach_approach = getent("trig_breach_approach_" + sRoomName, "targetname");
	level.eDoor = getent("door_" + sRoomName, "targetname");
	level.eTrigger_enter = getent("trig_enter_" + sRoomName, "targetname");
	level.aTrigger_use_breach = getentarray("trig_use_breach_" + sRoomName, "targetname");
	assertEx(isDefined(level.eBreach_Room_Volume), "Volume doesn't exist: volume_" + sRoomName);
	assertEx(isDefined(level.eTrigger_breach_approach), "You need to create a valid trig_breach_approach_<roomName> for " + sRoomName);
	assertEx(isDefined(level.eDoor), "You need to create a valid door_<roomName> for " + sRoomName);
	assertEx(isDefined(level.eTrigger_enter), "You need to create a valid trigr_enter_<roomName> for " + sRoomName);
	assert(level.aTrigger_use_breach.size == 2);

	// this ent is needed for animations
	level.eDoor.anim_ent = spawn( "script_origin", level.eDoor.origin);
	level.eDoor.anim_ent.angles = level.eDoor.angles;
	assertEx(isDefined(level.eDoor.anim_ent), "The script_origin for the door does not exist");

	// parameters for the different breach versions.
	level.aBreach_type = [];

	level.aBreach_type[0]["breach_anim"] = "door_breach_shoot_and_kick";
	level.aBreach_type[0]["door_open_type"] = 1;

}

breach_room(sRoomName, aFriendlies, iBreach_id)
{
	/*---------------------------------------------
	sRoomName - string name of room to be breached
	aFriendlies - array of 2 friendlies that will perform the breach
	iBreach_Id - integer that indicates whether it's a hinge shoot, generic kick, etc
	/----------------------------------------------*/
	assertEx(isdefined(iBreach_id), "You need to specify a valid iBreach_id");
	
	//reset and setup all variables
	breach_variable_setup(sRoomName, aFriendlies, iBreach_id);
	
	level thread breach_nag();						//thread for breach nagging
	level thread trigger_breach_approach();			//thread for when player approaches room
	level thread trigger_enter_room();				//thread for when player enters room
			
	//have everyone ignore eachother 
	ignoreEverybody(true);
	
	//setup friendlychain for after breach (should be ignored while scripted anims are playing)
	friendlyChainUpdate("friendlychain_exterior_" + sRoomName);	


	//setup animations for main dude and type of door open
	breach_anim		= level.aBreach_type[iBreach_id]["breach_anim"];
	door_open_type	= level.aBreach_type[iBreach_id]["door_open_type"];

	
	//have ai get into position
	level.gaz thread breach_ai_think();
	level.jack thread breach_ai_think();	
	
	level waittill ("door_ready_to_be_breached");	
	
	//Setup the activation triggers
	array_thread( level.aTrigger_use_breach, ::trigger_use_door_breach_think );

	level waittill ("player_has_given_breach_command");	
	
	// opens door on "breach" notify
	level.eDoor thread door_open_breach(door_open_type);
	
	//Have kneeling guy perform the breach		
	//level thread breach_perform(level.breach_firstguy, main_anim);
	level thread breach_perform(level.jack, breach_anim);

	level waittill ("breach");
	
	//Have enemies get freaked out
	aHostiles = getAIarrayTouchingVolume("axis", "volume_" + sRoomName);
	array_thread( aHostiles, ::enemy_surprised );

	
	sRoom_breached_flag = sRoomName + "_breached";
	flag_set(sRoom_breached_flag);
	
	//Run the default thread now that breach is done
	level breach_complete(sRoomName);
	
	level waittill ("breach_ai_back_to_normal");

}

enemy_surprised()
{
	guy = self;
	if (self.spawnflags & 1)
		self waittill("spawn",guy);

	//assert( isdefined(guy.script_animation) );

	guy endon("death");

	//self.old_maxsightdistsqrd = self.maxsightdistsqrd;
	//self.maxsightdistsqrd = (256*256);

	guy.allowdeath = true;
	guy.animname = "surprise_guy";
	
	//pick a random surprised anim from 1 to 3
	sSurprisedAnimName = "surprise_" + randomintrange(1,3);
	
	level thread print3Dthread(guy, "         Surprised!");
	
	guy anim_single_solo (guy, sSurprisedAnimName, undefined);
	guy waittillmatch("single anim", "end");
	
	level thread print3Dthread(guy, "");
}




breach_nag()	//friendlies nag the player if he is not in the approach trigger
{
	level endon ("player_has_entered_breach_trigger");
	level endon ("player_has_entered_breached_room");	
	
	level waittill ("door_ready_to_be_breached");
	
	iWaitTime = randomintrange(10,16);
	while (true)
	{
		wait(iWaitTime);
		
		iDialogueNumber = randomintrange(1,6);
		sDialogueString = "embassy_gaz_getoverhere" + iDialogueNumber;
		level.gaz thread queue_anim(sDialogueString);		
	}
}

breach_complete(sRoomName)
{

	switch(sRoomName)
	{
	case "officeB1":
		level thread officeB1_fight();
		break;
	case "officeD":
		level thread officeD_fight();
		break;
	case "officeF":
		level thread officeF_fight();
		break;
	default:
		assertMsg("need to create a thread to run after breach is done for this room");
		break;
	}
}

trigger_breach_approach()
{
	//wait until guys are in place
	level waittill ("door_ready_to_be_breached");
	
	//wait till trigger is hit	
	level.eTrigger_breach_approach waittill ( "trigger" ); level.eTrigger_breach_approach trigger_off();
	
	level notify ("player_has_entered_breach_trigger");
	
	//Gaz
	//Stack up against the wall, Andy. Get those flashbangs ready
	//level.gaz thread dialogue_thread("embassy_gaz_breachstack1");
	
	array_thread(level.aTrigger_use_breach, ::breach_use_trigger_touch_test);
	
	level waittill ("player_entered_breach_use_trigger"); 
	
	level notify ("player_has_entered_breach_trigger");
	
	//jack
	//"Waiting for your signal, Andy."
	level.jack thread queue_anim("embassy_jack_breachwaitingforsignal1");

}

breach_use_trigger_touch_test()
{
	level endon ("player_entered_breach_use_trigger");
	
	while ( !level.player isTouching(self) )
	{
		wait ( .05 );
	}
	level notify ("player_entered_breach_use_trigger");
}

trigger_enter_room()
{
	level.eTrigger_enter waittill ( "trigger" ); level.eTrigger_enter trigger_off();
	level notify ("player_has_entered_breached_room");	
}

breach_perform(guy, breach_anim)
{
	level endon ("player_has_entered_breached_room");
	
	//stop any looping animations on this guy
	ender = "stop_idle_" + guy getentitynumber();
	level.eDoor.anim_ent notify(ender);	
	
	//play breach animation
	level.eDoor.anim_ent thread anim_single_solo (guy, breach_anim);

	guy waittillmatch("single anim", "kick");
	level notify("breach");			//notifies door to open
	guy waittillmatch("single anim", "end");	
	
	level.player.ignoreme = false;		//have the hostiles see the player, but not other friendlies yet


	ender = "stop_idle_" + guy getentitynumber();
	guy setFlashbangImmunity( true );
	level.eDoor.anim_ent thread anim_loop_solo (guy, "support_idle", undefined, ender);
		
	ignoreEverybody(false);	

	level notify ("player_has_entered_breached_room");
}



trigger_use_door_breach_think()
{
	
	//create trigger, setup hint and wait till used
	trigger_use_door_breach = self;
	trigger_use_door_breach trigger_on();
	trigger_use_door_breach setHintString( &"EMBASSY_HINTSTR_BREACH");
	trigger_use_door_breach waittill("trigger");
	
	//Trigger has been used
	for(i=0;i<level.aTrigger_use_breach.size;i++)
		level.aTrigger_use_breach[i] trigger_off();	//delete all triggers, not just this one
	
	level notify ("player_has_given_breach_command");	
}

breach_ai_think()
{
	//setup temporary values for breach
	self pushplayer(true);
	
	self setGoalRadius(0);
	self setInterval(0);


	//Friendlies go to door and wait for player
	ender = "stop_idle_" + self getentitynumber();
	self setFlashbangImmunity( true );
	level.eDoor anim_reach_solo(self, "support_idle_start");		
	level.eDoor.anim_ent thread maps\_anim::anim_loop_solo (self, "support_idle", undefined, ender);

	level.friendliesReadyToBreach++;
	if (level.friendliesReadyToBreach == 2)
		level notify ("door_ready_to_be_breached");
				
	//wait until door is breached, then reset back to old values
	level waittill ("player_has_entered_breached_room");
	
	//stop guys from doing animations
	//self notify ("stop doing _anim notetracks");
	self stopanimscripted();
	
	ignoreEverybody(false);	
		
	//stop any looping animations and reset default ai
	ender = "stop_idle_" + self getentitynumber();
	level.eDoor.anim_ent notify(ender);	
	
	self pushplayer(false);
	self resetGoalRadius();
	self resetInterval();
	
	level notify ("breach_ai_back_to_normal");	
}





door_NPC_open(sDoorName, iOpenType, iDoorOpenType)
{
	/*----------------
	/ iDoorOpenType 1- fall over
	/ iDoorOpenType 2- swing open
	/ 
	/ 
	/-----------------*/
	assert(isdefined(self));
	self endon ("death");
	
	bDoubleDoors = false;
	
	//setup vars and different open types	
	aOpenType = [];
	aOpenType[0]["open_anim"] = "door_breach_shoot_and_kick";
	aOpenType[1]["open_anim"] = "door_breach_kick_in";
	aOpenType[2]["open_anim"] = "door_bash_and_block";
	breach_anim	= aOpenType[iOpenType]["open_anim"];
	
	eDoor = getent(sDoorName, "targetname");
	assert(isDefined(eDoor));

	eDoor.anim_ent = spawn( "script_origin", eDoor.origin);
	eDoor.anim_ent.angles = eDoor.angles;
	
	//Is it a double door?
	if ( (isdefined(eDoor.script_noteworthy)) && (eDoor.script_noteworthy == "double_door") )
	{
		bDoubleDoors = true;
		eDoor2 = getent(eDoor.targetname + "_2", "targetname");
		assertEx(isdefined(eDoor2), "For double doors, you need to put '_2' on the other door and ensure it is on the left side");
		//move the animation origin a bit to the left
	}
	else
		eDoor2 = undefined;
	
	
	//give the guy a temp animname
	self set_animname("guy");
	self setFlashbangImmunity( true );		
	eDoor.anim_ent anim_reach_solo(self, breach_anim);
	eDoor.anim_ent thread anim_single_solo (self, breach_anim);

	self waittillmatch("single anim", "kick");
	self notify("door_kicked");
	
	// Have door fall down if not specified
	if (!isdefined(iDoorOpenType))
		iDoorOpenType = 1;
		
	eDoor thread door_open(iDoorOpenType);
	
	
	// Make the double door fly open backwards if defined
	if (bDoubleDoors == true)
		eDoor2 thread door_open(3, false);
	
	self waittillmatch("single anim", "end");
	
	self reset_animname();
	
	self notify ("door_has_been_opened");
}

door_open_breach(type)
{
	level waittill("breach");

	self playsound ("wood_door_kick");
	
	switch(type)
	{
		case 1:
			self thread door_fall_over();
			self door_connectpaths();
			break;
		default:
			self rotateyaw(-175, 0.5);
			self door_connectpaths();
			break;
	}
}

open_all_doors_in_level()
{
	// define all the doors in the level you want initially open
	aDoorsToBeOpened = [];
	aDoorsToBeOpened[0] = getent("door_libraryhallway", "targetname");
	aDoorsToBeOpened[1] = getent("door_libraryfoyer", "targetname");
	
	for(i=0;i<aDoorsToBeOpened.size;i++)
	{
		//Is it a double door?
		if ( (isdefined(aDoorsToBeOpened[i].script_noteworthy)) && (aDoorsToBeOpened[i].script_noteworthy == "double_door") )
		{
			eDoor2 = getent(aDoorsToBeOpened[i].targetname + "_2", "targetname");
			assertEx(isdefined(eDoor2), "For double doors, you need to put '_2' on the other door and ensure it is on the left side");
			
			//open this other door in the opposite direction
			eDoor2 thread door_open(3, false);
			
		}
		else
			eDoor2 = undefined;
		
		//Open the door
		aDoorsToBeOpened[i] door_open(2, false);			
	}

}

door_close(sDoorName)
{
	//setup vars and different open types	
	eDoor = getent(sDoorName, "targetname");
	assert(isDefined(eDoor));
	eDoor2 = undefined;
	
	//Is it a double door?
	if ( (isdefined(eDoor.script_noteworthy)) && (eDoor.script_noteworthy == "double_door") )
	{
		bDoubleDoors = true;
		eDoor2 = getent(eDoor.targetname + "_2", "targetname");
		assertEx(isdefined(eDoor2), "For double doors, you need to put '_2' on the other door and ensure it is on the left side");
		//move the animation origin a bit to the left
	}
	else
		eDoor2 = undefined;
		
	eDoor rotateyaw(175, 0.5);
	eDoor door_disconnectpaths();
	
	//do double door as well if specified
	if (isdefined(eDoor2))
	{
		eDoor2 rotateyaw(-175, 0.5);
		eDoor2 door_disconnectpaths();
	}
	
	wait(0.5);
	eDoor playsound ("wood_door_kick");
	
}

door_open(type, bPlaySound)
{
	if (!isDefined(bPlaySound))
		bPlaySound = true;
		
	if (bPlaysound == true)
		self playsound ("wood_door_kick");
	
	switch(type)
	{
		case 1:
			self thread door_fall_over();
			self door_connectpaths();
			break;
		case 2:		//Rotate away from kick
			self rotateyaw(-175, 0.5);
			self door_connectpaths();
			break;
		case 3:		//Double door...opposite rotation
			self rotateyaw(175, 0.5);
			self door_connectpaths();
			break;
		default:
			self rotateyaw(-175, 0.5);
			self door_connectpaths();
			break;
	}
}

door_connectpaths()
{
	if (self.classname == "script_brushmodel")
		self  connectpaths();
	else
	{
		self.blocker = getent(self.target, "targetname");
		assertex( isdefined(self.blocker), "A script_model door needs to target a script_brushmodel that blocks the door.");
		//self.blocker delete();
		self.blocker hide();
		self.blocker notsolid();
		self.blocker connectpaths();		
	}
}

door_disconnectpaths()
{
	if (self.classname == "script_brushmodel")
		self  disconnectpaths();
	else
	{
		self.blocker = getent(self.target, "targetname");
		assertex( isdefined(self.blocker), "A script_model door needs to target a script_brushmodel that blocks the door.");
		self.blocker show();
		self.blocker solid();
		self.blocker disconnectpaths();
	}

}

door_fall_over()
{
	vector = anglestoforward(self.angles);
	dist = (vector[0] * 20, vector[1] * 20, vector[2] * 20);

	self moveto(self.origin + dist, .5, 0 , .5);
	self rotatepitch(90, 0.45, 0.40);
	wait 0.449;
	self rotatepitch(-4, 0.2, 0, 0.2);
	wait 0.2;
	self rotatepitch(4, 0.15, 0.15);
}


set_explosives(eAnimEnt, sBadplaceName, bDialogue, iExplosiveType)
{
	if (!isdefined(bDialogue))
		bDialogue = true;

	
	self endon ("death");
	
	self set_animname ("guy");
	self pushplayer(true);
	
	//figure out explosive type
	sAnim = "";
	switch (iExplosiveType)
	{
		case 0:	//Wall
			sAnim = "explosive_plant_knee";
		case 1:	//Window
			sAnim = "explosive_plant_window";
		default:
			sAnim = "explosive_plant_knee";
	}
	
	
	eAnimEnt anim_reach_solo(self, sAnim);
	eAnimEnt anim_single_solo (self, sAnim);
	
	if (isdefined(sBadplaceName))
		badplace_cylinder(sBadplaceName, -1, eAnimEnt.origin, 32, 200, "allies");
	
	//Guy
	//Charges in place!
	if ( isdefined(bDialogue) && (bDialogue == true) )
	{
//		//select a random "charges placed" line of dialogue
//		i = randomintrange(1,2);
//		if (i == 1)
//			self thread dialogue_thread("embassy_frnd_explosivesplanted1");	
//		else
//			self thread dialogue_thread("embassy_frnd_explosivesplanted2");	
	}
	if (isdefined(bDialogue))
		self thread queue_anim("embassy_frnd_explosivesplanted1");	
		
	
	self reset_animname();	
	self pushplayer(false);	
	
	self notify ("explosives_set");
}

door_check(eDoor, iSignalType, sAnimname)
{
	/*-----------------
	iSignalType 1 = left
	iSignalType 2 = right
	iSignalType 3 = both
	iSignalType 4 = none
	--------------------*/
	self endon ("death");
	
	self set_animname ("guy");
		
	self pushplayer(true);
	
	ender = "stop_idle";
		
	eAnimEnt = spawn( "script_origin", eDoor.origin);
	eAnimEnt.angles = eDoor.angles;
	
	self setFlashbangImmunity( true );
	eAnimEnt anim_reach_solo(self, "stand_2_cam");
	self notify ("door_check_reached");	
	eAnimEnt thread anim_loop_solo (self, "cam_idle", undefined, ender);
	
	self waittill ("door_check_signal");
	
	eAnimEnt notify (ender);

	switch(iSignalType)
	{
		case 1:	//Left signal only
			eAnimEnt thread anim_single_solo (self, "cam_sigL");
			self waittillmatch("single anim", "end");
			break;
		case 2: //Right signal only
			eAnimEnt thread anim_single_solo (self, "cam_sigR");
			self waittillmatch("single anim", "end");
			break;
		case 3: //Both Left & Right signal
			eAnimEnt thread anim_single_solo (self, "cam_sigR");
			self waittillmatch("single anim", "end");
			eAnimEnt thread anim_single_solo (self, "cam_sigL");
			self waittillmatch("single anim", "end");
			break;
		case 4: //No signal
			//do nothing
			break;
		default:
			//do nothing
			break;
	}
	self notify ("door_check_signals_complete");
	
	//Go back to playing looping animation until stopped by notify
	eAnimEnt thread anim_loop_solo (self, "cam_idle", undefined, ender);
	
	self waittill ("door_check_stop");
	
	//Have dude stand back up and reset his default values
	eAnimEnt notify (ender);
	eAnimEnt anim_single_solo (self, "cam_2_stand");
	
	self reset_animname();	
		
	self pushplayer(false);	
	
	self notify ("door_check_complete");
}

set_deathanim(animname)
{
		if ( !isdefined( self.old_deathanim ) )
			self.old_deathanim = self.deathanim;
		self.deathanim = animname;
}

reset_deathanim()
{
		self.deathanim = undefined;
//		if ( isdefined( self.old_deathanim ) )
//			self.deathanim = self.old_deathanim;
//		self.old_deathanim = undefined;
}


set_animname(animname)
{
		if ( !isdefined( self.old_animname ) )
			self.old_animname = self.animname;
		self.animname = animname;
}

reset_animname()
{
		if ( isdefined( self.old_animname ) )
			self.animname = self.old_animname;
		self.old_animname = undefined;
}

setGoalRadius(fRadius)
{
	if ( !isdefined( self.old_goalradius ) )
		self.old_goalradius = self.goalradius;
	self.goalradius = fRadius;
}

resetGoalRadius()
{
	if ( isdefined( self.old_goalradius ) )
		self.goalradius = self.old_goalradius;
	self.old_goalradius = undefined;
}

setInterval(iInterval)
{
	if ( !isdefined( self.old_interval ) )
		self.old_interval = self.interval;
	self.interval = iInterval;
}
resetInterval()
{
	if ( isdefined( self.old_interval ) )
		self.interval = self.old_interval;
	self.old_interval = undefined;
}
/****************************************************/
/**************** DEBUG FUNCTIONS****************/
/****************************************************/

print3Dthread(eEntity, sMessage)
{
	
	if ( level.debug_mode == false )
		return;
		
	level endon (eEntity getentitynumber() + "_stop_3dprint");	//this can be raised by passing an empty string
	if (!isdefined(eEntity))
		return;
		
			
	//No message...just clear and exit
	if (sMessage == "")
	{
		if (!isdefined(eEntity))
			return;
		print3d (eEntity.origin + (0,0,32), sMessage, (1,1,1), 1, 0.5);
		level notify (eEntity getentitynumber() + "_stop_3dprint");
		return;
	}
		
	// We have a message...print it continually
	for (;;)
	{
		if (!isdefined(eEntity))
			return;
		//print3d(<origin>, <text>, <color>, <alpha>, <scale> ...)
		print3d (eEntity.origin + (0,0,32), sMessage, (1,1,1), 1, 0.5);
		wait (0.05);
	}
	
}



debugMethod1()
{
	setdvar("debug1","0");
	while ( true )
	{
		wait (0.05);
		if 	(getdvar("debug1") == "1")
		{
			setdvar("debug1","0"); 
			
			//----PUT DEBUG CODE HERE---//	
			level thread skipWarp("mezzanine");
			msg("****debug 1 was called****");
			
			//----PUT DEBUG CODE HERE---//	
		}
	}
				
}

debugMethod2()
{
	setdvar("debug2","0");
	while ( true )
	{
		wait (0.05);
		if 	(getdvar("debug2") == "1")
		{
			setdvar("debug2","0"); 
			
			//----PUT DEBUG CODE HERE---//	
	
			//----PUT DEBUG CODE HERE---//	
		}
	}
				
}