IW4-Dump-Files/maps/_stealth_visibility_system.gsc

392 lines
12 KiB
Plaintext

#include common_scripts\utility;
#include maps\_utility;
#include maps\_anim;
#include maps\_stealth_utility;
#include maps\_stealth_shared_utilities;
stealth_visibility_system_main()
{
system_init();
thread system_message_loop();
array_thread( getentarray( "stealth_clipbrush", "targetname" ), ::system_handle_clipbrush );
}
/************************************************************************************************************/
/* SYSTEM LOGIC */
/************************************************************************************************************/
system_message_loop()
{
flag = "_stealth_spotted";
while ( 1 )
{
flag_wait( "_stealth_enabled" );
flag_wait( flag );
if ( !flag( "_stealth_enabled" ) )
continue;
system_event_change( "spotted" );
thread system_state_spotted();
flag_waitopen( flag );
if ( !flag( "_stealth_enabled" ) )
continue;
system_event_change( "hidden" );
//make sure everything gets a notify and does what it needs to do
//before possibly being reset within the same frame back to spotted
waittillframeend;
}
}
//this function basically sets the ai event distance handlers based on the global awareness of ai...
system_event_change( name )
{
level._stealth.logic.detection_level = name;
foreach ( key, event in level._stealth.logic.ai_event )
{
setsaveddvar( key, event[ name ] );
// Set ai_busyEvent* dvars too for now
busyEventDvarName = "ai_busyEvent" + getsubstr( key, 8 ); // strlen( "ai_event" ) = 8
setsaveddvar( busyEventDvarName, event[ name ] );
}
}
//if system specific settings need to be made for this state...they go there
system_state_spotted()
{
while ( flag( "_stealth_spotted" ) )
{
flag_wait( "_stealth_enabled" );
array = level._stealth.group.groups;
foreach ( group_name, group in array )
{
//is this group spotted?
_flag = group_get_flagname_from_group( "_stealth_spotted", group_name );
if ( !flag( _flag ) )
continue;
thread system_state_try_clear_flag( group_name );
}
//the most the last function will take is 1 second to complete...so lets wait a little longer
flag_waitopen_or_timeout( "_stealth_spotted", 1.25 );
}
}
system_state_try_clear_flag( group_name )
{
clear = system_state_check_no_enemy( group_name );
if ( !clear )
return;
//basically if everyone lost their enemy...then we're back to hidden
//there might be guys still looking so give them 1 second and check again
wait 1;
clear = system_state_check_no_enemy( group_name );
if ( !clear )
return;
//so if we got here, then we passed the second test, if that's the case, then clear the flag
group_flag_clear( "_stealth_spotted", group_name );
}
system_state_check_no_enemy( group_name )
{
group = group_get_ai_in_group( group_name );
foreach ( key, ai in group )
{
if ( !isalive( ai.enemy ) )
continue;
return false;
}
return true;
}
/************************************************************************************************************/
/* PLAYER LOGIC */
/************************************************************************************************************/
system_save_processes()
{
flag_init( "_stealth_player_nade" );
level._stealth.logic.player_nades = 0;
array_thread( level.players, ::player_grenade_check );
}
player_grenade_check()
{
while ( 1 )
{
//this one hit's as soon as the button is pressed - that's why we want
//to set the flag here and not after the grenade has left the hand
//with "grenade fire"
self waittill( "grenade_pullback" );
flag_set( "_stealth_player_nade" );
self waittill( "grenade_fire", grenade );
thread player_grenade_check_dieout( grenade );
}
}
player_grenade_check_dieout( grenade )
{
level._stealth.logic.player_nades++ ;
grenade waittill_notify_or_timeout( "death", 10 );
level._stealth.logic.player_nades -- ;
//give stealth a chance to notify of any issues because of the grenade before we clear the flag
//so that the system checking for saving the game can verify those notifies first
waittillframeend;
if ( !level._stealth.logic.player_nades )
flag_clear( "_stealth_player_nade" );
}
system_init_shadows()
{
array_thread( getentarray( "_stealth_shadow", "targetname" ), ::stealth_shadow_volumes );
array_thread( getentarray( "stealth_shadow", "targetname" ), ::stealth_shadow_volumes );
}
stealth_shadow_volumes()
{
self endon( "death" );// it can be deleted
while ( 1 )
{
self waittill( "trigger", other );
if ( !isalive( other ) )
continue;
if ( other ent_flag( "_stealth_in_shadow" ) )
continue;
other thread stealth_shadow_ai_in_volume( self );
}
}
stealth_shadow_ai_in_volume( volume )
{
self endon( "death" );
self ent_flag_set( "_stealth_in_shadow" );
while ( self istouching( volume ) )
wait .05;
self ent_flag_clear( "_stealth_in_shadow" );
}
/************************************************************************************************************/
/* CLIP BRUSH LOGIC */
/************************************************************************************************************/
system_handle_clipbrush()
{
self endon( "death" );
if ( isdefined( self.script_flag_wait ) )
flag_wait( self.script_flag_wait );
waittillframeend;
spotted_flag = "_stealth_spotted";
corpse_flag = "_stealth_found_corpse";
event_flag = "_stealth_event";
if ( isdefined( self.script_stealthgroup ) )
{
group_wait_group_spawned( string( self.script_stealthgroup ) );
spotted_flag = group_get_flagname_from_group( spotted_flag, self.script_stealthgroup );
corpse_flag = group_get_flagname_from_group( corpse_flag, self.script_stealthgroup );
event_flag = group_get_flagname_from_group( event_flag, self.script_stealthgroup );
}
self setcandamage( true );
self add_wait( ::waittill_msg, "damage" );
level add_wait( ::flag_wait, spotted_flag );
level add_wait( ::flag_wait, corpse_flag );
level add_wait( ::flag_wait, event_flag );
do_wait_any();
if ( self.spawnflags & 1 )
self connectpaths();
self delete();
}
/************************************************************************************************************/
/* SETUP */
/************************************************************************************************************/
system_init()
{
flag_init( "_stealth_spotted" );
flag_init( "_stealth_event" );
flag_init( "_stealth_enabled" );
flag_set( "_stealth_enabled" );
/#
thread stealth_flag_debug_print( "_stealth_spotted" );
#/
//under stealth we have a logic struct and a behavior struct...the behavior struct is created and
//handled in the _stealth_behavior system OR in the designers own script
level._stealth = spawnstruct();
level._stealth.logic = spawnstruct();
level._stealth.group = spawnstruct();
level._stealth.group.flags = [];
level._stealth.group.groups = [];
//friendly and player detection initilization
level._stealth.logic.detection_level = "hidden";
level._stealth.logic.detect_range = [];
level._stealth.logic.detect_range[ "hidden" ] = [];
level._stealth.logic.detect_range[ "spotted" ] = [];
system_default_detect_ranges();
//these are event handlers...they're already running in the game normally, but with these numbers we can
//tweak how well they AI can detect these events...for stealth gameplay we bring the numbers for
//footsteps, death of a teammate, etc, etc rediculously lower than normal COD gameplay
level._stealth.logic.ai_event = [];
level._stealth.logic.ai_event[ "ai_eventDistDeath" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistPain" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistExplosion" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistBullet" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistFootstep" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistFootstepWalk" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistFootstepSprint" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistGunShot" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistGunShotTeam" ] = [];
level._stealth.logic.ai_event[ "ai_eventDistNewEnemy" ] = [];
system_default_event_distances();
system_event_change( "hidden" );
system_save_processes();
system_init_shadows();
stealth_alert_level_duration( 0.5 );
}
/************************************************************************************************************/
/* UTILITIES */
/************************************************************************************************************/
system_default_detect_ranges()
{
//these values represent the BASE huristic for max visible distance base meaning
//when the character is completely still and not turning or moving
//HIDDEN is self explanatory
hidden = [];
hidden[ "prone" ] = 70;
hidden[ "crouch" ] = 600;
hidden[ "stand" ] = 1024;
//SPOTTED is when they are completely aware and go into NORMAL COD AI mode...however, the
//distance they can see you is still limited by these numbers because of the assumption that
//you're wearing a ghillie suit in woodsy areas
spotted = [];
spotted[ "prone" ] = 512;
spotted[ "crouch" ] = 5000;
spotted[ "stand" ] = 8000;
system_set_detect_ranges( hidden, spotted );
}
system_set_detect_ranges( hidden, spotted )
{
//these values represent the BASE huristic for max visible distance base meaning
//when the character is completely still and not turning or moving
//HIDDEN is self explanatory
if ( isdefined( hidden ) )
{
level._stealth.logic.detect_range[ "hidden" ][ "prone" ] = hidden[ "prone" ];
level._stealth.logic.detect_range[ "hidden" ][ "crouch" ] = hidden[ "crouch" ];
level._stealth.logic.detect_range[ "hidden" ][ "stand" ] = hidden[ "stand" ];
}
//SPOTTED is when they are completely aware and go into NORMAL COD AI mode...however, the
//distance they can see you is still limited by these numbers because of the assumption that
//you're wearing a ghillie suit in woodsy areas
if ( isdefined( spotted ) )
{
level._stealth.logic.detect_range[ "spotted" ][ "prone" ] = spotted[ "prone" ];
level._stealth.logic.detect_range[ "spotted" ][ "crouch" ] = spotted[ "crouch" ];
level._stealth.logic.detect_range[ "spotted" ][ "stand" ] = spotted[ "stand" ];
}
}
system_default_event_distances()
{
ai_event[ "ai_eventDistDeath" ] = [];
ai_event[ "ai_eventDistPain" ] = [];
ai_event[ "ai_eventDistExplosion" ] = [];
ai_event[ "ai_eventDistBullet" ] = [];
ai_event[ "ai_eventDistFootstep" ] = [];
ai_event[ "ai_eventDistFootstepWalk" ] = [];
ai_event[ "ai_eventDistFootstepSprint" ] = [];
ai_event[ "ai_eventDistGunShot" ] = [];
ai_event[ "ai_eventDistGunShotTeam" ] = [];
ai_event[ "ai_eventDistNewEnemy" ] = [];
ai_event[ "ai_eventDistDeath" ][ "spotted" ] = getdvar( "ai_eventDistDeath" );// 1024
ai_event[ "ai_eventDistDeath" ][ "hidden" ] = 512; // used to be 256
ai_event[ "ai_eventDistPain" ][ "spotted" ] = getdvar( "ai_eventDistPain" );// 512
ai_event[ "ai_eventDistPain" ][ "hidden" ] = 256; // used to be 256
ai_event[ "ai_eventDistExplosion" ][ "spotted" ] = 4000;
ai_event[ "ai_eventDistExplosion" ][ "hidden" ] = 4000;
ai_event[ "ai_eventDistBullet" ][ "spotted" ] = 96;// getdvar( "ai_eventDistBullet" );// 96
ai_event[ "ai_eventDistBullet" ][ "hidden" ] = 64;
ai_event[ "ai_eventDistFootstep" ][ "spotted" ] = 350;// getdvar( "ai_eventDistFootstep" );// 512
ai_event[ "ai_eventDistFootstep" ][ "hidden" ] = 64;
ai_event[ "ai_eventDistFootstepWalk" ][ "spotted" ] = 256;// getdvar( "ai_eventDistFootstepWalk" );// 256
ai_event[ "ai_eventDistFootstepWalk" ][ "hidden" ] = 32;
ai_event[ "ai_eventDistFootstepSprint" ][ "spotted" ] = 400;// getdvar( "ai_eventDistFootstepSprint" );// 400
ai_event[ "ai_eventDistFootstepSprint" ][ "hidden" ] = 400;
ai_event[ "ai_eventDistGunShot" ][ "spotted" ] = 2048;
ai_event[ "ai_eventDistGunShot" ][ "hidden" ] = 2048;
//added these ones when I added stealth groups...
//want to make it harder for 2 groups to hear eachother's gunshots
ai_event[ "ai_eventDistGunShotTeam" ][ "spotted" ] = 750; // 2048
ai_event[ "ai_eventDistGunShotTeam" ][ "hidden" ] = 750;
//want to make it harder for 2 groups to give eachother info
ai_event[ "ai_eventDistNewEnemy" ][ "spotted" ] = 750; // 1024
ai_event[ "ai_eventDistNewEnemy" ][ "hidden" ] = 750;
system_set_event_distances( ai_event );
}
system_set_event_distances( array )
{
foreach ( event, event_array in array )
{
foreach ( state, value in event_array )
{
level._stealth.logic.ai_event[ event ][ state ] = value;
}
}
}