1441 lines
36 KiB
Plaintext
1441 lines
36 KiB
Plaintext
#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" );
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------- |