#include maps\_utility; #include maps\_vehicle; #include common_scripts\utility; #include maps\_anim; #include maps\favela_code; PLAYER_SPRINT_SCALE = 1.4; main() { // ammo crates are for SO only so remove them array_call( getentarray( "ammo_crate_part", "targetname" ), ::delete ); array_call( getentarray( "ammo_crate_clip", "targetname" ), ::delete ); array_call( getentarray( "ammo_cache", "targetname" ), ::delete ); setDvarIfUninitialized( "favela_trailer", "0" ); setsaveddvar( "r_lightGridEnableTweaks", 1 ); setsaveddvar( "r_lightGridIntensity", 1.5 ); setsaveddvar( "r_lightGridContrast", 0 ); default_start( ::startStreet ); add_start( "street", ::startStreet ); add_start( "chase", ::startChase ); add_start( "favela", ::startFavela ); add_start( "torture", ::startTortureTrailer ); add_start( "soccer", ::startSoccer ); add_start( "hilltop", ::startHilltop ); add_start( "trailer1", ::trailer_talkers_1 ); add_start( "trailer2", ::trailer_talkers_2 ); add_start( "trailer3", ::trailer_talkers_3 ); add_start( "end", ::startEnd ); maps\createart\favela_fog::main(); maps\createart\favela_art::main(); maps\createfx\favela_audio::main(); maps\favela_precache::main(); maps\favela_fx::main(); maps\_drone_ai::init(); animscripts\dog\dog_init::initDogAnimations(); maps\_hiding_door_anims::main(); maps\_load::set_player_viewhand_model( "viewhands_player_tf141_favela" ); maps\_load::main(); maps\favela_anim::main(); maps\_compass::setupMiniMap( "compass_map_favela" ); thread maps\favela_amb::main(); level.ai_friendlyFireBlockDuration = getdvarfloat( "ai_friendlyFireBlockDuration" ); level.advanceToEnemyInterval = 30000; // how often AI will try to run directly to their enemy if the enemy is not visible level.advanceToEnemyGroupMax = 1; // group size for AI running to their enemy level.lastWallaTime = getTime(); level.physics_drop_models[ 0 ] = "trash_container_big2"; level.physics_drop_models[ 1 ] = "com_milk_carton"; level.physics_drop_models[ 2 ] = "com_bottle4"; level.physics_drop_models[ 3 ] = "trash_cup_tall3"; level.physics_drop_models[ 4 ] = "trash_plate1"; level.physics_drop_models[ 5 ] = "trash_can1"; level.physics_drop_models[ 6 ] = "trash_can2"; level.physics_drop_models[ 7 ] = "trash_can3"; level.physics_drop_models[ 8 ] = "trash_can4"; foreach( model in level.physics_drop_models ) precacheModel( model ); precacheString( &"FAVELA_OBJ_CATCH_RUNNER" ); precacheString( &"FAVELA_OBJ_REACH_TOP" ); precacheString( &"FAVELA_OBJ_CAPTURE" ); precacheString( &"FAVELA_KILLED_RUNNER" ); precacheString( &"FAVELA_RUNNER_GOT_AWAY" ); precacheString( &"FAVELA_ROJAS_KILLED" ); precacheShader( "black" ); precacheItem( "rpg_straight" ); precacheItem( "flash_grenade" ); precacheModel( "com_bike_animated" ); precacheModel( "curtain_torn01_animated" ); precacheModel( "machinery_car_battery" ); precacheModel( "vehicle_hummer_hula_girl" ); array_spawn_function_noteworthy( "delete_at_path_end", ::delete_ai_at_path_end ); array_spawn_function_noteworthy( "delete_at_path_end_no_choke", ::delete_ai_at_path_end_no_choke ); array_spawn_function_noteworthy( "seek_player", ::seek_player ); array_spawn_function_noteworthy( "dog_seek_player", ::dog_seek_player ); array_spawn_function_noteworthy( "delete_at_goal", ::delete_ai_at_goal ); array_spawn_function_noteworthy( "dont_see_player_no_choke", ::dont_see_player ); array_spawn_function_noteworthy( "ignore_and_delete_on_goal", ::ignore_and_delete_on_goal ); array_spawn_function_noteworthy( "ignore_and_delete_on_goal_nosight", ::ignore_and_delete_on_goal, true ); array_spawn_function_noteworthy( "window_smasher", ::window_smasher ); array_spawn_function_noteworthy( "ignored_until_goal", ::ignored_until_goal ); array_spawn_function_noteworthy( "desert_eagle_guy", ::desert_eagle_guy ); array_spawn_function_noteworthy( "faust", ::faust_spawn_func ); array_spawn_function_noteworthy( "civilian_driver", ::civilian_driver ); // spawners with script_parameters get processed on spawn all_axis_spawners = getspawnerteamarray( "axis" ); script_parameter_spawners = []; foreach( spawner in all_axis_spawners ) { if ( !isdefined( spawner.script_parameters ) ) continue; script_parameter_spawners[ script_parameter_spawners.size ] = spawner; } array_spawn_function( script_parameter_spawners, ::process_ai_script_parameters ); array_spawn_function( getSpawnerTeamArray( "neutral" ), ::civilian_flee_walla ); array_thread( getentarray( "play_sound", "targetname" ), ::play_sound_trigger ); array_thread( getentarray( "trigger_chance", "targetname" ), ::trigger_spawn_chance ); array_thread( getentarray( "physics_drop", "targetname" ), ::physics_drop ); array_thread( getentarray( "trigger_cleanup", "targetname" ), ::trigger_cleanup ); array_thread( getentarray( "potted_plant", "targetname" ), ::potted_plant ); array_thread( getentarray( "play_fx_trig", "targetname" ), ::play_fx_trig ); array_thread( getentarray( "retreat_trigger", "targetname" ), ::retreat_trigger ); array_thread( getentarray( "curtain_pulldown", "script_noteworthy" ), ::curtain_pulldown ); array_thread( getentarray( "curtain_pulldown_playerwait", "script_noteworthy" ), ::curtain_pulldown, true ); array_thread( getvehiclenodearray( "car_screech_node", "script_noteworthy" ), ::car_screech_node ); add_global_spawn_function( "axis", ::adjustAccuracy ); //flag_init( "all_friendlies_at_runner" ); flag_init( "favela_gate_dialog_done" ); flag_init( "car_getting_shot" ); flag_init( "driver_dead" ); flag_init( "player_is_ducking" ); flag_init( "favela_music" ); flag_init( "faust_music" ); flag_init( "opening_scene_started" ); flag_init( "favela_enemies_spawned" ); flag_init( "start_chase" ); flag_init( "block_alley" ); flag_init( "favela_move_friendlies" ); flag_init( "favela_civilians_fleeing" ); flag_init( "allow_meat_death" ); flag_init( "allow_royce_death" ); flag_init( "civilians_walla" ); flag_init( "torture_sequence_done" ); flag_init( "van_skid" ); flag_init( "makarov_alley_wounded" ); flag_init( "favela_civilians_alerted" ); flag_init( "favela_civilians_spawned" ); flag_init( "ending_sequence_ready" ); flag_init( "ending_sequence_started" ); flag_init( "ending_sequence_dialog" ); flag_init( "start_final_dialog" ); flag_init( "visionset_chase" ); flag_init( "visionset_torture" ); flag_init( "soap_exits_car" ); trigger_off( "favela_opening_civilians_spawn", "targetname" ); thread vision_chase(); thread vision_torture(); thread gag_fence_dog(); thread gag_civilian_window_1(); thread favela_opening_civilians(); thread favela_music(); thread upper_village_triggered_dialog(); thread upper_village_music(); thread random_favela_background_runners(); thread faust_appearance_1(); thread faust_appearance_2(); thread faust_appearance_3(); thread faust_appearance_4(); thread street_scenes(); thread chase(); thread forklift_blocker(); thread final_bend_dialog(); thread final_staircase_dialog(); thread ending_sequence(); skill = getDifficulty(); if ( skill != "hard" && skill != "fu" ) { setsaveddvar( "ai_accuracy_attackerCountMax", 4 ); setsaveddvar( "ai_accuracy_attackerCountDecrease", 0.6 ); } } startStreet() { thread battlechatter_off( "allies" ); thread battlechatter_off( "axis" ); setSavedDvar( "compass", 0 ); setSavedDvar( "hud_showStance", 0 ); // start random city traffic thread start_traffic_group( 3.5, "traffic_car_groupA_1", "traffic_car_groupA_2"); thread start_traffic_group( 5.0, "traffic_car_groupB_1", "traffic_car_groupB_2"); // spawn street civilians array_thread( getentarray( "street_civilian", "targetname" ), ::spawn_ai, true ); delayThread( 8.0, ::bike_rider, "bike_path_1" ); delayThread( 13.0, ::bike_rider, "bike_path_2" ); thread opening_scene(); thread intro_music(); } intro_music() { // start intro music for ride and chase, and ends the music if the runner is shot before the alley thread music_play( "favela_intro" ); level waittill( "runner_shot" ); music_stop( 2.0 ); } startChase() { thread battlechatter_off( "allies" ); thread battlechatter_off( "axis" ); movePlayerToStartPoint( "playerstart_chase" ); setSavedDvar( "player_sprintUnlimited", "1" ); setSavedDvar( "player_sprintSpeedScale", PLAYER_SPRINT_SCALE ); flag_set( "start_chase" ); flag_set( "visionset_chase" ); } startTortureTrailer() { setDvar( "favela_trailer", 1 ); thread startFavela(); } startFavela() { thread battlechatter_off( "allies" ); thread battlechatter_off( "axis" ); thread fade_to_black_alley( 0.2, 2.0, 2.5 ); level waittill( "black_screen_start" ); // Give flashbangs and grenades now that the chase is over level.player giveWeapon( "fraggrenade" ); level.player setOffhandSecondaryClass( "flash" ); level.player giveWeapon( "flash_grenade" ); level notify( "stop_monitoring_makarov_damage" ); // delete any AI ( dead or alive ) that might be left over from before thread delete_ai_during_blackscreen(); array_call( getCorpseArray(), ::delete ); if ( isdefined( level.runner ) ) level.runner delete(); flag_set( "visionset_torture" ); level delayThread( 1.2, ::torture_sequence ); movePlayerToStartPoint( "playerstart_favela" ); activate_trigger( "favela_vision", "script_noteworthy" ); flag_set( "civilians_walla" ); enablePlayerWeapons( false ); // Reenable destructibles to do bad places, was disabled for the chase level.disable_destructible_bad_places = undefined; level.player setStance( "stand" ); setSavedDvar( "player_sprintUnlimited", "0" ); setSavedDvar( "player_sprintSpeedScale", 1.5 ); assert( isdefined( level.ai_friendlyFireBlockDuration ) ); setSavedDvar( "ai_friendlyFireBlockDuration", level.ai_friendlyFireBlockDuration ); flag_clear( "player_near_stairs" ); // Block the alley with the forklift so player wont backtrack flag_set( "block_alley" ); level waittill( "black_screen_finish" ); thread autosave_now(); thread timed_favela_autosaves(); favela_friendlies(); flag_clear( "give_favela_warning" ); trigger_on( "favela_opening_civilians_spawn", "targetname" ); getent( "favela_enter_player_clip", "targetname" ) delete(); // remove player clip brush that prevented the player from entering the favela prematurely. wait 0.05; // Make enemies talk more by modding battlechatter times thread modify_battlechatter_times(); // Wait for torture sequence to end before going into favela flag_wait( "favela_move_friendlies" ); flag_set( "favela_music" ); enablePlayerWeapons( true ); thread add_top_of_hill_objective(); thread favela_gate(); thread favela_warning(); thread favela_dialog(); thread soccer_dialog(); thread meat_dies(); thread royce_dies(); } startSoccer() { add_top_of_hill_objective(); array_call( getentarray( "delete_for_start_soccer", "script_noteworthy" ), ::delete ); movePlayerToStartPoint( "playerstart_soccer" ); activate_trigger( "vision_shanty", "script_noteworthy" ); flag_set( "civilians_walla" ); } startHilltop() { add_top_of_hill_objective(); movePlayerToStartPoint( "playerstart_hilltop" ); activate_trigger( "favela_hill", "script_noteworthy" ); flag_set( "civilians_walla" ); } trailer_talkers_1() { spawn_talkers( "trailer_talkers_1" ); level.player set_ignoreme( true ); movePlayerToStartPoint( "trailer_talkers_1_player" ); } trailer_talkers_2() { spawn_talkers( "trailer_talkers_2" ); level.player set_ignoreme( true ); movePlayerToStartPoint( "trailer_talkers_2_player" ); } trailer_talkers_3() { spawn_talkers( "trailer_talkers_3" ); level.player set_ignoreme( true ); movePlayerToStartPoint( "trailer_talkers_3_player" ); } spawn_talkers( targetname ) { spawners = getentarray( targetname, "targetname" ); foreach( spawner in spawners ) { guy = spawner spawn_ai( true ); guy set_ignoreall( true ); guy.goalradius = 16; guy setGoalPos( guy.origin ); if ( !isdefined( spawner.animation ) ) continue; guy.animname = "trailer"; guy thread anim_loop_solo( guy, spawner.animation ); } } startEnd() { add_top_of_hill_objective(); movePlayerToStartPoint( "playerstart_end" ); activate_trigger( "favela_vision", "script_noteworthy" ); } favela_gate() { // Gate sequence gone, just some dialog now thread favela_gate_dialog(); } favela_gate_dialog() { // Wait for torture sequence to finish so we don't step on dialog flag_wait( "torture_sequence_done" ); // Let's go. level.royce anim_single_solo( level.royce, "favela_ryc_letsgo" ); // Wait for player to be somewhere nearby flag_wait( "player_near_stairs" ); // Remember - there are civilians in the favela. Take clean shots, watch your background. level.royce anim_single_solo( level.royce, "favela_ryc_watchyourbg" ); flag_set( "favela_gate_dialog_done" ); } torture_sequence() { node = getent( "torture_node", "targetname" ); door = getent( "torture_door", "targetname" ); torture_enemy_spawner_targetname = "torture_enemy_spawner"; if ( getdvarint( "favela_trailer" ) > 0 ) torture_enemy_spawner_targetname = "torture_enemy_spawner_trailer"; guys[ 0 ] = spawn_targetname( torture_enemy_spawner_targetname ); guys[ 0 ].animname = "torture_enemy"; guys[ 1 ] = spawn_targetname( "torture_friendly_1_spawner" ); guys[ 1 ].animname = "torture_friend1"; guys[ 2 ] = spawn_targetname( "torture_friendly_2_spawner" ); guys[ 2 ].animname = "torture_friend2"; foreach( guy in guys ) { guy set_ignoreme( true ); guy set_ignoreall( true ); } jumper_cables = spawn_anim_model( "torture_cables", node.origin ); guys[ 3 ] = jumper_cables; //chad - comment this out once the map has been recompiled battery_origin = ( -527, -1043.5, 725 ); battery_angles = ( 0, 289.5, 0 ); car_battery = spawn( "script_model", battery_origin ); car_battery.angles = battery_angles; car_battery setModel( "machinery_car_battery" ); //---- node anim_first_frame( guys, "torture" ); guys[ 2 ] thread torture_sequence_door( door ); guys[ 2 ] setLookAtEntity( level.player ); guys[ 0 ] thread play_sound_on_entity( "scn_favela_captive_in_chair" ); garagePos = guys[ 0 ].origin; node anim_single( guys, "torture" ); array_call( guys, ::delete ); flag_set( "torture_sequence_done" ); flag_set( "favela_move_friendlies" ); thread play_sound_in_space( "scn_favela_garage_interior", garagePos ); } torture_sequence_door( door ) { finalDoorPos = door.origin; startingDoorPos = door.origin + ( 0, 0, 45 ); door.origin = startingDoorPos; flag_wait( "drop_door" ); door playsound( "scn_favela_garage_door" ); door moveTo( finalDoorPos, 1.3, 0.1, 0.0 ); } opening_scene() { // open/close hotel doors for the sequence thread hotel_doors(); // spawn player vehicle and put player inside player_vehicle = spawn_vehicle_from_targetname_and_drive( "player_vehicle" ); assert( isdefined( player_vehicle ) ); player_vehicle hidepart( "TAG_GLASS_FRONT_D" ); player_vehicle hidepart( "TAG_BLOOD" ); player_vehicle thread car_anims(); player_vehicle thread car_driver_anims(); player_vehicle thread play_sound_on_entity( "scn_favela_driveup" ); thread player_rides_vehicle( player_vehicle ); // spawn van van = spawn_vehicle_from_targetname_and_drive( "van" ); assert( isdefined( van ) ); van godon(); van thread van_skid_sound(); van.animname = "van"; van SetAnimTree(); // slow for intro screen - dont want to go too far while screen is black player_vehicle Vehicle_SetSpeed( 3, 5.0, 5.0 ); van Vehicle_SetSpeed( 3, 5.0, 5.0 ); wait 4; thread opening_scene_dialog(); player_vehicle resumeSpeed( 2.5 ); van resumeSpeed( 2.5 ); // wait for van to get into position vehNode = getVehicleNode( "van_last_node", "script_noteworthy" ); vehNode waittill( "trigger" ); // get animation node animNode = getent( "opening_scene_node", "targetname" ); // spawn actors ( actually just spawns drones ) makarov_spawner = getent( "makarov_spawner", "targetname" ); driver_spawner = getent( "opening_driver_spawner", "targetname" ); gunner1_spawner = getent( "opening_gunner1_spawner", "targetname" ); gunner2_spawner = getent( "opening_gunner2_spawner", "targetname" ); wait 1; makarov = makarov_spawner spawn_ai( true ); makarov.animname = "makarov"; makarov thread magic_bullet_shield(); makarov.ignorerandombulletdamage = true; makarov.grenadeawareness = 0; driver = driver_spawner spawn_ai( true ); driver.animname = "driver"; driver thread opening_death(); driver thread blood_driver(); gunner1 = gunner1_spawner spawn_ai( true ); gunner1.animname = "gunner1"; gunner1 thread opening_death(); gunner1 thread blood_gunner1(); gunner2 = gunner2_spawner spawn_ai( true ); gunner2.animname = "gunner2"; gunner2 thread opening_death(); gunner2 thread blood_gunner2(); guys[ 0 ] = makarov; guys[ 1 ] = driver; guys[ 2 ] = gunner1; guys[ 3 ] = gunner2; street_clip = getent( "street_civilian_clip", "targetname" ); street_clip connectPaths(); street_clip delete(); flag_set( "opening_scene_started" ); van thread van_door_sounds(); van thread anim_single_solo( van, "door_open" ); animNode anim_single( guys, "opening_scene" ); level notify( "end_scene" ); thread stop_traffic(); // makarov shoots at player for a bit then flees animNode thread anim_loop_solo( makarov, "opening_scene_shoot", "stop_shooting" ); thread break_windshield( player_vehicle ); makarov makarov_shoot_player( player_vehicle ); animNode notify( "stop_shooting" ); makarov anim_stopanimscripted(); // makarov runs around the corner and gets deleted runner_first_node = getnode( "runner_first_node", "targetname" ); makarov.goalradius = 32; makarov thread delete_ai_at_goal( true ); makarov set_ignoreall( true ); makarov setGoalNode( runner_first_node ); thread delayThread( 1.0, ::flag_set, "start_chase" ); player_vehicle thread play_sound_on_entity( "scn_favela_npc_door_open" ); wait 2; // get player out of the vehicle thread player_exits_vehicle( player_vehicle ); flag_set( "visionset_chase" ); } player_rides_vehicle( vehicle ) { level endon( "exiting_vehicle" ); enablePlayerWeapons( false ); MAX_ROTATE_ANG = 66; // attach player to viewmodel rig for crouch movement player_rig = spawn_anim_model( "player_rig" ); player_rig.origin = vehicle getTagOrigin( "tag_passenger" ); player_rig.angles = vehicle getTagAngles( "tag_passenger" ); player_rig linkTo( vehicle, "tag_passenger" ); player_rig hide(); player_rig thread player_dies_in_vehicle(); level.player playerLinkToDelta( player_rig, "tag_player", 1.0, MAX_ROTATE_ANG, MAX_ROTATE_ANG, 45, 20 ); level.player allowProne( false ); level.player allowCrouch( false ); level.player allowStand( true ); flag_clear( "player_is_ducking" ); level.player endon( "death" ); level.player setStance( "stand" ); player_rig thread anim_first_frame_solo( player_rig, "duck_down" ); notifyOnCommand( "go_crouch", "+movedown" ); notifyOnCommand( "go_crouch", "+prone" ); notifyOnCommand( "go_crouch", "+stance" ); notifyOnCommand( "go_crouch", "lowerstance" ); notifyOnCommand( "go_crouch", "togglecrouch" ); notifyOnCommand( "go_crouch", "toggleprone" ); notifyOnCommand( "go_crouch", "goprone" ); notifyOnCommand( "go_crouch", "gocrouch" ); notifyOnCommand( "go_stand", "+stance" ); notifyOnCommand( "go_stand", "raisestance" ); notifyOnCommand( "go_stand", "togglecrouch" ); notifyOnCommand( "go_stand", "toggleprone" ); notifyOnCommand( "go_stand", "+moveup" ); notifyOnCommand( "go_stand", "+gostand" ); for(;;) { level.player waittill( "go_crouch" ); flag_set( "player_is_ducking" ); level.player enableInvulnerability(); level.player lerpViewAngleClamp( 0.3, 0, 0, 25, 25, 25, 0 ); player_rig anim_single_solo( player_rig, "duck_down" ); player_rig thread anim_loop_solo( player_rig, "duck_down_idle", "stop_down_idle" ); level.player waittill( "go_stand" ); level.player lerpViewAngleClamp( 0.3, 0, 0, MAX_ROTATE_ANG, MAX_ROTATE_ANG, 45, 20 ); player_rig notify( "stop_down_idle" ); player_rig anim_single_solo( player_rig, "duck_up" ); flag_clear( "player_is_ducking" ); level.player disableInvulnerability(); } } player_dies_in_vehicle() { level endon( "exiting_vehicle" ); level.player waittill( "shot_next_frame" ); level.player lerpViewAngleClamp( 0, 0, 0, 0, 0, 0, 0 ); self anim_single_solo( self, "die" ); } player_exits_vehicle( vehicle ) { wait 1.2; level notify( "exiting_vehicle" ); vehicle notify( "door_open" ); exit_point = getent( "player_vehicle_exit_point", "targetname" ); dummy = spawn( "script_model", level.player.origin ); dummy.angles = level.player.angles; dummy setmodel( "tag_origin" ); level.player playerLinkTo( dummy, "tag_player", 1.0, 45, 45, 45, 20 ); MOVETIME = 1.5; ACCEL = 0.3; DECEL = 0.3; dummy moveTo( exit_point.origin, MOVETIME, ACCEL, DECEL ); dummy rotateTo( exit_point.angles, MOVETIME, ACCEL, DECEL ); wait MOVETIME; level.player unlink(); level.player disableInvulnerability(); enablePlayerWeapons( true ); level.player allowProne( true ); level.player allowCrouch( true ); level.player allowStand( true ); level.player setStance( "stand" ); setSavedDvar( "player_sprintUnlimited", "1" ); setSavedDvar( "player_sprintSpeedScale", PLAYER_SPRINT_SCALE ); } van_skid_sound() { flag_wait( "van_skid" ); self thread play_sound_on_entity( "scn_favela_van_skid2stop" ); } van_door_sounds() { self thread delayThread( 0.0, ::play_sound_on_entity, "scn_favela_van_door_open" ); self thread delayThread( 2.3, ::play_sound_on_entity, "scn_favela_van_driverdoor_open" ); self thread delayThread( 2.8, ::play_sound_on_entity, "scn_favela_van_door_close" ); self thread delayThread( 4.0, ::play_sound_on_entity, "scn_favela_van_driverdoor_close" ); } opening_scene_dialog() { wait 2.0; // Ghost, the plates are a match. radio_dialogue( "favela_cmt_ready2move" ); // Copy. Any sign of Rojas's right hand man? radio_dialogue( "favela_gst_good2go" ); // Negative. They've stopped twice already - no sign of him. radio_dialogue( "favela_cmt_rogerthat" ); flag_wait( "van_in_position" ); thread autosave_now_silent(); wait 0.5; // Wait, they've stopped again. Standby. radio_dialogue( "favela_cmt_inposition" ); wait 2.5; // Got a positive ID! Whoever these guys are, they're not happy to see him… radio_dialogue( "favela_cmt_insight" ); wait 0.9; // Ghost we have a situation here! radio_dialogue( "favela_cmt_needhimalive" ); wait 0.2; // Get down get down!!! radio_dialogue( "favela_cmt_getdown" ); } chase() { flag_wait( "start_chase" ); flag_clear( "runner_gets_away" ); setSavedDvar( "compass", 1 ); setSavedDvar( "hud_showStance", 1 ); setSavedDvar( "ai_friendlyFireBlockDuration", 0 ); thread autosave_now(); // disable badplaces on destructibles so that soap can run through the city without getting stuck, then set it back level.disable_destructible_bad_places = true; // spawn soap level.soap = spawn_targetname( "soap_spawner", true ); level.soap set_ignoreall( true ); level.soap.usechokepoints = false; level.soap.fixednode = false; level.soap.disableBulletWhizbyReaction = true; level.soap.a.disablePain = true; level.soap.maxsightdistsqrd = 0; level.soap.ignoresuppression = true; level.soap.animname = "mactavish"; level.soap.pathRandomPercent = 0; level.soap thread magic_bullet_shield(); chase_objective_location = getent( "chase_objective_location", "targetname" ); objective_add( 1, "current", &"FAVELA_OBJ_CATCH_RUNNER", chase_objective_location.origin ); waveNode = getnode( "soap_start_node", "targetname" ); waveNode anim_teleport_solo( level.soap, "run_and_wave" ); flag_set( "soap_exits_car" ); waveNode anim_single_solo( level.soap, "run_and_wave" ); thread chase_dialog(); level.soap thread control_run_speed(); // Wait for makarov street trigger and then spawn makarov // He will run his path when he spawns //trigger_wait( "makarov_street_spawn_trig", "targetname" ); makarov = spawn_targetname( "makarov_street_spawner", true ); makarov set_ignoreall( true ); makarov set_ignoreme( true ); makarov.disableBulletWhizbyReaction = true; makarov.a.disablePain = true; makarov.maxsightdistsqrd = 0; makarov.ignoresuppression = true; makarov.usechokepoints = false; makarov.skipBloodPool = true; makarov thread magic_bullet_shield(); makarov thread faust_assistant_kill_player_monitor(); makarov thread teleport_runner_for_takedown_1(); makarov thread teleport_runner_for_takedown_2(); makarov thread makarov_alley_fall(); makarov thread makarov_gets_away(); makarov thread player_doesnt_chase(); makarov thread makarov_check_player_distance(); objective_onentity( 1, level.soap, ( 0, 0, 70 ) ); } makarov_check_player_distance() { // Player fails if you don't keep up with the runner // Once you're told to take the shot you can't fail for getting too far away anymore // He will get away and fail soon anyways if you don't shoot him so give the player some freedom to take him down here level endon( "take_the_shot" ); self endon( "death" ); self endon( "runner_shot" ); MIN_DIST = 500; MAX_DIST = 2500; SPEED_MIN = 1.0; SPEED_MAX = 1.6; for(;;) { d = distance( level.player.origin, self.origin ); if ( d > MAX_DIST ) { setdvar( "ui_deadquote", "@FAVELA_RUNNER_GOT_AWAY" ); maps\_utility::missionFailedWrapper(); return; } runSpeed = self.moveplaybackrate; if ( d < MIN_DIST ) { // player too close - run faster runSpeed += 0.1; } else { // player farther away - run normal speed again runSpeed -= 0.1; } self.moveplaybackrate = cap_value( runSpeed, SPEED_MIN, SPEED_MAX ); wait 0.1; } } chase_dialog() { level endon( "runner_shot" ); // Ghost, our driver's dead! We're on foot! Meet us at the Hotel Rio and cut him off if you can! level.soap dialogue_queue( "favela_cmt_driversdead" ); // Roger, I'm on my way! radio_dialogue( "favela_gst_onmyway" ); flag_wait( "runner_in_alley" ); // He went into the alley - bloody hell he's fast! radio_dialogue( "favela_gst_hesfast" ); // Non-lethal takedowns only! We need him alive! level.soap dialogue_queue( "favela_cmt_nonlethal" ); flag_wait( "take_the_shot" ); thread legshot_pre_stinger(); // Roach - take the shot!! Go for his leg!! level.soap dialogue_queue( "favela_cmt_takeshot" ); } legshot_pre_stinger() { level endon( "runner_shot" ); wait 0.75; thread music_stop( 0.25 ); level.player thread play_sound_on_entity( "favela_legshot_pre_stinger" ); } teleport_runner_for_takedown_1() { // This makes sure he hasn't gotten too far down the alley when the player gets there. // In the case that the player is really far behind they would have failed already for // not keeping up so I dont really have to worry about that. self endon( "death" ); trig = getent( "teleport_runner_1", "targetname" ); teleportLoc = getent( trig.target, "targetname" ); trig waittill( "trigger" ); // Only teleport him if he's gone around the corner out of sight if ( !flag( "runner_in_alley" ) ) return; self forceTeleport( teleportLoc.origin, teleportLoc.angles ); } teleport_runner_for_takedown_2() { self endon( "death" ); trig = getent( "teleport_runner_2", "targetname" ); teleportLoc = getent( trig.target, "targetname" ); trig waittill( "trigger" ); // Only teleport him if he's gone around the corner out of sight if ( !flag( "runner_in_alley2" ) ) return; self forceTeleport( teleportLoc.origin, teleportLoc.angles ); } makarov_alley_fall() { //level endon( "makarov_wounded_successfully" ); level endon( "stop_monitoring_makarov_damage" ); self set_generic_deathanim( "alley_death_fall" ); for(;;) { self waittill( "damage", damage, attacker, direction_vec, point, type ); // Only Soap and the player can damage him if ( !isdefined( attacker ) ) continue; if ( attacker != level.player && attacker != level.soap ) continue; // If damage is only 1 ignore it. This happens when flashbangs and other things bounce off him if ( damage <= 1 ) continue; // If player uses grenades you fail if ( !isdefined( type ) ) continue; if ( issubstr( type, "GRENADE" ) ) { self thread makarov_alley_killed( point ); return; } // Only non-lethal shots are allowed if ( self was_shot_in_lethal_area() ) { self thread makarov_alley_killed( point ); return; } self thread makarov_alley_wounded(); } } was_shot_in_lethal_area() { assert( isdefined( self ) ); if ( isdefined( self.disableLethalCheck ) ) return false; if ( !isdefined( self.damagelocation ) ) return true; switch( self.damagelocation ) { case "none": if ( flag( "makarov_alley_wounded" ) ) return false; return true; case "helmet": case "head": case "neck": case "torso_upper": case "torso_lower": return true; default: return false; } } makarov_alley_wounded() { level notify( "runner_shot" ); if ( flag( "makarov_alley_wounded" ) ) return; flag_set( "makarov_alley_wounded" ); self thread makarov_alley_wounded_and_crawl(); wait 1.0; level.soap thread anim_single_solo( level.soap, "favela_cmt_hesdown" ); wait 1.0; level notify( "makarov_wounded_successfully" ); objective_State( 1, "done" ); thread startFavela(); } makarov_alley_wounded_and_crawl() { self endon( "deleted" ); self endon( "death" ); if ( flag( "runner_disable_crawl" ) ) self clear_deathanim(); self stop_magic_bullet_shield(); level.runner = self; level.runner thread play_sound_in_space( "scn_favela_death_crawl", level.runner.origin ); self.noDrop = true; self kill(); } makarov_alley_killed( point ) { level notify( "runner_shot" ); if ( !flag( "makarov_alley_wounded" ) ) { self clear_deathanim(); self stop_magic_bullet_shield(); self kill( point, level.player ); } setdvar( "ui_deadquote", "@FAVELA_KILLED_RUNNER" ); maps\_utility::missionFailedWrapper(); } makarov_gets_away() { self endon( "runner_shot" ); self waittill( "reached_path_end" ); setdvar( "ui_deadquote", "@FAVELA_RUNNER_GOT_AWAY" ); maps\_utility::missionFailedWrapper(); } player_doesnt_chase() { self endon( "runner_shot" ); flag_wait( "runner_gets_away" ); setdvar( "ui_deadquote", "@FAVELA_RUNNER_GOT_AWAY" ); maps\_utility::missionFailedWrapper(); } stop_sounds_during_black() { // Total hack to get sounds to stop playing. No good way to do this X_LINE = -50; ents = getentarray(); foreach( ent in ents ) { if ( ent.origin[ 0 ] < X_LINE ) continue; if ( !isdefined( ent.code_classname ) ) continue; switch( ent.classname ) { case "script_vehicle": case "script_origin": case "script_model": case "script_struct": ent notify( "stop_car_alarm" ); ent stopSounds(); break; default: break; } } } fade_to_black_alley( fadeInTime, fadeOutTime, duration ) { setSavedDvar( "compass", 0 ); setSavedDvar( "hud_showStance", 0 ); stop_sounds_during_black(); level.player playLocalSound( "scn_favela_legshot_stinger" ); overlay = newHudElem(); overlay.x = 0; overlay.y = 0; overlay setshader( "black", 640, 480 ); overlay.alignX = "left"; overlay.alignY = "top"; overlay.horzAlign = "fullscreen"; overlay.vertAlign = "fullscreen"; overlay.alpha = 0; if ( fadeInTime > 0 ) overlay fadeOverTime( fadeInTime ); overlay.alpha = 1; wait fadeInTime; wait 0.05; level.player freezeControls( true ); level notify( "black_screen_start" ); wait duration; level.player freezeControls( false ); level notify( "black_screen_finish" ); if ( fadeOutTime > 0 ) overlay fadeOverTime( fadeOutTime ); overlay.alpha = 0; wait fadeOutTime; setSavedDvar( "compass", 1 ); setSavedDvar( "hud_showStance", 1 ); overlay destroy(); } hotel_doors() { rotationAmount = 110; left = getent( "hotel_door_left", "targetname" ); right = getent( "hotel_door_right", "targetname" ); knobs = getentarray( "hotel_knob", "targetname" ); // Doors open left rotateYaw( rotationAmount * -1, 0.05 ); right rotateYaw( rotationAmount, 0.05 ); array_call( knobs, ::hide ); flag_wait( "car_getting_shot" ); flag_wait( "player_is_ducking" ); // Doors close left rotateYaw( rotationAmount, 0.05 ); right rotateYaw( rotationAmount * -1, 0.05 ); array_call( knobs, ::show ); } break_windshield( vehicle ) { flag_wait( "driver_dead" ); // break windshield on player vehicle vehicle thread play_sound_on_tag( "scn_favela_car_glass_shatter", "TAG_GLASS_FRONT_D" ); playfxontag( getfx( "car_glass_interior" ), vehicle, "TAG_GLASS_FRONT_FX" ); vehicle showpart( "TAG_GLASS_FRONT_D" ); vehicle showpart( "TAG_BLOOD" ); vehicle hidepart( "TAG_GLASS_FRONT" ); if ( !isdefined( level.hula_girl ) ) return; level.hula_girl unlink(); force = 150; level.hula_girl physicsLaunchClient( level.hula_girl.origin + ( 0, 0, 5 ), ( 0, force, 0 ) ); } driver_shot_in_head( driver ) { //blood yessss!!! playfxontag( getfx( "blood" ), driver, "J_Head" ); playfxontag( getfx( "blood_dashboard_splatter" ), driver, "J_Head" ); wait 0.1; flag_set( "driver_dead" ); } driver_falls_on_horn( driver ) { alias = "scn_favela_merc_horn_loop"; driver thread play_loop_sound_on_entity( alias, ( 0, 0, 20 ) ); wait 60; driver notify( "stop sound" + alias ); } blood_gunner1() { wait 6.6; playfxontag( getfx( "blood" ), self, "J_Hip_RI" ); wait 0.1; playfxontag( getfx( "blood" ), self, "J_SpineLower" ); } blood_gunner2() { wait 7.1; playfxontag( getfx( "blood" ), self, "J_Hip_RI" ); wait 0.2; playfxontag( getfx( "blood" ), self, "J_SpineLower" ); wait 1.2; playfxontag( getfx( "blood" ), self, "J_Head" ); } blood_driver() { wait 9.5; playfxontag( getfx( "blood" ), self, "J_Shoulder_RI" ); } makarov_shoot_player( vehicle ) { self endon( "death" ); shots = 15; shot_kill_start = 10; shot_kill_stop = 15; width = 29; height = 8; interval_min = 0.1; interval_max = 0.3; fireAnim = level.scr_anim[ self.animname ][ "stand_fire" ]; center = vehicle getTagOrigin( "tag_glass_front_fx" ); windowAng = vehicle getTagAngles( "tag_glass_front_fx" ); right = anglesToRight( windowAng ); up = anglesToUp( windowAng ); farLeft = center - ( right * width ); farRight = center + ( right * width ); top = center + ( up * height ); bottom = center - ( up * height ); //thread draw_line_for_time( self.origin, farLeft, 1, 0, 0, 10.0 ); //thread draw_line_for_time( self.origin, farRight, 1, 0, 0, 10.0 ); //thread draw_line_for_time( self.origin, top, 1, 0, 0, 10.0 ); //thread draw_line_for_time( self.origin, bottom, 1, 0, 0, 10.0 ); flag_set( "car_getting_shot" ); shootPoints = []; for( i = 0 ; i < shots ; i++ ) { rand_horizontal_offset = randomfloatrange( width * -1, width ); rand_vertical_offset = randomfloatrange( height * -1, height ); point = center; point += right * rand_horizontal_offset; point += up * rand_vertical_offset; //thread draw_line_for_time( self.origin, point, 1, 1, 1, 10.0 ); shootPoints[ shootPoints.size ] = point; } for( i = 0 ; i < shots ; i++ ) { self shoot( 100.0, shootPoints[ i ] ); fxOrigin = shootPoints[ i ]; forward = vectorNormalize( fxOrigin - self getTagOrigin( "tag_flash" ) ); playFX( getfx( "glass_exit" ), fxOrigin, forward ); if ( i >= shot_kill_start && i <= shot_kill_stop ) { // this is a deadly bullet! Check that the player is crouching if ( !flag( "player_is_ducking" ) ) self thread kill_player(); } self setAnimKnobRestart( fireAnim, 1, .2, 1.0 ); wait randomfloatrange( interval_min, interval_max ); } self clearAnim( fireAnim, 0 ); } kill_player() { level.player notify( "shot_next_frame" ); wait 0.05; level.player enableDeathShield( false ); level.player enableHealthShield( false ); level.player disableInvulnerability(); level.player doDamage( level.player.health + 50000, level.player getEye(), self ); wait 0.05; if ( isalive( level.player ) ) level.player kill(); assert( !isAlive( level.player ) ); } opening_death() { level waittill( "end_scene" ); self.allowdeath = true; self.a.nodeath = true; self.noragdoll = true; self setContents( 0 ); self kill(); } add_top_of_hill_objective() { originEnt = getent( "mission_objective_location", "targetname" ); objective_add( 2, "current", &"FAVELA_OBJ_REACH_TOP", originEnt.origin ); } favela_friendlies() { level.meat = spawn_targetname( "meat_spawner", true ); level.meat thread magic_bullet_shield(); level.meat.animname = "meat"; level.royce = spawn_targetname( "royce_spawner", true ); level.royce thread magic_bullet_shield(); level.royce.animname = "royce"; } favela_opening_civilians() { trigger_wait( "favela_opening_civilians_spawn", "targetname" ); spawners = getentarray( "favela_opening_civilian_spawner", "targetname" ); array_thread( spawners, ::favela_opening_civilians_think ); thread favela_civilians_scream(); flag_set( "favela_civilians_spawned" ); } favela_opening_civilians_think() { // spawn the civilian civilian = self spawn_ai( true ); civilian endon( "death" ); if ( !isdefined( level.favelaCivilians ) ) level.favelaCivilians = []; level.favelaCivilians[ level.favelaCivilians.size ] = civilian; wait 0.05; civilian.alertlevel = "noncombat"; // Make walkers walk instead of do idle animations if ( !isdefined( self.animation ) ) { civilian thread delete_ai_at_path_end(); civilian.useChokePoints = false; return; } // make a node eNode = undefined; if ( isdefined( self.script_linkto ) ) { eNode = get_linked_ent(); } else { eNode = spawn( "script_origin", self.origin ); eNode.angles = self.angles; } assert( isdefined( eNode ) ); // do idle as specified in editor animScene = self.animation; eNode thread anim_generic_loop( civilian, animScene, "stop_idle_anim" ); // wait for firefight to break out civilian waittill( "combat" ); flag_set( "favela_civilians_fleeing" ); wait randomfloat( 1.5 ); // civilian stops looping idle eNode notify( "stop_idle_anim" ); civilian notify( "stop_idle_anim" ); civilian stopAnimScripted(); // civilian runs away and gets deleted civilian.useChokePoints = true; node = getnode( "favela_civ_flee_node_opening", "targetname" ); civilian thread follow_path( node ); civilian thread delete_ai_at_path_end(); } favela_civilians_scream() { soundEnt = getent( "favela_civilians_scream_ent", "targetname" ); soundEntEndPos = getent( soundEnt.target, "targetname" ); flag_wait( "favela_civilians_fleeing" ); soundEnt playSound( "scn_favela_civ_outofhere_screams" ); soundEnt moveTo( soundEntEndPos.origin, 6.0, 4.0, 2.0 ); } favela_music() { flag_wait( "favela_music" ); level endon( "favela_music" ); thread favela_music_stop(); alias = "favela_tension"; time = musicLength( alias ); while( flag( "favela_music" ) ) { thread music_play( alias ); wait time; } } favela_music_stop() { flag_waitopen( "favela_music" ); music_stop( 3 ); } upper_village_music() { flag_wait( "upper_village_music" ); level endon( "faust_appearance_1" ); // Roach - this is their territory and they know it well! Keep an eye open for ambush positions and check your corners! radio_dialogue( "favela_cmt_theirterritory" ); alias = "favela_uppervillage_start"; time = musicLength( alias ); while( !flag( "faust_appearance_1" ) ) { thread music_play( alias, 2.0 ); wait time; } } faust_music() { level endon( "faust_music" ); thread faust_music_stop(); alias = "favela_moneyrun"; time = musicLength( alias ); while( flag( "faust_music" ) ) { thread music_play( alias ); wait time; } } faust_music_stop() { flag_waitopen( "faust_music" ); music_stop( 3 ); } random_favela_background_runners() { level endon( "cleared_favela" ); spawners = getentarray( "random_favela_background_runner", "targetname" ); flag_wait( "favela_enemies_spawned" ); for(;;) { spawners = array_randomize( spawners ); foreach ( spawner in spawners ) { if ( flag( "cleared_favela" ) ) return; spawner.count = 1; spawner thread spawn_ai( true ); wait randomintrange( 4, 8 ); } } } faust_appearance_1() { flag_wait( "faust_appearance_1" ); thread autosave_by_name( "faust_appearance_1" ); thread faust_appearance_1_dialog(); faust = spawn_targetname( "faust_spawner_1", true ); faust thread objective_on_faust(); thread music_stop( 3.0 ); wait 3.2; flag_set( "faust_music" ); thread faust_music(); } objective_on_faust() { assert( isalive( self ) ); level notify( "objective_on_faust" ); level endon( "objective_on_faust" ); // put the objective marker on Faust objective_onentity( 2, self, ( 0, 0, 70 ) ); objective_setpointertextoverride( 2, &"FAVELA_OBJ_CAPTURE" ); setsaveddvar( "objectiveFadeTooFar", 0.1 ); // wait until we delete Faust self waittill( "death" ); // Marker back to top of hill originEnt = getent( "mission_objective_location", "targetname" ); objective_position( 2, originEnt.origin ); setsaveddvar( "objectiveFadeTooFar", 25 ); } faust_appearance_1_dialog() { // Roach! I've spotted Faust, he's making a run for it! He's headed your way! radio_dialogue( "favela_cmt_spottedfaust" ); // And don't shoot him! We need him alive and unharmed! radio_dialogue( "favela_cmt_unharmed" ); wait 5.0; // Roach, we're going to cut him off at the summit, keep pushing him that way! Go! Go! radio_dialogue( "favela_cmt_cutoff" ); } faust_appearance_2() { flag_wait( "faust_appearance_2" ); faust = spawn_targetname( "faust_spawner_2", true ); faust thread objective_on_faust(); } faust_appearance_3() { flag_wait( "faust_appearance_3" ); faust = spawn_targetname( "faust_spawner_3", true ); faust thread objective_on_faust(); thread faust_appearance_3_dialog(); } faust_appearance_3_dialog() { level endon( "ending_sequence_dialog" ); // We've got eyes on Faust - wait! Shite! he's headed back towards you! radio_dialogue( "favela_cmt_backtowards" ); if ( flag( "ending_sequence_dialog" ) ) return; // Roach, keep pushing him up the hill! Don't let him double back! radio_dialogue( "favela_cmt_doubleback" ); } faust_appearance_4() { flag_wait( "faust_appearance_4" ); faust = spawn_targetname( "faust_spawner_4", true ); faust thread objective_on_faust(); } street_scenes() { flag_wait( "start_street_sequences_1" ); thread street_scene_civilian_180_runaway(); thread street_scene_civilian_wounded_1(); thread street_scene_destruction(); } street_scene_civilian_180_runaway() { spawner = getent( "civilian_180_runaway", "targetname" ); animNode = spawn( "script_origin", spawner.origin ); animNode.angles = spawner.angles; animScene = spawner.animation; runtoNode = getnode( spawner.target, "targetname" ); guy = spawner spawn_ai( true ); guy endon( "death" ); guy.allowdeath = true; animNode anim_generic( guy, animScene ); guy.goalradius = 32; guy thread delete_ai_at_goal(); guy setGoalNode( runtoNode ); } street_scene_civilian_wounded_1() { wounded_spawner = getent( "wounded_guy_1", "targetname" ); helper_spawner = getent( "wounded_guy_helper_1", "targetname" ); woundedAnimScene = wounded_spawner.animation; helperAnimScene = helper_spawner.animation; animNode = wounded_spawner get_linked_ent(); runtoNode = getnode( helper_spawner.target, "targetname" ); wounded = wounded_spawner spawn_ai( true ); helper = helper_spawner spawn_ai( true ); wounded.a.nodeath = true; animNode thread anim_generic_first_frame( wounded , woundedAnimScene ); animNode thread anim_generic_first_frame( helper , helperAnimScene ); helper endon( "death" ); // wait for player to hit the proximity trigger trigger_wait( "wounded_guy_1_proximity", "targetname" ); animNode thread anim_generic( wounded , woundedAnimScene ); animNode anim_generic( helper , helperAnimScene ); // scene is over, put wounded guy back into first frame idle animNode thread anim_generic_first_frame( wounded , woundedAnimScene ); // helper is done, he runs away now and gets deleted helper.goalradius = 32; helper thread delete_ai_at_goal(); helper setGoalNode( runtoNode ); } street_scene_destruction() { //chad - disabled this because nobody really likes it? Try without it for now. car1 = getent( "force_explosion_car_1", "script_noteworthy" ); car2 = getent( "force_explosion_car_2", "script_noteworthy" ); car3 = getent( "force_explosion_car_3", "script_noteworthy" ); thread delayThread( 0.0, ::street_scene_gunshots, car1.origin ); car1 thread delayThread( 1.8, ::destructible_force_explosion ); thread delayThread( 2.5, ::street_scene_gunshots, car2.origin ); car2 thread delayThread( 3.2, ::destructible_force_explosion ); thread delayThread( 4.0, ::street_scene_gunshots, car3.origin ); thread delayThread( 5.0, ::street_scene_gunshots, car3.origin ); car3 thread delayThread( 6.2, ::destructible_force_explosion ); } street_scene_gunshots( org ) { shots = randomintrange( 5, 10 ); for( i = 0 ; i < shots ; i++ ) { thread play_sound_in_space( "weap_deserteagle_fire_npc", org ); wait randomfloatrange( 0.1, 0.3 ); } } favela_warning() { // Friendlies take up positions above the favela and wait for the player to approach level.meat.goalradius = 32; level.royce.goalradius = 32; level.meat set_goal_node_targetname( "meat_first_node" ); level.royce set_goal_node_targetname( "royce_first_node" ); thread player_gives_favela_warning(); // Wait for other dialog to be done flag_wait( "favela_gate_dialog_done" ); // Wait for player to approach flag_wait( "give_favela_warning" ); animNode = getnode( "favela_warning_node", "targetname" ); if ( !flag( "favela_civilians_alerted" ) ) { // Royce tells meat to give the warning level.royce anim_single_solo( level.royce, "favela_ryc_warning" ); // Meat, give the civvies a fair warning. level.meat thread anim_single_solo( level.meat, "favela_met_rogerthat" ); // Roger that. // meat gives warning animNode anim_reach_solo( level.meat, "favela_warning_jump" ); } // make friendlies go to nodes at the bottom of the favela level.meat thread set_goal_node_targetname( "favela_warning_guy_first_node" ); level.royce thread set_goal_node_targetname( "favela_other_guy_first_node" ); // friendlies are now on color node system level.meat enable_ai_color(); level.royce enable_ai_color(); if ( !flag( "favela_civilians_alerted" ) ) { animNode anim_single_solo( level.meat, "favela_warning_jump" ); animNode anim_single_solo( level.meat, "favela_warning_landing" ); } // spawn favela enemies flag_set( "favela_enemies_spawned" ); thread activate_trigger( "favela_spawn_trigger", "script_noteworthy", level.player ); thread battlechatter_on( "allies" ); thread battlechatter_on( "axis" ); } player_gives_favela_warning() { flag_wait( "favela_civilians_spawned" ); thread player_gives_favela_warning_weapons(); thread player_gives_favela_warning_trigger(); } player_gives_favela_warning_weapons() { level endon( "favela_civilians_alerted" ); level.player waittill_any( "grenade_fire", "weapon_fired" ); thread alert_favela_civilians(); } player_gives_favela_warning_trigger() { level endon( "favela_civilians_alerted" ); flag_wait( "player_entered_favela" ); thread alert_favela_civilians(); } alert_favela_civilians() { flag_set( "favela_civilians_alerted" ); wait 1.5; foreach( civilian in level.favelaCivilians ) { if ( isdefined( civilian ) ) civilian.alertlevel = "alert"; } } favela_dialog() { flag_wait( "favela_enemies_spawned" ); wait 7.0; radio_dialogue( "favela_cmt_fullbattalion" ); // Bravo Six, be advised - we've engaged enemy militia at the lower village! radio_dialogue( "favela_ryc_withyou" ); // Roach! I'm with you! Watch the rooftops! Go! // wait for player to fight in a bit flag_wait( "player_in_lower_favela_shanty" ); radio_dialogue( "favela_cmt_doingok" ); // Royce, gimme a sitrep, over! radio_dialogue( "favela_ryc_nosign" ); // Lots of militia but no sign of Faust over here, over! radio_dialogue( "favela_cmt_keepsearching" ); // Copy that! Keep searching! Let me know if you see him! Out! wait 2.5; radio_dialogue( "favela_ryc_moveup" ); // Roach! Move up! Let's go! // allow meat to die now that dialog with him is over flag_set( "allow_meat_death" ); } soccer_dialog() { flag_wait( "cleared_favela" ); radio_dialogue( "favela_cmt_cuthimoff" ); // Roach - we've got Faust's location! He's headed west along the upper levels of the favela. radio_dialogue( "favela_cmt_keepgoing" ); // We'll keep him from doubling back on our side - keep going and cut him off up top! wait 1.0; radio_dialogue( "favela_cmt_notime" ); // There's no time to wait for backup. You're gonna have to do this on your own. Good luck. Out. } meat_dies() { // wait until all dialog is done before killing him because he needs to say some lines before he dies flag_wait( "allow_meat_death" ); flag_wait( "player_midway_through_lower_favela" ); // meat becomes vulnerable to die now. If he doens't die by the time we hit the next flag trigger then force kill him. level.meat thread meat_dies_dialog(); level.meat stop_magic_bullet_shield(); wait 0.05; level.meat.health = 1; level.meat thread meat_force_death(); } meat_force_death() { self endon( "death" ); flag_wait( "force_meat_death" ); magicBullet( "dragunov", ( -5427, -77, 1790 ), self getEye() ); wait 0.1; self kill(); } meat_dies_dialog() { self waittill( "death" ); // Meat is down! I repeat, Meat is down! radio_dialogue( "favela_ryc_meatisdown" ); flag_set( "allow_royce_death" ); } royce_dies() { // wait until meat is dead, and dialog is done about him dying, and player is most of the way through the lower favela flag_wait( "force_meat_death" ); flag_wait( "allow_royce_death" ); // royce becomes vulnerable now. If he doesn't die by the time we hit the next flag trigger then force kill him. level.royce thread royce_dies_dialog(); level.royce stop_magic_bullet_shield(); wait 0.05; level.royce.health = 1; level.royce thread royce_force_death(); } royce_force_death() { self endon( "death" ); flag_wait( "force_kill_royce" ); magicBullet( "dragunov", ( -5427, -77, 1790 ), self getEye() ); wait 0.1; self kill(); } royce_dies_dialog() { self waittill( "death" ); withinView = false; if ( isdefined( self ) && isdefined( self.origin ) ) withinView = level.player player_looking_at( self.origin, cos( 45 ) ); if ( !withinView ) radio_dialogue( "favela_ryc_imhit" ); // Roach! I'm down! Meat's dead! They're all over - (gunfire, angry shouting in Portuguese) } upper_village_triggered_dialog() { level endon( "faust_appearance_1" ); // Trigger flag_wait( "dialog_watch_rooftops" ); radio_dialogue( "favela_cmt_watchrooftops" ); // Roach, watch the rooftops! We've had a few close calls with RPGs and machine guns positioned up high! wait 4.0; radio_dialogue( "favela_cmt_stilltracking" ); // Roach, we're taking heavy fire from militia here but I'm still tracking Faust! He's gone into a building to get something! Ghost, you see him? radio_dialogue( "favela_gst_duffelbag" ); // Roger that, subject is now carrying a black duffel bag full of cash! Greedy bastard! radio_dialogue( "favela_cmt_intercept" ); // Well that ought to slow him down! Roach, we're keeping him from doubling back! Keep moving to intercept! Go! Go! wait 12; radio_dialogue( "favela_cmt_yourside" ); // Keep going! Faust is still headed towards your side of the favela! radio_dialogue( "favela_gst_pinyoudown" ); // Roach! Don't let the militia pin you down for too long! Use your flashbangs on them! radio_dialogue( "favela_cmt_lostsightagain" ); // I've lost sight of him again! Ghost, talk to me! radio_dialogue( "favela_gst_alleysbelow" ); // I'm onto him! He's trying to double back through the alleys below! radio_dialogue( "favela_cmt_stayonhim" ); // Roger that! Stay on him! wait 6; // Trigger flag_wait( "dialog_faust_through_market" ); radio_dialogue( "favela_gst_cuttingthru" ); // I've got a visual on Faust! He's cutting through the market! radio_dialogue( "favela_cmt_headforrooftops" ); // Roger that! I'll head for the rooftops and try to cut him off on the right! He's going to have no choice but to head west! wait 3.0; radio_dialogue( "favela_gst_wayaround" ); // Bloody hell, I'm taking a lot of fire from the militia, I don't think I can track him through the market! I'm going to have to find another way around! wait 6; // Trigger flag_wait( "dialog_faust_in_sights" ); radio_dialogue( "favela_gst_halfklick" ); // Be advised, I'm about half a klick east of the market, I can see Faust running across the rooftops on my right side! radio_dialogue( "favela_cmt_eyeopen" ); // Roger that! Roach! We're corraling him closer to your side of the hill! Keep an eye open for Faust! He's still moving across the rooftops! wait 8; radio_dialogue( "favela_gst_legshot" ); // Sir, I've got Faust in my sights! I can go for a clean leg shot! We can end it here! radio_dialogue( "favela_cmt_donotengage" ); // Negative! We can't risk it! Do not engage Faust! radio_dialogue( "favela_gst_rogerthat2" ); // Bollocks! Roger that! wait 12; radio_dialogue( "favela_cmt_nowheretogo" ); // Roach! Keep moving uphill! I've cut him off! He's got nowhere to go but west over the rooftops into your area! radio_dialogue( "favela_cmt_traphimuphere" ); // Roach! He knows the area well but we can trap him up here! Don't stop! Go! Go! wait 12; radio_dialogue( "favela_gst_jumpedfence" ); // He jumped the fence! I'm after him!!! radio_dialogue( "favela_cmt_goingleft" ); // Roger that! I'm going around to the left! wait 12; radio_dialogue( "favela_cmt_closertoyourpart" );// Roach! He's getting closer to your part of the favela!! Keep moving! Go! Go! } final_bend_dialog() { level endon( "ending_sequence_dialog" ); level endon( "player_approaching_final_stairs" ); level endon( "stop_all_misc_dialog" ); flag_wait( "player_at_final_bend" ); radio_dialogue( "favela_cmt_motorcycle" ); // Ghost he's going for that motorcycle! soundEnt = getent( "nohesnot_location", "targetname" ); soundEnt play_sound_in_space( "favela_gst_nohesnot" ); // (gunshots, explosion) No he's not. radio_dialogue( "favela_cmt_dontshoothim" ); // Nice! He's breaking to the right again! Roach, if you see him, don't shoot him! I need him unharmed! wait 0.3; radio_dialogue( "favela_cmt_onthemove" ); // Roach! He's on the move and headed your way! Go! Go! wait 4.0; radio_dialogue( "favela_cmt_anotherfence" ); // Roach! He's jumped another fence and he's still headed towards your end of the favela! Keep moving up! Go! Go! wait 4.0; radio_dialogue( "favela_cmt_corraling" ); // Keep corraling him up the hill! We'll cut him off at the top! wait 10; radio_dialogue( "favela_gst_whereishe" ); // Where is he where is he? wait 0.2; radio_dialogue( "favela_cmt_slidingrooftops" ); // Got a visual! He's over there, sliding down the tin rooftops! wait 0.2; radio_dialogue( "favela_gst_anotherlegshot" ); // I've got another clear leg shot! wait 0.2; radio_dialogue( "favela_cmt_carryhimback" ); // Negative! Not unless you want to carry him back out with all this militia breathing down your neck! I need him unharmed! } final_staircase_dialog() { flag_wait( "player_approaching_final_stairs" ); if ( flag( "ending_sequence_dialog" ) ) return; level endon( "ending_sequence_dialog" ); // Ghost, I'm going far right! radio_dialogue( "favela_cmt_farright" ); // ( Ghost - Radio ) Roger that. radio_dialogue( "favela_gst_rogerthat" ); } ending_sequence() { trigger_wait( "ending_sequence", "targetname" ); thread ending_sequence_dialog(); thread battlechatter_off( "allies" ); thread battlechatter_off( "axis" ); node = getent( "ending_node", "targetname" ); soap = spawn_targetname( "ending_soap_spawner", true ); soap.animname = "mactavish"; soap set_ignoreme( true ); soap set_ignoreall( true ); soap thread magic_bullet_shield(); faust = spawn_targetname( "ending_faust_spawner", true ); faust.animname = "faust"; faust set_ignoreme( true ); faust set_ignoreall( true ); faust thread magic_bullet_shield(); faust thread faust_mission_fail(); faust thread objective_on_faust(); car = getent( "ending_car", "targetname" ); car useanimtree( level.scr_animtree[ "car" ] ); car.animname = "car"; // do first frame animation to set it up guys[ 0 ] = soap; guys[ 1 ] = faust; guys[ 2 ] = car; node anim_first_frame( guys, "ending_takedown" ); // wait for the player to be in the area and to look at the sequence, or timeout flag_wait( "player_in_ending_area" ); faust waittill_player_lookat( 0.8, undefined, undefined, 7.0 ); // don't slomo the "no he's not" dialog SoundSetTimeScaleFactor( "Music", 0 ); SoundSetTimeScaleFactor( "Menu", 0 ); SoundSetTimeScaleFactor( "Bulletimpact", 0 ); SoundSetTimeScaleFactor( "Voice", 0 ); SoundSetTimeScaleFactor( "effects2", 0 ); SoundSetTimeScaleFactor( "Mission", 0 ); SoundSetTimeScaleFactor( "Announcer", 0 ); SoundSetTimeScaleFactor( "local", 0 ); SoundSetTimeScaleFactor( "physics", 0 ); SoundSetTimeScaleFactor( "ambient", 0 ); SoundSetTimeScaleFactor( "auto", 0 ); SoundSetTimeScaleFactor( "Shellshock", 0 ); //flag_wait( "ending_sequence_ready" ); flag_set( "ending_sequence_started" ); thread ending_sequence_ghost(); // ending sequence happens flag_clear( "faust_music" ); flag_clear( "favela_music" ); thread music_stop( 1.0 ); level.player thread play_sound_on_entity( "favela_moneyrun_endfall" ); node thread anim_single( guys, "ending_takedown" ); delayThread( 13.0, ::fade_out_level ); wait 5.2; assert( isdefined( level.ghost ) ); level.ghost anim_single_solo( level.ghost, "favela_gst_sendchopper" ); wait 0.8; level.ghost anim_single_solo( level.ghost, "favela_gst_skiesareclear" ); wait 1.0; level.ghost thread anim_single_solo( level.ghost, "favela_gst_onourown" ); wait 4; nextmission(); } fade_out_level() { fadeInTime = 1.0; setSavedDvar( "compass", 0 ); setSavedDvar( "hud_showStance", 0 ); overlay = newHudElem(); overlay.x = 0; overlay.y = 0; overlay setshader( "black", 640, 480 ); overlay.alignX = "left"; overlay.alignY = "top"; overlay.horzAlign = "fullscreen"; overlay.vertAlign = "fullscreen"; overlay.alpha = 0; overlay fadeOverTime( fadeInTime ); overlay.alpha = 1; wait fadeInTime; level.player freezeControls( true ); enablePlayerWeapons( false ); } ending_sequence_ghost() { level.ghost = spawn_targetname( "ending_ghost_spawner", true ); level.ghost.animname = "ghost"; level.ghost set_ignoreme( true ); level.ghost set_ignoreall( true ); level.ghost thread magic_bullet_shield(); } ending_sequence_dialog() { flag_set( "ending_sequence_dialog" ); if ( !flag( "ending_sequence_started" ) ) { // ( Ghost - Radio ) He's gonna get away!! radio_dialogue( "favela_gst_getaway" ); } //flag_set( "ending_sequence_ready" ); flag_wait( "ending_sequence_started" ); // No he's not. radio_dialogue( "favela_cmt_nohesnot" ); flag_set( "start_final_dialog" ); } ending_sequence_slowmo() { wait 0.15; if ( !player_looking_at( self.origin, undefined, true ) ) return; slomoLerpTime_in = 0.5; slomoLerpTime_out = 0.65; slomobreachplayerspeed = 0.1; slomoSpeed = 0.2; slomoDuration = 2.0; level.player thread play_sound_on_entity( "slomo_whoosh" ); slowmo_start(); slowmo_setspeed_slow( slomoSpeed ); slowmo_setlerptime_in( slomoLerpTime_in ); slowmo_lerp_in(); level.player SetMoveSpeedScale( slomobreachplayerspeed ); wait slomoDuration * slomoSpeed; level.player thread play_sound_on_entity( "slomo_whoosh" ); slowmo_setlerptime_out( slomoLerpTime_out ); slowmo_lerp_out(); slowmo_end(); level.player SetMoveSpeedScale( 1.0 ); wait 1; objective_State( 2, "done" ); }