#include common_scripts\utility; #include maps\_utility; #include maps\_anim; #include maps\_specialops; // --------------------------------------------------------------------------------- should_spawn() { switch ( level.gameSkill ) { case 0: case 1: return !( self.spawnflags & 256 ); case 2: return !( self.spawnflags & 512 ); case 3: return !( self.spawnflags & 1024 ); } } // --------------------------------------------------------------------------------- create_ghillie_enemies( enemy_id, wait_id, activate_id ) { ghillie_enemies_init(); assertex( isdefined( enemy_id ), "create_ghillie_enemies() requires a valid enemy_id" ); ghillie_spawners = getentarray ( enemy_id, "targetname" ); assertex( ghillie_spawners.size > 0, "create_ghillie_enemies() could not find any spawners with id " + enemy_id ); if ( isdefined( wait_id ) ) level waittill( wait_id ); thread stealth_disable(); array_thread( ghillie_spawners, ::add_spawn_function, ::ghillie_enemy_init, enemy_id, activate_id ); foreach ( ghillie in ghillie_spawners ) { if ( ghillie should_spawn() ) ghillie spawn_ai( true ); } } ghillie_enemies_init() { if ( isdefined( level.ghillie_enemies_initialized ) && level.ghillie_enemies_initialized ) return; foreach ( player in level.players ) player thread ghillie_player_damage_tracker(); level.ghillie_enemies_initialized = true; level.ghillies_unaware = []; level.ghillies_nofire = []; level.ghillies_active = []; } ghillie_player_damage_tracker() { level endon( "special_op_terminated" ); self endon( "death" ); while ( 1 ) { self waittill( "damage", damage, attacker ); // is it a ghillie? if ( !isai( attacker ) || !isdefined( attacker.ghillie_is_prone ) ) continue; // Only set this if they are currently unaware. if ( !array_contains( level.ghillies_unaware, attacker.unique_id ) ) continue; attacker ghillie_enemy_set_fired(); } } ghillie_enemy_init( enemy_id, activate_id ) { level.ghillie_count++; level.enemies_spawned++; // Ghillies count as "unaware" before they've fired their first shot. ghillie_enemy_set_unaware(); // self.sightlatency = 1000; self.baseaccuracy = 6; self.goalradius = 96; self.grenadeAmmo = 0; self.dontEverShoot = true; self.allowdeath = true; self.neverForceSniperMissEnemy = true; self.ghillie_is_prone = false; self.ghillie_is_frozen = false; ghillie_enemy_set_flub_time(); anim.shootEnemyWrapper_func = animscripts\utility::ShootEnemyWrapper_shootNotify; thread ghillie_enemy_register_death(); thread ghillie_enemy_behavior( activate_id ); maps\_stealth_utility::disable_stealth_for_ai(); } ghillie_enemy_register_death() { level endon( "special_op_terminated" ); self endon ("ghillie_silent_kill" ); my_id = self.unique_id; self waittill( "death", attacker ); level.ghillie_count--; if ( array_contains( level.ghillies_unaware, my_id ) ) death_register_unaware( attacker, undefined, true ); else if ( array_contains( level.ghillies_nofire, my_id ) ) death_register_nofire( attacker, undefined, true ); else death_register_basic( attacker, undefined, true ); } // This can probably be revisited to be simpler. ghillie_enemy_behavior( activate_id ) { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); self.combatmode = "no_cover"; ghillie_enemy_freeze_while_prone(); if ( isdefined( activate_id ) ) flag_wait( activate_id ); else wait 1; thread ghillie_enemy_quit_when_sidearm(); foreach ( player in level.players ) thread ghillie_enemy_detect_player_looking( player ); ghillie_enemy_resume_moving( "stand" ); if ( !ghillie_enemy_can_be_seen( false, true ) ) ghillie_enemy_crouch_and_fire(); ghillie_enemy_go_prone(); ghillie_enemy_freeze_while_prone(); while( 1 ) { if( ghillie_enemy_can_be_seen( false, true ) ) { wait 0.5; continue; } move_time = ghillie_get_move_time(); crouch = randomfloat( 1.0 ) < level.ghillie_crouch_chance; if ( crouch ) thread ghillie_enemy_resume_moving( "crouch", move_time ); else thread ghillie_enemy_resume_moving( "prone", move_time ); time_moved = 0.0; while( time_moved < move_time ) { wait 1.0; time_moved += 1.0; if ( ghillie_enemy_can_be_seen( false, false ) ) { self notify( "stop_moving" ); if ( crouch ) ghillie_enemy_go_prone(); ghillie_enemy_freeze_while_prone(); while ( ghillie_enemy_can_be_seen( false, false ) ) wait 0.05; } new_move_time = clamp( move_time - time_moved, 0, move_time ); if ( new_move_time > 0 ) { if ( crouch ) thread ghillie_enemy_resume_moving( "crouch", new_move_time ); else thread ghillie_enemy_resume_moving( "prone", new_move_time ); } } self notify( "stop_moving" ); shot_attempts = 0; ghillie_enemy_crouch_and_fire(); while ( !ghillie_enemy_can_be_seen( false, false ) && ( shot_attempts <= randomintrange( 1, 4 ) ) ) { shot_attempts++; ghillie_enemy_crouch_and_fire(); } ghillie_enemy_go_prone(); ghillie_enemy_freeze_while_prone(); } } ghillie_enemy_go_prone() { self allowedstances( "prone" ); if ( !self.ghillie_is_prone ) { self.ghillie_is_frozen = false; self.ghillie_is_prone = true; self anim_generic_custom_animmode( self, "gravity", "pronehide_dive" ); } } ghillie_enemy_freeze_while_prone() { if ( self.ghillie_is_frozen ) return; self allowedstances( "prone" ); self.ghillie_is_prone = true; self.ghillie_is_frozen = true; self thread anim_generic_loop( self, "prone_idle", "stop_loop" ); } ghillie_enemy_resume_moving( stance, move_time ) { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); self endon( "stop_moving" ); anim_stopanimscripted(); self allowedstances( stance ); self.ghillie_is_frozen = false; switch ( stance ) { case "prone": self.ghillie_is_prone = true; break; case "crouch": self.ghillie_is_prone = false; break; case "stand": self.ghillie_is_prone = false; break; } ghillie_enemy_set_goal_pos(); self waittill( "goal_changed" ); if ( !isdefined( move_time ) ) move_time = ghillie_get_move_time(); wait move_time; } ghillie_get_move_time() { if ( isdefined( self.ghillie_moved_once ) && self.ghillie_moved_once ) return ghillie_get_time( level.ghillie_move_time_min, level.ghillie_move_time_max ); self.ghillie_moved_once = true; return ghillie_get_time( level.ghillie_move_intro_min, level.ghillie_move_intro_max ); } ghillie_enemy_crouch_and_fire() { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); anim_stopanimscripted(); self allowedstances( "crouch" ); self.ghillie_is_prone = false; self.ghillie_is_froze = false; self setgoalpos( self.origin ); thread ghillie_enemy_enable_shooting(); thread ghillie_enemy_abandon_shooting(); // if ( isdefined( level.ghillies_unaware[ self.unique_id ] ) ) // thread ghillie_enemy_detect_fire(); waittill_any( "shooting", "abandon_shooting" ); self.dontEverShoot = true; wait ghillie_get_time( level.ghillie_shoot_hold_min, level.ghillie_shoot_hold_max ); } ghillie_enemy_detect_fire() { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); self endon( "abandon_shooting" ); self waittill( "shooting" ); ghillie_enemy_set_fired(); } ghillie_enemy_enable_shooting() { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); self endon( "abandon_shooting" ); wait ghillie_get_time( level.ghillie_shoot_pause_min, level.ghillie_shoot_pause_max ); self.dontEverShoot = undefined; } ghillie_enemy_abandon_shooting() { level endon( "special_op_terminated" ); self endon( "quit_ghillie_behavior" ); self endon( "death" ); self endon( "pain_death" ); self endon( "shooting" ); self endon( "enemy_visible" ); wait ghillie_get_time( level.ghillie_shoot_quit_min, level.ghillie_shoot_quit_max ); self notify( "abandon_shooting" ); } ghillie_enemy_quit_when_sidearm() { level endon( "special_op_terminated" ); self endon( "quit_ghillie_forever" ); self endon( "death" ); self endon( "pain_death" ); self waittill( "switched_to_sidearm" ); ghillie_enemy_quit_ghillie(); } ghillie_enemy_detect_player_looking( player ) { level endon( "special_op_terminated" ); self endon( "quit_ghillie_forever" ); self endon( "death" ); self endon( "pain_death" ); while ( 1 ) { self waittill_player_lookat( 0.95, 1.0, true, undefined, undefined, player ); dist = distance( self.origin, player.origin ); if ( dist > level.ghillie_go_aggro_distance ) { wait 0.5; continue; } break; } ghillie_enemy_quit_ghillie(); } ghillie_enemy_quit_ghillie() { ghillie_enemy_set_fired(); thread ghillie_enemy_detect_fire_active(); self.ghillie_is_prone = false; self.ghillie_is_frozen = false; // self.combatmode = "cover"; self.dontEverShoot = undefined; self allowedstances( "stand", "crouch" ); self.goalradius = 512; self setEngagementMinDist( 0, 0 ); self setEngagementMaxDist( 8000, 9000 ); self anim_stopanimscripted(); self notify ( "quit_ghillie_behavior" ); self notify( "quit_ghillie_forever" ); self thread ghillie_enemy_update_target(); } ghillie_enemies_quit_ghillie() { enemies = getaiarray( "axis" ); foreach ( guy in enemies ) { if ( guy.classname == "actor_enemy_ghillie_sniper" ) { wait 0.05; if ( !isalive( guy ) || !isdefined( guy ) ) continue; guy ghillie_enemy_quit_ghillie(); } } } ghillie_enemy_update_target() { level endon( "special_op_terminated" ); self endon( "death" ); self endon( "pain_death" ); while ( 1 ) { self setgoalentity( get_closest_player_healthy( self.origin ) ); wait 1; } } ghillie_enemy_detect_fire_active() { level endon( "special_op_terminated" ); self endon( "death" ); self endon( "pain_death" ); waittill_any( "shooting", "meleeanim" ); ghillie_enemy_set_active(); } ghillie_enemy_set_goal_pos() { close_player = get_closest_player_healthy( self.origin ); self setgoalpos( close_player.origin ); } ghillie_enemy_silent_remove() { self endon( "death" ); level endon( "special_op_terminated" ); while ( 1 ) { if ( !ghillie_enemy_should_delete() ) { wait 1; continue; } self notify( "ghillie_silent_kill" ); self Delete(); break; } } ghillie_enemy_should_delete() { if ( ghillie_enemy_can_be_seen( false, true ) ) return false; foreach ( player in level.players ) { if ( distance( player.origin, self.origin ) < 512 ) return false; } return true; } ghillie_enemy_can_be_seen( check_for_flub, check_offset ) { can_see_me = ghillie_enemy_sight_test( level.player, check_offset ); if ( !can_see_me && is_coop() ) can_see_me = ghillie_enemy_sight_test( level.player2, check_offset ); // If I can be seen, then check for a flub. If not, then restart my flub from scratch. if ( isdefined( check_for_flub ) && check_for_flub ) { if ( can_see_me ) can_see_me = ghillie_enemy_check_flub(); else ghillie_enemy_clear_flub_time(); } return can_see_me; } ghillie_enemy_sight_test( player, check_offset ) { if ( is_player_down_and_out( player ) ) return false; my_eye = self geteye(); their_eye = player geteye(); dot = 0.9; if ( player playerADS() >= 0.8 ) dot = 0.998; if ( !player player_looking_at( my_eye, dot, true ) ) return false; // Normal tests can_see_me = SightTracePassed( my_eye, their_eye, false, self ); if ( !can_see_me ) can_see_me = SightTracePassed( self.origin, their_eye, false, self ); if ( !can_see_me && self.ghillie_is_prone && isdefined( check_offset ) && check_offset ) { offset = 96; can_see_me = SightTracePassed( my_eye + ( 0, 0, offset ), their_eye, false, self ); if ( !can_see_me ) can_see_me = SightTracePassed( self.origin + ( 0, 0, offset ), their_eye, false, self ); } return can_see_me; } ghillie_enemy_check_flub() { // If we aren't allowing flubs, always return true. if ( !isdefined( level.ghillie_flub_time_min ) ) return true; // If we don't have a current flub time, set it now and return. // This makes it so the time is set from the first moment of being seen again. if ( !isdefined( self.ghillie_flub_time ) ) { ghillie_enemy_set_flub_time(); return true; } // Otherwise, player has been staring at me, see if I should make a mistake. if ( gettime() < self.ghillie_flub_time ) return true; // We are ready to make a mistake. ghillie_enemy_clear_flub_time(); return false; } ghillie_enemy_set_unaware() { my_id = self.unique_id; level.ghillies_unaware[ my_id ] = my_id; level.ghillies_nofire = array_remove( level.ghillies_nofire, my_id ); level.ghillies_active = array_remove( level.ghillies_active, my_id ); } ghillie_enemy_set_fired() { my_id = self.unique_id; level.ghillies_nofire[ my_id ] = my_id; level.ghillies_unaware = array_remove( level.ghillies_unaware, my_id ); level.ghillies_active = array_remove( level.ghillies_active, my_id ); } ghillie_enemy_set_active() { my_id = self.unique_id; level.ghillies_active[ my_id ] = my_id; level.ghillies_unaware = array_remove( level.ghillies_unaware, my_id ); level.ghillies_nofire = array_remove( level.ghillies_nofire, my_id ); } ghillie_enemy_set_flub_time() { if ( !isdefined( level.ghillie_flub_time_min ) ) return; self.ghillie_flub_time = gettime() + ghillie_get_time( level.ghillie_flub_time_min, level.ghillie_flub_time_max ); } ghillie_enemy_clear_flub_time() { self.ghillie_flub_time = undefined; } ghillie_get_time( time_min, time_max ) { wait_time = randomfloatrange( time_min, time_max ); if ( is_coop() ) wait_time *= level.coop_difficulty_scalar; return wait_time; } // --------------------------------------------------------------------------------- create_patrol_enemies( enemy_id, wait_id, spawn_delay ) { patrol_enemies_init(); assertex( isdefined( enemy_id ), "create_patrol_enemies() requires a valid enemy_id" ); if ( isdefined( wait_id ) ) level waittill( wait_id ); thread stealth_enable(); patrol_spawners = getentarray( enemy_id, "targetname" ); assertex( patrol_spawners.size > 0, "create_patrol_enemies() could not find any spawners with id " + enemy_id ); array_thread( patrol_spawners, ::add_spawn_function, ::patrol_enemy_init ); foreach ( spawner in patrol_spawners ) spawner patrol_enemy_spawn(); } patrol_enemy_spawn() { if ( !should_spawn() ) return ; level endon( "special_op_terminated" ); stagger = isdefined( self.script_noteworthy ) && ( self.script_noteworthy == "patrol_stagger_spawn" ); if ( stagger ) wait randomfloatrange( 0.0, 3.0 ); self spawn_ai( true ); } patrol_enemies_init() { if ( isdefined( level.patrol_enemies_initialized ) && level.patrol_enemies_initialized ) return; thread script_chatgroups(); level.patrol_enemies_initialized = true; level.patrols = []; level.patrols_unaware = []; level.patrols_nofire = []; } patrol_enemy_init() { level.patrol_count++; level.enemies_spawned++; thread patrol_enemy_register_alert(); thread patrol_enemy_register_attack(); thread patrol_enemy_register_death(); maps\_stealth_utility::stealth_default(); if ( isdefined( self.target ) ) thread maps\_patrol::patrol(); self.patrol_stop = []; self.patrol_start = []; self.baseaccuracy = 2.0; } patrol_enemy_register_alert() { level endon( "special_op_terminated" ); my_id = self.unique_id; level.patrols_unaware[ my_id ] = my_id; self waittill( "enemy" ); level.patrols_unaware = array_remove( level.patrols_unaware, my_id ); } patrol_enemy_register_attack() { level endon( "special_op_terminated" ); my_id = self.unique_id; level.patrols_nofire[ my_id ] = my_id; self waittill( "shooting" ); level.patrols_nofire = array_remove( level.patrols_nofire, my_id ); } patrol_enemy_register_death() { level endon( "special_op_terminated" ); self endon( "patrol_silent_kill" ); my_id = self.unique_id; level.patrols = array_add( level.patrols, self ); self waittill( "death", attacker, cause, weapon_name ); level.patrol_count--; level.patrols = array_removedead( level.patrols ); if ( patrol_enemy_can_multi_kill( attacker, cause, weapon_name ) ) { // Only register multi-kills when in stealth. current_time = gettime(); if ( current_time == level.patrol_death_time ) level.patrol_multi_kills++; else patrol_enemy_reset_multi_kill(); } else { patrol_enemy_reset_multi_kill(); } special_dialog = false; if ( level.patrol_multi_kills > 1 ) { special_dialog = true; switch ( level.patrol_multi_kills ) { case 2: thread patrol_enemy_kill_double(); break; case 3: thread patrol_enemy_kill_triple(); break; default: // No known 4x+ kill possibilities. Better to say nothing than sound dumb. } } if ( array_contains( level.patrols_unaware, my_id ) ) thread death_register_unaware( attacker, false, special_dialog ); else if ( array_contains( level.patrols_nofire, my_id ) ) thread death_register_nofire( attacker, false, special_dialog ); else thread death_register_basic( attacker, false, special_dialog ); } patrol_enemy_can_multi_kill( attacker, cause, weapon_name ) { if ( flag( "_stealth_spotted" ) ) return false; if ( !isdefined( attacker ) || !isplayer( attacker ) ) return false; if( !( cause == "MOD_PISTOL_BULLET" || cause == "MOD_RIFLE_BULLET" ) ) return false; return true; } patrol_enemy_reset_multi_kill() { level.patrol_multi_kills = 1; level.patrol_death_time = gettime(); } patrol_enemy_kill_double() { level endon( "special_op_terminated" ); level notify( "multi_kill_message" ); level endon( "multi_kill_message" ); wait 0.5; radio_dialogue( "so_hid_ghil_double_kill" ); } patrol_enemy_kill_triple() { level endon( "special_op_terminated" ); level notify( "multi_kill_message" ); level endon( "multi_kill_message" ); wait 0.5; radio_dialogue( "so_hid_ghil_triple_kill" ); } patrol_enemy_silent_remove() { self endon( "death" ); level endon( "special_op_terminated" ); while( 1 ) { if ( !patrol_enemy_should_delete() ) { wait 1; continue; } self notify( "patrol_silent_kill" ); level.patrols = array_remove( level.patrols, self ); self Delete(); break; } } patrol_enemy_should_delete() { if ( flag( "_stealth_spotted" ) ) return false; foreach ( player in level.players ) { if ( distance( player.origin, self.origin ) < 384 ) return false; if ( patrol_enemy_sight_test( player ) ) return false; } return true; } patrol_enemy_sight_test( player ) { my_eye = self geteye(); if ( !player player_looking_at( self.origin, 0.9, true ) && !player player_looking_at( my_eye, 0.9, true ) ) return false; their_eye = player geteye(); if ( !SightTracePassed( self.origin, their_eye, false, self ) && !SightTracePassed( my_eye, their_eye, false, self ) ) return false; return true; } // --------------------------------------------------------------------------------- death_register_unaware( attacker, force_dialog, skip_dialog ) { if ( isdefined( attacker ) && isplayer( attacker ) ) { level notify( "kill_registered" ); attacker.kills_stealth++; } level.deaths_stealth++; level.bonus_time_given += level.bonus_stealth; death_dialog( level.dialog_kill_stealth, level.deaths_stealth, force_dialog, skip_dialog ); } death_register_nofire( attacker, force_dialog, skip_dialog ) { if ( isdefined( attacker ) && isplayer( attacker ) ) { level notify( "kill_registered" ); attacker.kills_nofire++; } level.deaths_nofire++; level.bonus_time_given += level.bonus_nofire; death_dialog( level.dialog_kill_quiet, level.deaths_nofire, force_dialog, skip_dialog ); } death_register_basic( attacker, force_dialog, skip_dialog ) { if ( isdefined( attacker ) && isplayer( attacker ) ) { level notify( "kill_registered" ); attacker.kills_basic++; } level.deaths_basic++; level.bonus_time_given += level.bonus_basic; // The "basic" dialog wound up being a bit too harsh, so using these lines for the kills, and will use // the "sloppy" type lines for once everyone is dead after stealth is broken. // death_dialog( level.dialog_kill_basic, level.deaths_basic, force_dialog, skip_dialog ); // New update, no lines for "broken stealth" kills. // death_dialog( level.dialog_kill_quiet, level.deaths_nofire, force_dialog, skip_dialog ); } death_dialog( dialog, total, force_dialog, skip_dialog ) { level endon( "special_op_terminated" ); level endon( "multi_kill_message" ); if ( isdefined( skip_dialog ) && skip_dialog ) return; if ( !isdefined( force_dialog ) || !force_dialog ) { if ( level.death_dialog_time > gettime() ) return; } level.death_dialog_time = gettime() + level.death_dialog_throttle; wait 0.5; radio_dialogue( dialog[ total % dialog.size ], 1.0 ); } // --------------------------------------------------------------------------------- turn_on_stealth() { battlechatter_off( "axis" ); battlechatter_off( "allies" ); maps\_stealth::main(); foreach ( player in level.players ) player maps\_stealth_utility::stealth_default(); init_prone_DOF(); rangesHidden = []; rangesHidden[ "prone" ] = 200; rangesHidden[ "crouch" ] = 600; rangesHidden[ "stand" ] = 1500; rangesSpotted = []; rangesSpotted[ "prone" ] = 600; rangesSpotted[ "crouch" ] = 1200; rangesSpotted[ "stand" ] = 2500; maps\_stealth_utility::stealth_detect_ranges_set( rangesHidden, rangesSpotted ); thread stealth_music_loop(); // Decided to not chastize player ever. // thread stealth_chastize_loop(); } stealth_disable() { level endon( "special_op_terminated" ); // Currently the Ghillies behave poorly when the Stealth System is active. The way the map is structured // makes it viable to disable stealth from pocket to pocket. Wait until all the patrols are dead before doing // so though, just in case they are at the edge. // A flag can be set to force it (player touches a trigger where they've gone too far to allow stealth to continue. while ( level.patrol_count > 0 && !flag( "force_disable_stealth" ) ) wait 1; foreach ( player in level.players ) { player.maxVisibleDist = 8192; if ( player ent_flag_exist( "_stealth_enabled" ) ) player ent_flag_clear( "_stealth_enabled" ); } if ( isdefined( level.patrols ) ) { foreach ( patrol in level.patrols ) patrol thread patrol_enemy_silent_remove(); } } stealth_enable() { // Clear this so the next trigger has a chance to set it when new ghillies are spawned. flag_clear( "force_disable_stealth" ); // Force the ghillies out of ghillie mode. ghillie_enemies_quit_ghillie(); foreach ( player in level.players ) { if ( player ent_flag_exist( "_stealth_enabled" ) ) player ent_flag_set( "_stealth_enabled" ); player thread maps\_stealth_visibility_friendly::friendly_visibility_logic(); } } stealth_music_loop() { level endon( "special_op_terminated" ); while ( 1 ) { thread stealth_music_hidden_loop(); flag_wait( "_stealth_spotted" ); music_stop( .2 ); wait .5; thread stealth_music_busted_loop(); flag_waitopen( "_stealth_spotted" ); music_stop( 3 ); wait 3.25; } } stealth_music_hidden_loop() { music_loop( "so_hidden_so_ghillies_stealth_music", 2 ); /* level endon( "special_op_terminated" ); level endon( "_stealth_spotted" ); hidden_stealth_music_TIME = 119; while ( 1 ) { MusicPlayWrapper( "so_hidden_so_ghillies_stealth_music" ); wait hidden_stealth_music_TIME; wait 2; }*/ } stealth_music_busted_loop() { music_loop( "so_hidden_so_ghillies_busted_music", 2 ); /* level endon( "special_op_terminated" ); level endon( "_stealth_spotted" ); hidden_stealth_busted_music_TIME = 88; while ( 1 ) { MusicPlayWrapper( "so_hidden_so_ghillies_busted_music" ); wait hidden_stealth_busted_music_TIME; wait 2; }*/ } stealth_chastize_loop() { level endon( "special_op_terminated" ); while ( 1 ) { flag_wait( "_stealth_spotted" ); flag_waitopen( "_stealth_spotted" ); wait 1; death_dialog( level.dialog_kill_basic, level.deaths_basic, true ); } } // --------------------------------------------------------------------------------- turn_on_radiation() { thread maps\_radiation::main(); wait 4; thread radio_dialogue( "so_hid_ghil_rad_warning" ); } // --------------------------------------------------------------------------------- hud_bonuses_create() { ypos = so_hud_ypos(); stealth_title = so_create_hud_item( 3, ypos, &"SO_HIDDEN_SO_GHILLIES_KILL_STEALTH", self ); nofire_title = so_create_hud_item( 4, ypos, &"SO_HIDDEN_SO_GHILLIES_KILL_NOFIRE", self ); basic_title = so_create_hud_item( 5, ypos, &"SO_HIDDEN_SO_GHILLIES_KILL_BASIC", self ); stealth_kills = so_create_hud_item( 3, ypos, undefined, self ); nofire_kills = so_create_hud_item( 4, ypos, undefined, self); basic_kills = so_create_hud_item( 5, ypos, undefined, self); stealth_kills.alignx = "left"; nofire_kills.alignx = "left"; basic_kills.alignx = "left"; stealth_kills SetValue( 0 ); nofire_kills SetValue( 0 ); basic_kills SetValue( 0 ); thread info_hud_handle_fade( stealth_title, "so_hidden_complete" ); thread info_hud_handle_fade( nofire_title, "so_hidden_complete" ); thread info_hud_handle_fade( basic_title, "so_hidden_complete" ); thread info_hud_handle_fade( stealth_kills, "so_hidden_complete" ); thread info_hud_handle_fade( nofire_kills, "so_hidden_complete" ); thread info_hud_handle_fade( basic_kills, "so_hidden_complete" ); thread hud_bonuses_update_scores( stealth_kills, nofire_kills, basic_kills ); flag_wait( "so_hidden_complete" ); stealth_title thread so_remove_hud_item(); nofire_title thread so_remove_hud_item(); basic_title thread so_remove_hud_item(); stealth_kills thread so_remove_hud_item(); nofire_kills thread so_remove_hud_item(); basic_kills thread so_remove_hud_item(); } hud_bonuses_update_scores( stealth_kills, nofire_kills, basic_kills ) { level endon( "special_op_terminated" ); while ( 1 ) { level waittill( "kill_registered" ); stealth_kills SetValue( self.kills_stealth ); nofire_kills SetValue( self.kills_nofire ); basic_kills SetValue( self.kills_basic ); } } // --------------------------------------------------------------------------------- objective_set_chopper() { flag_wait( "so_hidden_obj_chopper" ); obj = getstruct( "so_hidden_obj_chopper", "script_noteworthy" ); objective_position( 1, obj.origin ); playFX( getfx( "extraction_smoke" ), obj.origin ); } // --------------------------------------------------------------------------------- create_chatter_aliases_for_patrols() { aliases = []; aliases[ aliases.size ] = "scoutsniper_ru1_passcig"; aliases[ aliases.size ] = "scoutsniper_ru2_whoseturnisit"; aliases[ aliases.size ] = "scoutsniper_ru1_wakeup"; aliases[ aliases.size ] = "scoutsniper_ru2_buymotorbike"; aliases[ aliases.size ] = "scoutsniper_ru1_tooexpensive"; aliases[ aliases.size ] = "scoutsniper_ru2_illtakecareofit"; aliases[ aliases.size ] = "scoutsniper_ru1_otherteam"; aliases[ aliases.size ] = "scoutsniper_ru2_notwandering"; aliases[ aliases.size ] = "scoutsniper_ru1_wandering"; aliases[ aliases.size ] = "scoutsniper_ru2_zahkaevspayinggood"; aliases[ aliases.size ] = "scoutsniper_ru1_wasteland"; //aliases[ aliases.size ] = "scoutsniper_ru2_imonit";//yelling //aliases[ aliases.size ] = "scoutsniper_ru1_takealook";//radio and loud aliases[ aliases.size ] = "scoutsniper_ru2_whoseturnisit"; aliases[ aliases.size ] = "scoutsniper_ru1_onourway"; aliases[ aliases.size ] = "scoutsniper_ru1_passcig"; aliases[ aliases.size ] = "scoutsniper_ru2_youidiot"; aliases[ aliases.size ] = "scoutsniper_ru1_wakeup"; aliases[ aliases.size ] = "scoutsniper_ru2_call"; aliases[ aliases.size ] = "scoutsniper_ru1_tooexpensive"; aliases[ aliases.size ] = "scoutsniper_ru2_americagoingtostartwar"; aliases[ aliases.size ] = "scoutsniper_ru4_raise"; aliases[ aliases.size ] = "scoutsniper_ru2_sendsomeonetocheck"; aliases[ aliases.size ] = "scoutsniper_ru4_ifold"; aliases[ aliases.size ] = "scoutsniper_ru2_andreibringingfood"; aliases[ aliases.size ] = "scoutsniper_ru4_thisonesheavy"; aliases[ aliases.size ] = "scoutsniper_ru2_quicklyaspossible"; aliases[ aliases.size ] = "scoutsniper_ru4_didnteatbreakfast"; aliases[ aliases.size ] = "scoutsniper_ru2_yescomrade"; aliases[ aliases.size ] = "scoutsniper_ru4_takenzakhaevsoffer"; aliases[ aliases.size ] = "scoutsniper_ru2_clearrotorblades"; //aliases[ aliases.size ] = "scoutsniper_ru4_mayhaveproblem";//fear aliases[ aliases.size ] = "scoutsniper_ru2_radiationdosimeters"; aliases[ aliases.size ] = "scoutsniper_ru4_canceltransactions"; aliases[ aliases.size ] = "scoutsniper_ru2_dontbelieveatall"; aliases[ aliases.size ] = "scoutsniper_ru4_cantwaitforshiftend"; aliases[ aliases.size ] = "scoutsniper_ru2_ok"; aliases[ aliases.size ] = "scoutsniper_ru4_hopeitdoesntrain"; aliases[ aliases.size ] = "scoutsniper_ru2_professionaljob"; level.chatter_aliases = aliases; } script_chatgroups() { level.last_talker = undefined; talker = undefined; create_chatter_aliases_for_patrols(); spawners = GetSpawnerTeamArray( "axis" ); array_thread( spawners, ::add_spawn_function, ::setup_chatter ); level.current_conversation_point = RandomInt( level.chatter_aliases.size ); while ( true /*!flag( "done_with_stealth_camp" )*/ ) { flag_waitopen( "_stealth_spotted" ); closest_talker = undefined; next_closest = undefined; enemies = GetAIArray( "axis" ); //sort from closest to furthest closest_enemies = get_array_of_closest( getAveragePlayerOrigin(), enemies ); for ( i = 0; i < closest_enemies.size; i++ ) { if ( IsDefined( closest_enemies[ i ].script_chatgroup ) ) { closest_chat_group = closest_enemies[ i ].script_chatgroup; closest_talker = closest_enemies[ i ]; if ( closest_talker ent_flag_exist( "_stealth_normal" ) ) if ( !closest_talker ent_flag( "_stealth_normal" ) ) continue; //find next closest member of same chat group next_closest = find_next_member( closest_enemies, i, closest_chat_group ); //if has no buddy or is too far from buddy or buddy is alert find another if ( !isdefined( next_closest ) ) continue; if ( next_closest ent_flag_exist( "_stealth_normal" ) ) if ( !next_closest ent_flag( "_stealth_normal" ) ) continue; d = Distance( next_closest.origin, closest_talker.origin ); if ( d > 220 ) { //println( d ); continue; } else break; } } //we have a group, say something if ( IsDefined( next_closest ) ) { //check if closest guy is our last talker, if so use second closest if ( IsDefined( level.last_talker ) ) { if ( level.last_talker == closest_talker ) talker = next_closest; else talker = closest_talker; } else talker = closest_talker; talker chatter_play_sound( level.chatter_aliases[ level.current_conversation_point ] ); level.current_conversation_point++; if ( level.current_conversation_point >= level.chatter_aliases.size ) level.current_conversation_point = 0; level.last_talker = talker; wait .5;// conversation has pauses } else wait 2;// lets try again in 2 seconds } } setup_chatter() { if ( !isdefined( self.script_chatgroup ) ) return; self endon( "death" ); self ent_flag_init( "mission_dialogue_kill" ); self setup_chatter_kill_wait(); self ent_flag_set( "mission_dialogue_kill" ); } setup_chatter_kill_wait() { self endon( "death" ); self endon( "event_awareness" ); self endon( "enemy" ); flag_wait_any( "_stealth_spotted", "_stealth_found_corpse" ); } chatter_play_sound( alias ) { if ( is_dead_sentient() ) return; org = Spawn( "script_origin", ( 0, 0, 0 ) ); org endon( "death" ); thread maps\_utility::delete_on_death_wait_sound( org, "sounddone" ); org.origin = self.origin; org.angles = self.angles; org LinkTo( self ); org PlaySound( alias, "sounddone" ); //println( "script_chatter alias = " + alias ); self chatter_play_sound_wait( org ); if ( IsAlive( self ) ) self notify( "play_sound_done" ); org StopSounds(); wait( 0.05 );// stopsounds doesnt work if the org is deleted same frame org Delete(); } chatter_play_sound_wait( org ) { self endon( "death" ); self endon( "mission_dialogue_kill" ); org waittill( "sounddone" ); } find_next_member( closest_enemies, closest, closest_chat_group ) { for ( i = closest + 1; i < closest_enemies.size; i++ ) { if ( IsDefined( closest_enemies[ i ].script_chatgroup ) ) { if ( closest_enemies[ i ].script_chatgroup == closest_chat_group ) return closest_enemies[ i ]; } } return undefined; } // --------------------------------------------------------------------------------- clip_nosight_wait_for_activate() { self endon( "death" ); flag_wait( self.script_flag ); self thread clip_nosight_wait_damage(); self thread clip_nosight_wait_stealth(); } clip_nosight_wait_damage() { if ( flag( "_stealth_spotted" ) ) return; level endon( "_stealth_spotted" ); self setcandamage( true ); self waittill( "damage" ); self delete(); } clip_nosight_wait_stealth() { self endon( "death" ); flag_wait_either( "_stealth_spotted", "_stealth_found_corpse" ); self delete(); } // --------------------------------------------------------------------------------- init_prone_DOF() { foreach ( player in level.players ) { player.dofDefault[ "nearStart" ]= level.dofDefault[ "nearStart" ]; player.dofDefault[ "nearEnd" ] = level.dofDefault[ "nearEnd" ]; player.dofDefault[ "nearBlur" ] = level.dofDefault[ "nearBlur" ]; player.dofDefault[ "farStart" ] = level.dofDefault[ "farStart" ]; player.dofDefault[ "farEnd" ] = level.dofDefault[ "farEnd" ]; player.dofDefault[ "farBlur" ] = level.dofDefault[ "farBlur" ]; player.dofProne[ "nearStart" ] = 10; player.dofProne[ "nearEnd" ] = 50; player.dofProne[ "nearBlur" ] = 6; player.dofReg[ "nearStart" ] = player.dofDefault[ "nearStart" ]; player.dofReg[ "nearEnd" ] = player.dofDefault[ "nearEnd" ]; player.dofReg[ "nearBlur" ] = player.dofDefault[ "nearBlur" ]; player thread player_prone_DOF(); } } player_prone_DOF() { self endon( "death" ); while ( 1 ) { my_stance = self getstance(); if ( my_stance == "prone" ) self set_prone_DOF(); else self set_default_DOF(); wait 0.05; } } set_default_DOF() { if ( self.dofDefault[ "nearStart" ] == self.dofReg[ "nearStart" ] ) return; self.dofDefault[ "nearStart" ] = self.dofReg[ "nearStart" ]; self.dofDefault[ "nearEnd" ] = self.dofReg[ "nearEnd" ]; self.dofDefault[ "nearBlur" ] = self.dofReg[ "nearBlur" ]; self setViewModelDepthOfField( 0, 0 ); self maps\_art::setdefaultdepthoffield(); } set_prone_DOF() { if ( self.dofDefault[ "nearStart" ] == self.dofProne[ "nearStart" ] ) return; self.dofDefault[ "nearStart" ] = self.dofProne[ "nearStart" ]; self.dofDefault[ "nearEnd" ] = self.dofProne[ "nearEnd" ]; self.dofDefault[ "nearBlur" ] = self.dofProne[ "nearBlur" ]; self setViewModelDepthOfField( 10, 50 ); self maps\_art::setdefaultdepthoffield(); } // --------------------------------------------------------------------------------- dialog_unsilenced_weapons() { self endon( "death" ); level endon( "nonsilenced_weapon_pickup" ); while ( true ) { self waittill( "weapon_change" ); current_weapon = self getcurrentprimaryweapon(); if ( !isdefined( current_weapon ) ) continue; if ( current_weapon == "none" ) continue; if ( current_weapon == "c4" ) continue; if ( current_weapon == "claymore" ) continue; if ( issubstr( current_weapon, "silence" ) ) continue; //Be careful about picking up enemy weapons, Soap. Any un-suppressed firearms will attract a lot of attention. thread radio_dialogue( "so_hid_ghil_pri_attractattn" ); break; } level notify( "nonsilenced_weapon_pickup" ); } // ---------------------------------------------------------------------------------