IW4-Dump-Files/maps/cliffhanger_stealth.gsc

1269 lines
31 KiB
Plaintext

#include maps\_utility;
#include maps\_anim;
#include common_scripts\utility;
#include maps\_stealth_utility;
#include maps\_stealth_shared_utilities;
#include maps\cliffhanger_code;
/************************************************************************************************************/
/* INITIALIZATIONS */
/************************************************************************************************************/
//stealth_price_accuracy_control()
//{
// level endon( "price_starts_moving" );
// self.baseaccuracy = 5000000;
//
// flag_wait( "near_camp_entrance" );
//
// self.baseaccuracy = .5;
//
// flag_wait( "at_hanger_entrance" );
//
// self.baseaccuracy = 1;
//}
init_cliffhanger_cold_patrol_anims()
{
// make sure we alternate instead of doing a random selection
if( !IsDefined( level.lastColdPatrolAnimSetAssigned ) )
{
level.lastColdPatrolAnimSetAssigned = "none";
}
if( level.lastColdPatrolAnimSetAssigned != "huddle" )
{
self.patrol_walk_anim = "patrol_cold_huddle";
self.patrol_walk_twitch = "patrol_twitch_weights";
self.patrol_scriptedanim[ "pause" ][ 0 ] = "patrol_cold_huddle_pause";
self.patrol_stop[ "pause" ] = "patrol_cold_huddle_stop";
self.patrol_start[ "pause" ] = "patrol_cold_huddle_start";
self.patrol_stop[ "path_end_idle" ] = "patrol_cold_huddle_stop";
self.patrol_end_idle[ 0 ] = "patrol_cold_huddle_pause";
level.lastColdPatrolAnimSetAssigned = "huddle";
}
else
{
self.patrol_walk_anim = "patrol_cold_crossed";
self.patrol_walk_twitch = "patrol_twitch_weights";
self.patrol_scriptedanim[ "pause" ][ 0 ] = "patrol_cold_crossed_pause";
self.patrol_stop[ "pause" ] = "patrol_cold_crossed_stop";
self.patrol_start[ "pause" ] = "patrol_cold_crossed_start";
self.patrol_stop[ "path_end_idle" ] = "patrol_cold_crossed_stop";
self.patrol_end_idle[ 0 ] = "patrol_cold_crossed_pause";
level.lastColdPatrolAnimSetAssigned = "crossed";
}
}
clear_cliffhanger_cold_patrol_anims()
{
self.patrol_walk_anim = undefined;
self.patrol_walk_twitch = undefined;
self.patrol_scriptedanim = undefined;
self.patrol_stop = undefined;
self.patrol_start = undefined;
self.patrol_stop = undefined;
self.patrol_end_idle = undefined;
self maps\_patrol::set_patrol_run_anim_array();
}
set_cliffhanger_alert_cold_patrol_anims()
{
self.patrol_walk_anim = "patrol_cold_gunup";
self.patrol_walk_twitch = "patrol_gunup_twitch_weights";
}
stealth_cliffhanger_clifftop()
{
self stealth_plugin_basic();
if ( isplayer( self ) )
return;
threat_array[ "warning1" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning2;
switch( self.team )
{
case "axis":
self stealth_plugin_threat();
self stealth_pre_spotted_function_custom( ::clifftop_prespotted_func );
self stealth_threat_behavior_custom( threat_array );
self stealth_enable_seek_player_on_spotted();
self stealth_plugin_corpse();
self stealth_plugin_event_all();
self.baseaccuracy = 1;
self.fovcosine = .76; // for the 2nd group -z
self.fovcosinebusy = .1;
//self thread dialog_price_kill();
self init_cliffhanger_cold_patrol_anims();
break;
case "allies":
//self stealth_plugin_aicolor();
//self stealth_plugin_accuracy();
//self stealth_plugin_smart_stance();
}
}
stealth_cliffhanger()
{
self stealth_plugin_basic();
if( isplayer( self ) )
{
self._stealth_move_detection_cap = 0;
return;
}
switch( self.team )
{
case "axis":
self ent_flag_init( "player_found" );
self ent_flag_init( "not_first_attack" );
self thread maps\_stealth_shared_utilities::enemy_event_debug_print( "player_found" );
self thread maps\_stealth_shared_utilities::enemy_event_debug_print( "not_first_attack" );
self stealth_plugin_threat();//call first
custom_array = [];
if ( level.gameskill < 2 )
{
custom_array[ "warning1" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning1;
custom_array[ "warning2" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning2;
}
else
{
custom_array[ "warning1" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning2;
}
self stealth_threat_behavior_custom( custom_array );
//goal radius etc for attack
//overridding this: enemy_alert_level_attack( enemy )
//modify this to make sure you can see the player
b_array = [];
b_array [ "attack" ] = ::cliffhanger_enemy_attack_behavior;
self stealth_threat_behavior_replace( b_array, undefined );
//time till attack once stealth is broken
//overriding this: enemy_animation_attack( type )
new_array = [];
new_array[ "attack" ] = ::cliffhanger_enemy_animation_attack;
self stealth_threat_behavior_replace( undefined, new_array );
//how long till rest of group is notified
//modify this to wait for ent_flag from attack_behavior
self stealth_pre_spotted_function_custom( ::cliffhanger_prespotted_func_with_flag_wait );
self stealth_enable_seek_player_on_spotted();
self stealth_plugin_corpse();
self stealth_plugin_event_all();
self maps\_stealth_shared_utilities::ai_set_goback_override_function( ::cliffhanger_enemy_goback_startfunc );
self.grenadeAmmo = 0;
self.baseaccuracy = 1;
self.fovcosine = .5; // cos60
self.fovcosinebusy = .1;
self thread dialog_player_kill();
self thread dialog_price_kill();
self thread dialog_theyre_looking_for_you();
self init_cliffhanger_cold_patrol_anims();
break;
case "allies":
//self stealth_plugin_aicolor();
//self stealth_plugin_accuracy();
//self allowedstances( "crouch" );
self.grenadeawareness = 0;//dont chase grenades
self thread stealth_plugin_smart_stance();
self._stealth.behavior.no_prone = true;
self._stealth.behavior.wait_resume_path = 4;
self._stealth_move_detection_cap = 0;
array = [];
array[ "hidden" ] = ::cliffhanger_friendly_state_hidden;
array[ "spotted" ] = ::cliffhanger_friendly_state_spotted;
stealth_basic_states_custom( array );
}
}
cliffhanger_enemy_goback_startfunc()
{
self endon( "death" );
self endon( "pain_death" );
self endon( "_stealth_attack" );
self endon( "restart_attack_behavior" );
self endon( "_stealth_enemy_alert_level_change" );
// report back to base that we didn't find anybody
if ( self can_report_to_base() )
{
level.reportingToBase = true;
level thread reset_reportingToBase( self );
self thread enemy_announce_hmph();
self.customMoveTransition = maps\_patrol::patrol_resume_move_start_func;
}
else
{
self.customMoveTransition = maps\_patrol::turn_180_move_start_func;
}
// set patrol cold walking anims back
self init_cliffhanger_cold_patrol_anims();
self maps\_patrol::set_patrol_run_anim_array();
}
// check to see if an enemy who has given up searching for the player
// can do the "report back to base" anim
can_report_to_base()
{
// don't do it if someone is already doing it
if ( IsDefined( level.reportingToBase ) )
return false;
// don't do it if we're not standing
if ( !IsDefined( self.a.stance ) || self.a.stance != "stand" )
return false;
// don't do it if we don't have enough room in front of us
delta = GetMoveDelta( level.scr_anim[ "generic" ][ "patrol_radio_in_clear" ], 0, 1 );
endPoint = self LocalToWorldCoords( delta );
if ( !self MayMoveToPoint( endPoint ) )
return false;
return true;
}
reset_reportingToBase( ai )
{
time = GetAnimLength( level.scr_anim[ "generic" ][ "patrol_radio_in_clear" ] );
wait time;
//ai waittill_any( "death", "pain_death", "_stealth_enemy_alert_level_change", "_stealth_attack", "restart_attack_behavior" );
level.reportingToBase = undefined;
}
friendly_init_cliffhanger()
{
spawner = level.price_spawner;
spawner.count = 1;
level.price = spawner stalingradSpawn();
spawn_failed( level.price );
assert( isDefined( level.price ) );
//add overrides for bcs and color nodes
level.price.ref_node = Spawn( "script_origin", level.price.origin );
//level.price.fixednode = false;
level.price.animname = "price";
//level.price thread disable_ai_color();
// level.price stealth_plugin_aicolor();
// array = [];
// array[ "hidden" ] = ::do_nothing;
// array[ "spotted" ] = ::do_nothing;
// level.price stealth_color_state_custom( array );
level.price enable_ai_color();
level.price.pathRandomPercent = 0;
level.price thread magic_bullet_shield();
//level.price thread price_bullet_sheild(); //disables bullet shield if player is too far
//level.price thread price_handle_death(); //mission fail if price dies
level.price make_hero();
level.price.allowdeath = false;
level.price thread ShootEnemyWrapper_price();
thread battlechatter_off( "allies" );
//level.price thread stealth_price_accuracy_control();
level.price.baseaccuracy = 5000000;
//all stuff from scoutsniper that might be a good idea
// level.price thread price_death();
// level.price setthreatbiasgroup( "price" );
}
cliffhanger_friendly_state_hidden()
{
self thread set_battlechatter( false );
self.grenadeammo = 0;
self.forceSideArm = undefined;
//used to be ignore all - but that makes him not aim at enemies when exposed - which isn't good...also
//after stealth groups were created we want to differentiate between who should be shot at and who shouldn't
//so we don't all of a sudden alert another stealth group by shooting at them
//self.dontEverShoot = true;
self.ignoreme = true;
//self enable_ai_color();
}
cliffhanger_friendly_state_spotted()
{
if( flag( "price_go_to_climb_ridge" ) )
self.dontEverShoot = true;
//self thread set_battlechatter( true );
self.grenadeammo = 0;
//used to be ignore all - but that makes him not aim at enemies when exposed - which isn't good...also
//after stealth groups were created we want to differentiate between who should be shot at and who shouldn't
//so we don't all of a sudden alert another stealth group by shooting at them
//self.dontEverShoot = false;//self.ignoreall = false;
if( !flag( "said_lets_split_up" ) )
self.ignoreme = false;
//self.disablearrivals = true;
//self.disableexits = true;
self pushplayer( false );
//self disable_cqbwalk();
//self thread maps\_stealth_behavior_friendly::friendly_spotted_getup_from_prone();
//self allowedstances( "prone", "crouch", "stand" );
//self anim_stopanimscripted();
//self disable_ai_color();
//self setgoalpos( self.origin );
}
check_near_enemy()
{
self endon( "death" );
self endon( "stop_check_near_enemy" );
self endon( "restart_attack_behavior" );
distanceSq = max( self.newEnemyReactionDistSq, squared( self.pathEnemyFightDist ) );
waittillframeend;
while ( 1 )
{
if( !isdefined( self.enemy ) )
return;
if( distanceSquared( self.origin, self.enemy.origin ) < distanceSq )
break;
wait 0.1;
}
self notify( "near_enemy" );
}
cliffhanger_enemy_attack_behavior_attacked_again()
{
self endon( "death" );
self endon( "_stealth_attack" );
level endon( "_stealth_spotted" );
wait 2;
self waittill( "_stealth_bad_event_listener" );
self maps\_stealth_shared_utilities::enemy_reaction_state_alert();
self ent_flag_set( "not_first_attack" );
self notify( "enemy_runto_and_lookaround" );
self notify( "restart_attack_behavior" );
self clear_generic_idle_anim();
self thread cliffhanger_enemy_attack_behavior( self.enemy );
}
cliffhanger_enemy_attack_behavior( enemy )
{
self endon( "restart_attack_behavior" );
self set_cliffhanger_alert_cold_patrol_anims();
//que up the yell
if ( !self ent_flag( "not_first_attack" ) )
self thread maps\_stealth_shared_utilities::enemy_announce_spotted( self.origin );
self endon( "death" );
self ent_flag_set( "_stealth_override_goalpos" );
self thread cliffhanger_enemy_attack_behavior_attacked_again();
if ( !self stealth_group_spotted_flag() )
{
self thread cliffhanger_enemy_attack_behavior_looking_for_player();
//give the player a chance to hide
wait_reaction_time();
if ( !self ent_flag( "not_first_attack" ) )
{
self thread check_near_enemy();
waittill_notify_or_timeout( "near_enemy", 3 );
self notify( "stop_check_near_enemy" );
}
self thread flag_when_you_can_see_the_player( "player_found" );
self ent_flag_wait( "player_found" );
}
self.dontevershoot = undefined;
cliffhanger_enemy_attack_behavior_sees_player();
}
wait_reaction_time()
{
//200 = 0, 700 = .5
d = distance( self.origin, ( get_closest_player( self.origin ) ).origin );
t = ( d - 200)/1000;
t = clamp( t, 0, 0.5 );
wait t;
println( "---------reaction time: " + t );
}
/*
low sight dist
self orientmode( "face motion" );
patrol to here
reaction time
wait till "enemy visible" = cansee
regular combat
*/
cliffhanger_enemy_attack_behavior_looking_for_player()
{
self endon( "player_found" );
self endon( "death" );
self endon( "_stealth_attack" );
self endon( "restart_attack_behavior" );
self endon( "_stealth_enemy_alert_level_change" );
level endon( "_stealth_spotted" );
//dont shoot until you can see him
self.dontevershoot = true;
//cqb halfway to enemy
self enable_cqbwalk();
self.disablearrivals = false;
self.disableexits = false;
self.goalradius = 64;
player = get_closest_player( self.origin );
lastknownspot = player.origin;
distance = distance( lastknownspot, self.origin );
self ent_flag_set( "_stealth_override_goalpos" );
if ( self cansee( player ) )
{
self setgoalpos( lastknownspot );
}
else
{
searchRadius = 256;
nodes = getNodesInRadius( lastknownspot, searchRadius, 0, 512, "Path" );
if ( nodes.size )
{
node = nodes[ randomint( nodes.size ) ];
self setgoalpos( node.origin );
}
else
{
self setgoalpos( lastknownspot );
}
}
self.goalradius = distance * .5;
self waittill( "goal" );
//switch to a walk
if ( !flag( "_stealth_spotted" ) && ( !isdefined( self.enemy ) || !self cansee( self.enemy ) ) )
{
self set_cliffhanger_search_walk();
self thread maps\_stealth_shared_utilities::enemy_runto_and_lookaround( undefined, lastknownspot );
}
}
set_cliffhanger_search_walk()
{
self disable_cqbwalk();
self set_generic_run_anim( "patrol_cold_gunup_search", true );
self.disablearrivals = true;
self.disableexits = true;
}
cliffhanger_enemy_attack_behavior_sees_player()
{
self endon( "death" );
self endon( "_stealth_enemy_alert_level_change" );
//there is a .5 second delay in enemy_runto_and_lookaround...
//this notify makes sure that script dies here so that the
//looping anim doesn't start after we stop current behavior below
self notify( "enemy_runto_and_lookaround" );
self maps\_stealth_shared_utilities::enemy_stop_current_behavior();
self.dontevershoot = undefined;
self.aggressivemode = true;//dont linger at cover when you cant see your enemy
prev_pos = undefined;
while( !flag( "script_attack_override" ) )
{
player = get_closest_player( self.origin );
if ( animscripts\utility::isShotgun( self.weapon ) )
radius = 250;
else
radius = max( 500, player.maxVisibleDist );
self.goalradius = radius;
last_known_pos = self lastKnownPos( player );
player_pos = ( player.origin * 0.25 ) + ( last_known_pos * 0.75 );
if ( self set_goal_near_pos( player_pos, prev_pos ) )
prev_pos = player_pos;
wait 5;
}
}
set_goal_near_pos( pos, prev_pos )
{
if ( !isdefined( prev_pos ) || distanceSquared( pos, prev_pos ) > squared( 64 ) )
{
searchRadius = 256;
nodes = getNodesInRadius( pos, searchRadius, 0 );
if ( nodes.size )
{
node = nodes[ randomint( nodes.size ) ];
self setgoalpos( node.origin );
}
else
{
self setgoalpos( pos );
}
return true;
}
return false;
}
flag_when_you_can_see_the_player( flag_name )
{
self endon( "death" );
self endon( "restart_attack_behavior" );
while ( 1 )
{
player = get_closest_player( self.origin );
if ( self cansee( player ) )
{
self ent_flag_set( flag_name );
break;
}
wait .1;
}
}
cliffhanger_enemy_animation_attack( type )
{
// no animation, just attack
self thread maps\_stealth_shared_utilities::enemy_announce_attack();
}
stealth_settings()
{
stealth_set_default_stealth_function( "cliffhanger", ::stealth_cliffhanger );
stealth_set_default_stealth_function( "clifftop", ::stealth_cliffhanger_clifftop );
ai_event = [];
ai_event[ "ai_eventDistNewEnemy" ] = [];
ai_event[ "ai_eventDistNewEnemy" ][ "spotted" ] = 512;
ai_event[ "ai_eventDistNewEnemy" ][ "hidden" ] = 256;
ai_event[ "ai_eventDistExplosion" ] = [];
ai_event[ "ai_eventDistExplosion" ][ "spotted" ] = 1500;
ai_event[ "ai_eventDistExplosion" ][ "hidden" ] = 1500;
ai_event[ "ai_eventDistDeath" ] = [];
ai_event[ "ai_eventDistDeath" ][ "spotted" ] = 512;
ai_event[ "ai_eventDistDeath" ][ "hidden" ] = 512; // used to be 256
ai_event[ "ai_eventDistPain" ] = [];
ai_event[ "ai_eventDistPain" ][ "spotted" ] = 256;
ai_event[ "ai_eventDistPain" ][ "hidden" ] = 256; // used to be 256
ai_event[ "ai_eventDistBullet" ] = [];
ai_event[ "ai_eventDistBullet" ][ "spotted" ] = 96;
ai_event[ "ai_eventDistBullet" ][ "hidden" ] = 96;
stealth_ai_event_dist_custom( ai_event );
array = [];
array[ "player_dist" ] = 1000;
array[ "sight_dist" ] = 400;
array[ "detect_dist" ] = 200;
stealth_corpse_ranges_custom( array );
}
sight_ranges_long()
{
ai_event[ "ai_eventDistFootstep" ] = [];
ai_event[ "ai_eventDistFootstep" ][ "spotted" ] = 300;
ai_event[ "ai_eventDistFootstep" ][ "hidden" ] = 300;
ai_event[ "ai_eventDistFootstepWalk" ] = [];
ai_event[ "ai_eventDistFootstepWalk" ][ "spotted" ] = 300;
ai_event[ "ai_eventDistFootstepWalk" ][ "hidden" ] = 300;
ai_event[ "ai_eventDistFootstepSprint" ] = [];
ai_event[ "ai_eventDistFootstepSprint" ][ "spotted" ] = 400;
ai_event[ "ai_eventDistFootstepSprint" ][ "hidden" ] = 400;
stealth_ai_event_dist_custom( ai_event );
rangesHidden = [];
rangesHidden[ "prone" ] = 800;
rangesHidden[ "crouch" ] = 800;
rangesHidden[ "stand" ] = 800;
rangesSpotted = [];
rangesSpotted[ "prone" ] = 8192;
rangesSpotted[ "crouch" ] = 8192;
rangesSpotted[ "stand" ] = 8192;
stealth_detect_ranges_set( rangesHidden, rangesSpotted );
stealth_alert_level_duration( 0.5 );
}
sight_ranges_blizzard()
{
ai_event[ "ai_eventDistFootstep" ] = [];
ai_event[ "ai_eventDistFootstep" ][ "spotted" ] = 120;
ai_event[ "ai_eventDistFootstep" ][ "hidden" ] = 120;
ai_event[ "ai_eventDistFootstepWalk" ] = [];
ai_event[ "ai_eventDistFootstepWalk" ][ "spotted" ] = 60;
ai_event[ "ai_eventDistFootstepWalk" ][ "hidden" ] = 60;
ai_event[ "ai_eventDistFootstepSprint" ] = [];
ai_event[ "ai_eventDistFootstepSprint" ][ "spotted" ] = 400;
ai_event[ "ai_eventDistFootstepSprint" ][ "hidden" ] = 400;
stealth_ai_event_dist_custom( ai_event );
rangesHidden = [];
rangesHidden[ "prone" ] = 250;
rangesHidden[ "crouch" ] = 450;
rangesHidden[ "stand" ] = 500;
rangesSpotted = [];
rangesSpotted[ "prone" ] = 500;
rangesSpotted[ "crouch" ] = 500;
rangesSpotted[ "stand" ] = 600;
stealth_detect_ranges_set( rangesHidden, rangesSpotted );
alert_duration = [];
alert_duration[0] = 1;
alert_duration[1] = 1;
alert_duration[2] = 1;
alert_duration[3] = 0.75;
// easy and normal have 2 alert levels so the above times are effectively doubled
stealth_alert_level_duration( alert_duration[ level.gameskill ] );
}
clifftop_prespotted_func()
{
//thread debug_timer();
self.battlechatter = false;
wait 5;
self.battlechatter = true;
}
debug_timer()
{
time_past = 0;
while( time_past < 10 )
{
wait .05;
time_past = time_past + .05;
println( "time past: " + time_past );
}
}
cliffhanger_prespotted_func_with_flag_wait()
{
self.battlechatter = false;
if( level.gameskill < 3 )
self ent_flag_wait( "player_found" );
if( level.gameskill < 2 )
wait 3;
else
wait .25;
self.battlechatter = true;
}
////////////////////////////////////////////////////
price_stealth_kills_guy( targetguy2 )
{
level.price.fixednode = false;
level.price disable_ai_color();
level.price setgoalpos( level.price.origin );
level.price.goalradius = 8;
self.dontattackme = undefined;
level.price.favoriteenemy = self;
self.health = 1;
self waittill( "death" );
//alert second guy and tell price to kill him
if( isalive( targetguy2 ) )
{
targetguy2.favoriteenemy = level.player;
wait .2;
level.price.favoriteenemy = self;
targetguy2.dontattackme = undefined;
targetguy2 waittill( "death" );
}
wait .8;
wait 2;
level.price.fixednode = true;
level.price enable_ai_color();
//level.price Shoot();
//aim_spot = self geteye();
//MagicBullet( level.price.weapon, level.price gettagorigin( "tag_flash" ), aim_spot );
}
wait_for_player_interupt( msg )
{
if( flag( msg ) )
return;
level endon ( "_stealth_spotted" );
level endon ( msg );
level.player waittill( "weapon_fired" );
}
///////////////////////////////////////////////////////////////////////////////////
start_truck_patrol()
{
array_thread( getentarray( "truck_guys", "script_noteworthy" ), ::add_spawn_function, ::base_truck_guys_think );
flag_wait( "start_truck_patrol" );
autosave_stealth();
truck_spawner = getent( "truck_patrol", "targetname" );
truck_spawner.script_badplace = true;
level.truck_patrol = maps\_vehicle::spawn_vehicle_from_targetname_and_drive( "truck_patrol" );
level.truck_patrol thread dialog_truck_coming();
level.truck_patrol thread play_loop_sound_on_entity( "cliffhanger_truck_music" );
level.truck_patrol thread base_truck_think();
level.truck_patrol thread truck_headlights();
thread dialog_jeep_blown_up();
level.truck_patrol thread dialog_jeep_stopped();
level.truck_patrol waittill( "death" );
flag_set( "jeep_blown_up" );
level.truck_patrol notify( "stop sound" + "cliffhanger_truck_music" );
}
truck_headlights()
{
//level.truck_patrol maps\_vehicle::lights_on( "headlights" );
PlayFXOnTag( level._effect[ "lighthaze_snow_headlights" ], self, "TAG_LIGHT_RIGHT_FRONT" );
PlayFXOnTag( level._effect[ "lighthaze_snow_headlights" ], self, "TAG_LIGHT_LEFT_FRONT" );
//level.truck_patrol maps\_vehicle::lights_on( "brakelights" );
//taillights
PlayFXOnTag( level._effect[ "car_taillight_uaz_l" ], self, "TAG_LIGHT_LEFT_TAIL" );
PlayFXOnTag( level._effect[ "car_taillight_uaz_l" ], self, "TAG_LIGHT_RIGHT_TAIL" );
self waittill ( "death" );
if( isdefined( self ) )
delete_truck_headlights();
}
delete_truck_headlights()
{
StopFXOnTag( level._effect[ "lighthaze_snow_headlights" ], self, "TAG_LIGHT_RIGHT_FRONT" );
StopFXOnTag( level._effect[ "lighthaze_snow_headlights" ], self, "TAG_LIGHT_LEFT_FRONT" );
StopFXOnTag( level._effect[ "car_taillight_uaz_l" ], self, "TAG_LIGHT_LEFT_TAIL" );
StopFXOnTag( level._effect[ "car_taillight_uaz_l" ], self, "TAG_LIGHT_RIGHT_TAIL" );
}
base_truck_think()
{
self endon( "death" );
//level.truck_patrol thread handle_end_of_path();
//array_thread( level.players, ::base_truck_see, self );
level.truck_patrol thread unload_and_attack_if_stealth_broken_and_close();
//level.truck_patrol thread break_stealth_if_player_spotted();
//level.truck_patrol thread break_stealth_if_damage_taken();//handled by wizz bys
flag_wait( "truck_guys_alerted" );
//self.runtovehicleoverride = ::truck_guy_runtovehicle;
//guys = self.attachedguys;
guys = get_living_ai_array( "truck_guys", "script_noteworthy" );
if( guys.size == 0 )
{
self Vehicle_SetSpeed( 0, 15 );
return;
}
screamer = random( guys );
screamer maps\_stealth_shared_utilities::enemy_announce_wtf();
//wait .5;
self waittill( "safe_to_unload" );
self Vehicle_SetSpeed( 0, 15 );
wait 1;
self maps\_vehicle::vehicle_unload();
flag_set( "jeep_stopped" );
//self waittill( "unloaded" );
}
/*
handle_end_of_path()
{
while( 1 )
{
self waittillmatch( "noteworthy", "end_of_path" );
path = getent( self.target, "targetname" );
self maps\_vehicle::vehicle_paths( path );
}
}
*/
//break_stealth_if_damage_taken()
//{
// self waittill( "damage" );
//
// flag_set( "truck_guys_alerted" );
//}
unload_and_attack_if_stealth_broken_and_close()
{
self endon( "truck_guys_alerted" );
while( 1 )
{
flag_wait( "_stealth_spotted" );
level.player waittill_entity_in_range( self, 800 );
if( !flag( "_stealth_spotted" ) )
continue;
else
break;
}
flag_set( "truck_guys_alerted" );
}
//base_truck_see( truck )
//{
// truck endon( "death" );
// self endon( "death" );
//
// while ( 1 )
// {
// dist = self.maxVisibleDist * .75;
// dist = dist * dist;
//
// if ( distancesquared( self.origin, truck.origin ) <= dist )
// break;
//
// wait .1;
// }
//
// flag_set( "truck_guys_alerted" );
//}
base_truck_guys_attacked_again()
{
self endon( "death" );
self endon( "_stealth_attack" );
level endon( "_stealth_spotted" );
wait 2;
self waittill( "_stealth_bad_event_listener" );
self maps\_stealth_shared_utilities::enemy_reaction_state_alert();
self ent_flag_set( "not_first_attack" );
}
base_truck_guys_think()
{
self endon( "death" );
//if ( flag( "_stealth_spotted" ) || self ent_flag( "_stealth_attack" ) )
// return;
level endon( "_stealth_spotted" );
self endon( "_stealth_attack" );
self ent_flag_init( "jumped_out" );
self thread truck_guys_think_jumpout();
corpse_array = [];
corpse_array[ "saw" ] = ::truck_guys_reaction_behavior;
corpse_array[ "found" ] = ::truck_guys_reaction_behavior;
alert_array = [];
alert_array[ "warning1" ] = ::truck_guys_reaction_behavior;
alert_array[ "warning2" ] = ::truck_guys_reaction_behavior;
alert_array[ "attack" ] = ::truck_alert_level_attack;
awareness_array = [];
awareness_array[ "explode" ] = ::truck_guys_no_enemy_reaction_behavior;
awareness_array[ "heard_scream" ] = ::truck_guys_no_enemy_reaction_behavior;
awareness_array[ "doFlashBanged" ] = ::truck_guys_no_enemy_reaction_behavior;
self maps\_stealth_shared_utilities::ai_create_behavior_function( "animation", "wrapper", ::truck_animation_wrapper );
self stealth_threat_behavior_custom( alert_array );
self stealth_corpse_behavior_custom( corpse_array );
foreach ( key, value in awareness_array )
self maps\_stealth_event_enemy::stealth_event_mod( key, value );
self ent_flag_set( "_stealth_behavior_reaction_anim" );
}
truck_guys_base_search_behavior( node )
{
self endon( "_stealth_enemy_alert_level_change" );
level endon( "_stealth_spotted" );
self endon( "_stealth_attack" );
self endon( "death" );
self endon( "pain_death" );
self thread base_truck_guys_attacked_again();
self.disablearrivals = false;
self.disableexits = false;
distance = distance( node.origin, self.origin );
self setgoalnode( node );
self.goalradius = distance * .5;
wait 0.05; // because stealth system keeps clearing run anim on every enemy_animation_wrapper
self set_generic_run_anim( "_stealth_patrol_cqb" );
self waittill( "goal" );
if ( !flag( "_stealth_spotted" ) && ( !isdefined( self.enemy ) || !self cansee( self.enemy ) ) )
{
set_cliffhanger_search_walk();
self maps\_stealth_shared_utilities::enemy_runto_and_lookaround( node );
}
}
truck_guys_think_jumpout()
{
self endon( "death" );
self endon( "pain_death" );
while ( 1 )
{
self waittill( "jumpedout" );
self enemy_set_original_goal( self.origin );
self.got_off_truck_origin = self.origin;
self ent_flag_set( "jumped_out" );
self waittill( "enteredvehicle" );
wait .15;
self ent_flag_clear( "jumped_out" );
self ent_flag_set( "_stealth_behavior_reaction_anim" );
}
}
truck_animation_wrapper( type )
{
self endon( "death" );
self endon( "pain_death" );
flag_set( "truck_guys_alerted" );
self ent_flag_wait( "jumped_out" );
self maps\_stealth_shared_utilities::enemy_animation_wrapper( type );
}
truck_guys_reaction_behavior( type )
{
self endon( "death" );
self endon( "pain_death" );
level endon( "_stealth_spotted" );
self endon( "_stealth_attack" );
flag_set( "truck_guys_alerted" );
self ent_flag_wait( "jumped_out" );
if ( !flag( "truck_guys_alerted" ) )
return;
if ( flag_exist( "truck_guys_not_going_back" ) && flag( "truck_guys_not_going_back" ) )
return;
if ( !flag( "_stealth_spotted" ) && !self ent_flag( "_stealth_attack" ) )
{
player = get_closest_player( self.origin );
node = maps\_stealth_shared_utilities::enemy_find_free_pathnode_near( player.origin, 1500, 128 );
if ( isdefined( node ) )
self thread truck_guys_base_search_behavior( node );
}
spotted_flag = self group_get_flagname( "_stealth_spotted" );
if ( flag( spotted_flag ) )
self flag_waitopen( spotted_flag );
else
self waittill( "normal" );
}
truck_guys_no_enemy_reaction_behavior( type )
{
self endon( "death" );
self endon( "pain_death" );
level endon( "_stealth_spotted" );
self endon( "_stealth_attack" );
flag_set( "truck_guys_alerted" );
self ent_flag_wait( "jumped_out" );
if ( !flag( "truck_guys_alerted" ) )
return;
if ( flag_exist( "truck_guys_not_going_back" ) && flag( "truck_guys_not_going_back" ) )
return;
if ( !flag( "_stealth_spotted" ) && !self ent_flag( "_stealth_attack" ) )
{
origin = self._stealth.logic.event.awareness_param[ type ];
node = self maps\_stealth_shared_utilities::enemy_find_free_pathnode_near( origin, 300, 40 );
self thread maps\_stealth_shared_utilities::enemy_announce_wtf();
if ( isdefined( node ) )
self thread truck_guys_base_search_behavior( node );
}
spotted_flag = self group_get_flagname( "_stealth_spotted" );
if ( flag( spotted_flag ) )
self flag_waitopen( spotted_flag );
else
self waittill( "normal" );
}
truck_alert_level_attack( enemy )
{
self endon( "death" );
self endon( "pain_death" );
flag_set( "truck_guys_alerted" );
self ent_flag_wait( "jumped_out" );
self cliffhanger_enemy_attack_behavior();
}
////////////////////////////////////////////////////
spawn_beehive()
{
level endon ( "done_with_stealth_camp" );
spawner_triggers = getentarray( "beehive_spawner", "targetname" );
array_thread( getentarray( "beehive_spawner", "script_noteworthy" ), ::add_spawn_function, ::beehive_enemies );
while( 1 )
{
println( " beehive ready" );
flag_wait( "_stealth_spotted" );
wait 1;
num = alert_enemies_count();
hives = 0;
if ( num <= 3 )
hives = 2;
if ( num > 3 )
hives = 1;
if ( num > 5 )
hives = 0;
if(! is_group77_alert() )
hives = 0;
println( " beehives : " + hives );
//sort from closest to furtherest
spawner_triggers = get_array_of_closest( getAveragePlayerOrigin(), spawner_triggers );
//skip the closest 2
for( i = 2 ; i < (2 + hives); i++ )
{
spawner_triggers[i] notify ( "trigger" );
}
flag_waitopen( "_stealth_spotted" );
}
}
is_group77_alert()
{
alerted_groups = stealth_group_return_groups_with_spotted_flag();
foreach( group in alerted_groups )
{
if( group == "77" )
return true;
}
return false;
}
alert_enemies_count()
{
enemies = getaiarray( "axis" );
count = 0;
foreach( guy in enemies )
{
if( guy ent_flag_exist( "_stealth_normal" ) )
if( !guy ent_flag( "_stealth_normal" ) )
count++;
}
return count;
}
beehive_enemies()
{
self endon( "death" );
self.baseaccuracy = 1;
self.aggressivemode = true;
g_radius = 700;
if( self.weapon == "m1014" )
g_radius = 250;
while( 1 )
{
if ( isdefined( self.enemy ) )
{
self.goalradius = g_radius;
player = get_closest_player( self.origin );
self setgoalpos( player.origin );
}
wait 4;
}
}
////////////////////////////////////////////////////
MIN_NON_ALERT_TEAMMATE_DIST_SQ = 300 * 300;
MIN_ALERT_TEAMMATE_DIST_SQ = 1000 * 1000;
// price should snipe if AI is not alert or there are no teammates nearby it.
price_should_snipe_me()
{
teammates = getAIArray( self.team );
foreach( ai in teammates )
{
if ( self == ai )
continue;
if ( ai.alertLevel == "alert" )
checkDistSq = MIN_ALERT_TEAMMATE_DIST_SQ;
else
checkDistSq = MIN_NON_ALERT_TEAMMATE_DIST_SQ;
if ( distanceSquared( self.origin, ai.origin ) < checkDistSq )
return false;
}
return true;
}