IW4-Dump-Files/maps/_specialops_battlechatter.gsc

631 lines
13 KiB
Plaintext

#include common_scripts\utility;
#include maps\_utility;
#include maps\_hud_util;
init()
{
anim.so = spawnstruct(); // holds all of our SO-specific bc stuff
anim.so.eventTypes = [];
anim.so.eventTypes[ "check_fire" ] = "threat_friendly_fire";
anim.so.eventTypes[ "reload" ] = "inform_reload_generic";
anim.so.eventTypes[ "frag_out" ] = "inform_attack_grenade";
anim.so.eventTypes[ "flash_out" ] = "inform_attack_flashbang";
anim.so.eventTypes[ "smoke_out" ] = "inform_attack_smoke";
anim.so.eventTypes[ "c4_plant" ] = "inform_attack_c4";
anim.so.eventTypes[ "claymore_plant" ] = "inform_plant_claymore";
anim.so.eventTypes[ "downed" ] = "inform_suppressed";
anim.so.eventTypes[ "bleedout" ] = "inform_bleedout";
anim.so.eventTypes[ "reviving" ] = "inform_reviving";
anim.so.eventTypes[ "revived" ] = "inform_revived";
anim.so.eventTypes[ "sentry_out" ] = "inform_place_sentry";
anim.so.eventTypes[ "area_secure" ] = "inform_area_secure";
// Supported, but not currently used anywhere.
anim.so.eventTypes[ "kill_generic" ] = "inform_kill_generic";
anim.so.eventTypes[ "kill_infantry" ] = "inform_kill_infantry";
anim.so.eventTypes[ "affirmative" ] = "inform_roger";
anim.so.eventTypes[ "negative" ] = "inform_negative";
anim.so.eventTypes[ "on_comms" ] = "inform_comms";
anim.so.eventTypes[ "mark_dropzone" ] = "inform_markdz";
anim.so.eventTypes[ "glowstick_out" ] = "inform_use_glowstick";
anim.so.eventTypeMinWait = [];
anim.so.eventTypeMinWait[ "check_fire" ] = 4;
anim.so.eventTypeMinWait[ "reload" ] = 8;
anim.so.eventTypeMinWait[ "frag_out" ] = 3;
anim.so.eventTypeMinWait[ "flash_out" ] = 3;
anim.so.eventTypeMinWait[ "smoke_out" ] = 3;
anim.so.eventTypeMinWait[ "c4_plant" ] = 2;
anim.so.eventTypeMinWait[ "claymore_plant" ] = 2;
anim.so.eventTypeMinWait[ "downed" ] = 0.5;
anim.so.eventTypeMinWait[ "bleedout" ] = 0.5;
anim.so.eventTypeMinWait[ "reviving" ] = 2;
anim.so.eventTypeMinWait[ "revived" ] = 2;
anim.so.eventTypeMinWait[ "sentry_out" ] = 3;
anim.so.eventTypeMinWait[ "kill_generic" ] = 2;
anim.so.eventTypeMinWait[ "kill_infantry" ] = 2;
anim.so.eventTypeMinWait[ "area_secure" ] = 0.5;
anim.so.eventTypeMinWait[ "affirmative" ] = 2;
anim.so.eventTypeMinWait[ "negative" ] = 2;
anim.so.eventTypeMinWait[ "on_comms" ] = 0.5;
anim.so.eventTypeMinWait[ "mark_dropzone" ] = 0.5;
anim.so.eventTypeMinWait[ "glowstick_out" ] = 3;
anim.so.skipDistanceCheck = [];
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "affirmative";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "negative";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "area_secure";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "on_comms";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "mark_dropzone";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "downed";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "bleedout";
anim.so.skipDistanceCheck[ anim.so.skipDistanceCheck.size ] = "check_fire";
anim.so.noReloadCalloutWeapons = [];
anim.so.noReloadCalloutWeapons[ anim.so.noReloadCalloutWeapons.size ] = "m79";
anim.so.noReloadCalloutWeapons[ anim.so.noReloadCalloutWeapons.size ] = "ranger";
anim.so.noReloadCalloutWeapons[ anim.so.noReloadCalloutWeapons.size ] = "claymore";
anim.so.noReloadCalloutWeapons[ anim.so.noReloadCalloutWeapons.size ] = "rpg";
anim.so.noReloadCalloutWeapons[ anim.so.noReloadCalloutWeapons.size ] = "rpg_player";
anim.so.bcMaxDistSqd = 800 * 800; // units
anim.so.bcPrintFailPrefix = "^3***** BCS FAILURE: ";
array_thread( level.players, ::enable_chatter_on_player );
enable_chatter();
}
enable_chatter()
{
level.so_player_chatter_enabled = true;
}
disable_chatter()
{
level.so_player_chatter_enabled = false;
}
enable_chatter_on_player()
{
self.so_isSpeaking = false;
self.bc_eventTypeLastUsedTime = [];
self thread revive_tracking();
self thread claymore_tracking();
self thread reload_tracking();
self thread grenade_tracking();
self thread friendlyfire_tracking();
self thread friendlyfire_whizby_tracking();
self thread sentry_tracking();
self thread kill_generic_tracking();
self thread kill_infantry_tracking();
self thread area_secure_tracking();
self thread affirmative_tracking();
self thread negative_tracking();
self thread on_comms_tracking();
self thread mark_dropzone_tracking();
self thread glowstick_tracking();
}
revive_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while( 1 )
{
note = self waittill_any_return( "so_downed", "so_bleedingout", "so_reviving", "so_revived" );
if( note == "so_downed" )
{
self play_so_chatter( "downed" );
}
else if( note == "so_bleedingout" )
{
self play_so_chatter( "bleedout" );
}
else if( note == "so_reviving" )
{
self play_so_chatter( "reviving" );
}
else if( note == "so_revived" )
{
self play_so_chatter( "revived" );
}
}
}
claymore_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "begin_firing" );
weaponName = self GetCurrentWeapon();
if ( weaponName == "claymore" )
{
self play_so_chatter( "claymore_plant" );
}
}
}
sentry_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "sentry_placement_finished" );
self play_so_chatter( "sentry_out" );
}
}
kill_generic_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_kill_generic" );
self play_so_chatter( "kill_generic" );
}
}
kill_infantry_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_kill_infantry" );
self play_so_chatter( "kill_infantry" );
}
}
area_secure_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_area_secure" );
self play_so_chatter( "area_secure" );
}
}
affirmative_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_affirmative" );
self play_so_chatter( "area_secure" );
}
}
negative_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_negative" );
self play_so_chatter( "negative" );
}
}
on_comms_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_on_comms" );
self play_so_chatter( "on_comms" );
}
}
mark_dropzone_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while ( 1 )
{
self waittill( "so_bcs_mark_dropzone" );
self play_so_chatter( "mark_dropzone" );
}
}
glowstick_tracking()
{
// Currently glowsticks aren't used or supported.
}
reload_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
for ( ;; )
{
self waittill( "reload_start" );
weaponName = self GetCurrentWeapon();
if( weapon_no_reload_callout( weaponName ) )
{
continue;
}
// sounds dumb for a player to chatter about reloading when he's downed
if( self is_downed() )
{
continue;
}
self play_so_chatter( "reload" );
}
}
weapon_no_reload_callout( weaponName )
{
foreach( weap in anim.so.noReloadCalloutWeapons )
{
if( weaponName == weap )
{
return true;
}
}
return false;
}
grenade_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while( 1 )
{
self waittill( "grenade_fire", grenade, weaponName );
eventType = undefined;
if ( weaponName == "fraggrenade" )
{
eventType = "frag_out";
}
else if ( weaponName == "semtex_grenade" )
{
eventType = "frag_out";
}
else if ( weaponName == "flash_grenade" )
{
eventType = "flash_out";
}
else if ( weaponName == "smoke_grenade_american" )
{
eventType = "smoke_out";
}
else if ( weaponName == "c4" )
{
eventType = "c4_plant";
}
if( IsDefined( eventType ) )
{
self play_so_chatter( eventType );
}
}
}
friendlyfire_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
while( 1 )
{
self waittill( "damage", damage, attacker, direction_vec, point, type );
if ( !friendlyfire_is_valid( damage, attacker, type ) )
{
continue;
}
self play_so_chatter( "check_fire" );
}
}
friendlyfire_is_valid( damage, attacker, type )
{
if ( damage <= 0 )
{
return false;
}
if ( !isplayer( attacker ) )
{
return false;
}
if ( attacker == self )
{
return false;
}
if( type == "MOD_MELEE" )
{
return false;
}
if( isdefined( level.friendlyfire_warnings ) && !level.friendlyfire_warnings )
{
return false;
}
return true;
}
friendlyfire_whizby_tracking()
{
level endon( "special_op_terminated" );
self endon( "death" );
self AddAiEventListener( "bulletwhizby" );
while( 1 )
{
self waittill( "ai_event", event, shooter, whizByOrigin );
if( event == "bulletwhizby" )
{
if( !friendlyfire_whizby_is_valid( shooter, whizByOrigin ) )
{
continue;
}
self play_so_chatter( "check_fire" );
}
}
}
friendlyfire_whizby_is_valid( shooter, whizByOrigin )
{
if( !IsPlayer( shooter ) )
{
return false;
}
if( shooter == self )
{
return false;
}
// downed guys don't notice friendlyfire whizbys
if( self is_downed() )
{
return false;
}
// hack - the whizby notify for a player gives us an origin, not a distance like it does when an AI calls it
if( abs( whizByOrigin[ 2 ] - self.origin[ 2 ] > 128 ) )
{
// throw away whizbys that are way too high or low
return false;
}
whizByDist = Distance2D( self.origin, whizByOrigin );
// make distance checks consistent with SP
if( !animscripts\battlechatter_ai::friendlyfire_whizby_distances_valid( shooter, whizbyDist ) )
{
return false;
}
if( isdefined( level.friendlyfire_warnings ) && !level.friendlyfire_warnings )
{
return false;
}
return true;
}
play_revive_nag()
{
type = self get_nag_event_type();
ASSERT( IsDefined( type ) );
self play_so_chatter( type );
}
// depending on where we are in the bleedout sequence, we play lines with different intensity
get_nag_event_type()
{
type = "downed";
currentTime = self.coop.bleedout_time;
totalTime = self.coop.bleedout_time_default;
if ( currentTime < ( totalTime * level.coop_bleedout_stage2_multiplier ) )
{
type = "bleedout";
}
return type;
}
can_say_current_nag_event_type()
{
type = self get_nag_event_type();
return self can_say_event_type( type );
}
play_so_chatter( eventType )
{
level endon( "special_op_terminated" );
self endon( "death" );
if( !self can_say_event_type( eventType ) )
{
return;
}
if ( !self close_enough_to_other_player( eventType ) )
{
return;
}
soundalias = get_player_team_prefix( self ) + anim.so.eventTypes[ eventType ];
soundalias = check_overrides( eventType, soundalias );
if( !IsDefined( soundalias ) )
{
return;
}
if( !SoundExists( soundalias ) )
{
PrintLn( anim.so.bcPrintFailPrefix + "soundalias " + soundalias + " doesn't exist." );
return;
}
self.so_isSpeaking = true;
self PlaySound( soundalias, "bc_done", true );
self waittill( "bc_done" );
self.so_isSpeaking = false;
self update_event_type( eventType );
}
can_say_event_type( eventType )
{
if ( !isdefined( level.so_player_chatter_enabled ) || !level.so_player_chatter_enabled )
{
return false;
}
if( self.so_isSpeaking )
{
return false;
}
if( !IsDefined( self.bc_eventTypeLastUsedTime[ eventType ] ) )
{
return true;
}
lastUsedTime = self.bc_eventTypeLastUsedTime[ eventType ];
minWaitTime = anim.so.eventTypeMinWait[ eventType ] * 1000;
if( ( GetTime() - lastUsedTime ) >= minWaitTime )
{
return true;
}
return false;
}
update_event_type( eventType )
{
self.bc_eventTypeLastUsedTime[ eventType ] = GetTime();
}
check_overrides( soundtype, defaultAlias )
{
if( soundtype == "reload" )
{
if ( isdefined( level.so_override[ "skip_inform_reloading" ] ) && level.so_override[ "skip_inform_reloading" ] )
{
return undefined;
}
if ( isdefined( level.so_override[ "inform_reloading" ] ) )
{
return level.so_override[ "inform_reloading" ];
}
}
return defaultAlias;
}
get_player_team_prefix( player )
{
assertex( isdefined( level.so_campaign ), "level.so_campaign must be set in order to play co-op team chatter." );
stealth = "";
if ( isdefined( level.so_stealth ) && level.so_stealth )
stealth = "STEALTH_";
player_num = "1";
if ( player == level.player2 )
player_num = "2";
switch( level.so_campaign )
{
case "ranger":
return "SO_US_" + player_num + "_" + stealth;
case "seal":
return "SO_NS_" + player_num + "_" + stealth;
case "arctic":
case "desert":
case "woodland":
case "ghillie":
return "SO_UK_" + player_num + "_" + stealth;
default:
ASSERTMSG( "level.so_campaign was set to an invalid value, '" + level.so_campaign + "'." );
}
}
close_enough_to_other_player( eventType )
{
if ( isdefined( eventType ) )
{
foreach( event in anim.so.skipDistanceCheck )
{
if ( event == eventType )
return true;
}
}
other_player = get_other_player( self );
if ( DistanceSquared( other_player.origin, self.origin ) > anim.so.bcMaxDistSqd )
{
return false;
}
return true;
}
is_downed()
{
if( self ent_flag_exist( "coop_downed" ) && self ent_flag( "coop_downed" ) )
{
return true;
}
return false;
}