IW4-Dump-Files/maps/_specialops_code.gsc

1836 lines
48 KiB
Plaintext
Raw Blame History

#include maps\_utility;
#include common_scripts\utility;
#include maps\_hud_util;
/*QUAKED info_player_start_so (0.0 0.3 1.0) (-16 -16 0) (16 16 72)
Player 1 spawns at these locations in Special Ops games. If there is a player 2 but player2 specific start points, player 2 will be positioned near player 1.*/
/*QUAKED info_player_start_soPlayer2 (0.2 0.5 1.0) (-16 -16 0) (16 16 72)
Player 2 spawns at these locations in Special Ops games. Will use the closest spawn point to player 1.*/
pick_starting_location_so( return_placement )
{
if ( isdefined( return_placement ) && return_placement )
{
if ( isdefined( level.skip_PlayerSetStreamOrigin ) && level.skip_PlayerSetStreamOrigin )
return undefined;
}
if ( isdefined( level.pmc_match ) && level.pmc_match )
{
return pick_starting_location_pmc( return_placement );
}
p1_starts = getentarray( "info_player_start_so", "classname" );
if ( p1_starts.size <= 0 )
p1_starts = getentarray( "info_player_start", "classname" );
assertex( p1_starts.size > 0, "Special Ops requires at least 1 player starting position. Place either an info_player_start_so or info_player_start in the level." );
p1_start_point = random( p1_starts );
// return_placement tells it to not actually place the people, and instead send back where it *would* have placed them.
// If the map can potentially spawn them in random locations or far apart, this logic breaks down.
// Used by PlayerSetStreamOrigin for map restarts. Use level.skip_PlayerSetStreamOrigin to avoid it.
if ( isdefined( return_placement ) && return_placement )
{
assert( p1_starts.size == 1 );
return p1_start_point.origin;
}
place_player_at_start_point( level.player, p1_start_point );
if ( is_coop() )
{
p2_starts = getentarray( "info_player_start_soPlayer2", "classname" );
if ( p2_starts.size > 0 )
{
p2_start_point = getClosest( p1_start_point.origin, p2_starts );
place_player_at_start_point( level.player2, p2_start_point );
}
else
{
place_player2_near_player1();
}
}
}
isDefendMatch()
{
return( level.pmc_gametype == "mode_defend" );
}
// Having to include this is sucky, but I don't know a better way.
pick_starting_location_pmc( return_placement )
{
if ( isDefendMatch() )
{
startingLocations = getentarray( "info_player_start_pmcDefend", "classname" );
assertEx( startingLocations.size > 0, "You don't have any player starting positions in the level for defend mode. Place info_player_start_pmcDefend entities in the level." );
assertEx( startingLocations.size >= level.players.size, "You don't have enough info_player_start_pmcDefend entities in the level to support " + level.players.size + " players." );
}
else
{
// Get all of the spawn locations in the map
startingLocations = getentarray( "info_player_start_pmc", "classname" );
assertEx( startingLocations.size > 0, "You don't have any player starting positions in the level. Place info_player_start_pmc entities in the level." );
assertEx( startingLocations.size >= level.players.size, "You don't have enough info_player_start_pmc entities in the level to support " + level.players.size + " players." );
}
// Pick one at random then put the player at it and put other players at the next nearest ones
excluders = [];
spawnEnt = undefined;
foreach ( player in level.players )
{
if ( !excluders.size )
spawnEnt = random( startingLocations );
else
spawnEnt = get_closest_exclude( spawnEnt.origin, startingLocations, excluders );
assert( isdefined( spawnEnt ) );
// See notes in pick_starting_location_so()
if ( isdefined( return_placement ) && return_placement )
{
assert( startingLocations.size <= 2 );
return spawnEnt.origin;
}
player setOrigin( spawnEnt.origin );
player setPlayerAngles( spawnEnt.angles );
excluders[ excluders.size ] = spawnEnt;
}
}
place_player_at_start_point( player, start_point )
{
assertex( isdefined( player ), "place_player_at_start_point() requires a valid player." );
assertex( isdefined( start_point ), "place_player_at_start_point() requires a valid start_point." );
player SetOrigin( start_point.origin );
if ( isdefined( start_point.angles ) )
player setPlayerAngles( start_point.angles );
}
place_player2_near_player1()
{
level.player2 setPlayerAngles( level.player.angles + ( 0, -25, 0 ) );
level.player2 SetOrigin( level.player.origin );
// Offset player 2 a bit from player 1 (adjusted by angle players are facing).
ent = spawnstruct();
ent.entity = level.player2;
ent.right = -20.0;
ent.forward = -50.0;
ent translate_local();
level.player2 SetOrigin( level.player2.origin );
}
specialops_remove_entity_check( special_op_state )
{
if ( specialops_remove_flag_check( special_op_state ) )
return true;
if ( specialops_remove_name_check( special_op_state ) )
return true;
return false;
}
specialops_remove_flag_check( special_op_state )
{
if ( !isdefined( self.script_specialops ) )
return false;
assertex( ( ( self.script_specialops == 0 ) || ( self.script_specialops == 1 ) ), "Entities with script_specialops set must use a value of either 0 or 1. Classname " + self.classname + " at Origin " + self.origin );
if ( self.script_specialops == special_op_state )
return false;
return true;
}
specialops_remove_name_check( special_op_state )
{
if ( !isdefined( self.script_specialopsname ) )
return false;
if ( special_op_state == 0 )
return true;
tokens = strtok( self.script_specialopsname, ":;, " );
delete_ent = true;
foreach ( token in tokens )
{
if ( token == level.script )
{
delete_ent = false;
break;
}
}
return delete_ent;
}
so_create_hud_item_delay_draw( hudelem )
{
hudelem.alpha = 0;
while( !so_hud_can_show() )
wait 0.5;
if ( !isdefined( hudelem ) )
return;
if ( so_hud_can_toggle( hudelem ) )
{
switch( self.so_infohud_toggle_state )
{
case "on":
case "none": hudelem fade_over_time( 1, 0.5 ); break;
case "off": hudelem fade_over_time( 0, 0.5 ); break;
default: assertmsg( "so_create_hud_item_delay_draw() encountered a setting for player.so_infohud_toggle_state (" + self.so_infohud_toggle_state + ") it didn't recognize." );
}
}
else
{
hudelem fade_over_time( 1, 0.5 );
}
if ( !self ent_flag( "so_hud_can_toggle" ) )
self ent_flag_set( "so_hud_can_toggle" );
}
so_hud_can_show()
{
if ( isdefined( level.so_waiting_for_players ) && level.so_waiting_for_players )
return false;
if ( isdefined( level.challenge_time_force_on ) && level.challenge_time_force_on )
return true;
if ( !isdefined( self.so_hud_show_time ) )
return true;
return ( gettime() > self.so_hud_show_time );
}
so_hud_can_toggle( hudelem )
{
if ( !isdefined( hudelem.so_can_toggle ) || !hudelem.so_can_toggle )
return false;
if ( !isdefined( self.so_infohud_toggle_state ) )
return false;
return true;
}
challenge_timer_player_setup( start_flag, passed_flag, message )
{
level endon( "challenge_timer_expired" );
level endon( "new_challenge_timer" );
level endon( "special_op_terminated" );
ypos = maps\_specialops::so_hud_ypos();
self.hud_so_timer_msg = maps\_specialops::so_create_hud_item( 1, ypos, message, self );
if ( isdefined( level.challenge_time_limit ) )
{
self.hud_so_timer_time = maps\_specialops::so_create_hud_item( 1, ypos, undefined /*convert_to_time_string( level.challenge_time_limit, true )*/, self );
self.hud_so_timer_time SetTenthsTimerStatic( level.challenge_time_limit );
}
else
self.hud_so_timer_time = maps\_specialops::so_create_hud_item( 1, ypos, &"SPECIAL_OPS_TIME_NULL", self );
self.hud_so_timer_time.alignX = "left";
thread maps\_specialops::info_hud_wait_for_player();
thread maps\_specialops::info_hud_handle_fade( self.hud_so_timer_msg );
thread maps\_specialops::info_hud_handle_fade( self.hud_so_timer_time );
challenge_timer_wait_start( self.hud_so_timer_msg, self.hud_so_timer_time, start_flag );
/* if ( !isdefined( level.challenge_progress_manual_update ) || !level.challenge_progress_manual_update )
{
thread challenge_timer_detect_3quarter();
thread challenge_timer_detect_halfway();
thread challenge_timer_detect_quarter();
}*/
if ( isdefined( level.challenge_time_limit ) )
{
level.so_challenge_time_left = level.challenge_time_limit;
thread challenge_timer_show_nudge( self.hud_so_timer_msg, self.hud_so_timer_time );
thread challenge_timer_show_hurry( self.hud_so_timer_msg, self.hud_so_timer_time );
thread challenge_timer_show_failed( self.hud_so_timer_msg, self.hud_so_timer_time );
thread challenge_timer_destroy_prematurely( self.hud_so_timer_msg, self.hud_so_timer_time );
}
thread challenge_timer_wait_passed( self.hud_so_timer_msg, self.hud_so_timer_time, passed_flag );
}
// CTW - Better way to do this: Have the timer detect the halfway mark when counting down
// and if you haven't set these flags, tell the player they need to pick it up.
challenge_timer_detect_3quarter()
{
if ( !flag_exist( "so_challenge_is_3quarter" ) )
flag_init( "so_challenge_is_3quarter" );
flag_wait( "so_challenge_is_3quarter" );
maps\_specialops::so_dialog_progress_update( 3, 4 );
}
challenge_timer_detect_halfway()
{
if ( !flag_exist( "so_challenge_is_halfway" ) )
flag_init( "so_challenge_is_halfway" );
flag_wait( "so_challenge_is_halfway" );
maps\_specialops::so_dialog_progress_update( 2, 4 );
}
challenge_timer_detect_quarter()
{
if ( !flag_exist( "so_challenge_is_quarter" ) )
flag_init( "so_challenge_is_quarter" );
flag_wait( "so_challenge_is_quarter" );
maps\_specialops::so_dialog_progress_update( 1, 4 );
}
challenge_timer_wait_start( hud_msg, hud_time, start_flag )
{
level endon( "special_op_terminated" );
if ( isdefined( start_flag ) )
flag_wait( start_flag );
// Force the hud on if player charges ahead.
foreach ( player in level.players )
{
if ( !player so_hud_can_show() )
player.so_hud_show_time = gettime();
}
if ( !isdefined( level.challenge_start_time ) )
{
if ( challenge_timer_should_play_alarm() )
level.player PlaySound( "arcademode_zerodeaths" );
level.challenge_start_time = gettime();
}
hud_time.label = "";
if ( isdefined( level.challenge_time_limit ) )
hud_time settenthstimer( level.challenge_time_limit );
else
hud_time settenthstimerup( 0.00 );
}
challenge_timer_should_play_alarm()
{
if ( isdefined( level.challenge_time_limit ) )
return true;
foreach ( player in level.players )
{
if ( player.so_infohud_toggle_state != "off" )
return true;
}
return false;
}
challenge_timer_show_nudge( hud_msg, hud_time )
{
if ( !validate_timer( level.challenge_time_nudge ) )
return;
level endon( "challenge_timer_passed" );
level endon( "new_challenge_timer" );
level endon( "special_op_terminated" );
// if ( level.challenge_time_limit > level.challenge_time_nudge )
// wait level.challenge_time_limit - level.challenge_time_nudge;
while ( level.so_challenge_time_left > level.challenge_time_nudge )
{
wait( 0.1 );
}
hud_msg set_hudelem_yellow();
hud_time set_hudelem_yellow();
if ( !challenge_timer_be_silent() )
thread maps\_specialops::so_dialog_time_low_normal();
}
challenge_timer_show_hurry( hud_msg, hud_time )
{
if ( !validate_timer( level.challenge_time_hurry ) )
return;
level endon( "challenge_timer_passed" );
level endon( "new_challenge_timer" );
level endon( "special_op_terminated" );
// if ( level.challenge_time_limit > level.challenge_time_hurry )
// wait level.challenge_time_limit - level.challenge_time_hurry;
while ( level.so_challenge_time_left > level.challenge_time_hurry )
{
wait( 0.1 );
}
hud_msg set_hudelem_red();
hud_time set_hudelem_red();
if ( !challenge_timer_be_silent() )
thread maps\_specialops::so_dialog_time_low_hurry();
}
challenge_timer_be_silent()
{
if ( self != level.player )
return true;
if ( !isdefined( level.challenge_time_silent ) )
return false;
return level.challenge_time_silent;
}
challenge_timer_thread()
{
level endon( "special_op_terminated" );
level notify( "stop_challenge_timer_thread" );
level endon( "stop_challenge_timer_thread" );
while ( level.so_challenge_time_left > 0 )
{
wait( 0.05 );
level.so_challenge_time_left -= 0.05;
thread challenge_timer_give_alert();
}
level notify( "challenge_timer_failed" );
}
challenge_timer_give_alert()
{
if ( challenge_timer_should_pulse() )
{
foreach ( player in level.players )
{
player.hud_so_timer_msg thread maps\_specialops::so_hud_pulse_create();
player.hud_so_timer_time thread maps\_specialops::so_hud_pulse_create();
}
if ( level.so_challenge_time_beep < 0 )
level.player PlaySound( "arcademode_kill_streak_lost" );
else
level.player PlaySound( "so_countdown_beep" );
}
}
challenge_timer_should_pulse()
{
if ( level.so_challenge_time_left > level.so_challenge_time_beep )
return false;
for ( i = 0; i <= level.challenge_time_beep_start; i++ )
{
if ( level.so_challenge_time_left > i )
{
// If the timer has been increased, need to reset our beep tracking.
if ( level.so_challenge_time_beep < i )
level.so_challenge_time_beep = i + 1;
continue;
}
// We already know time_left is less than time_beep, so go go go!
level.so_challenge_time_beep = i - 1;
return true;
}
return false;
}
challenge_timer_show_failed( hud_msg, hud_time )
{
if ( !validate_timer( level.challenge_time_limit ) )
return;
level endon( "challenge_timer_passed" );
level endon( "new_challenge_timer" );
level endon( "special_op_terminated" );
// wait( level.challenge_time_limit );
thread challenge_timer_thread();
level waittill( "challenge_timer_failed" );
flag_set( "challenge_timer_expired" );
level.challenge_end_time = gettime();
challenge_timer_destroy( hud_msg, hud_time );
// radio_dialogue_stop();
if ( self == level.player )
thread maps\_specialops::so_dialog_mission_failed_time();
maps\_specialops::so_force_deadquote( "@SPECIAL_OPS_FAILURE_HINT_TIME", "ui_time_failure" );
if ( self == level.player )
MissionFailedWrapper();
}
challenge_timer_wait_passed( hud_msg, hud_time, passed_flag )
{
level endon( "challenge_timer_expired" );
level endon( "new_challenge_timer" );
if ( flag_exist( "individual_timers" ) && flag( "individual_timers" ) )
self ent_flag_wait( passed_flag );
else
flag_wait( passed_flag );
flag_set( "challenge_timer_passed" );
level.challenge_end_time = gettime();
// This might not work in every circumstance?
// Freeze the timer where it is for the couple of seconds it remains visible.
time = ( level.challenge_end_time - level.challenge_start_time ) * 0.001;
if ( isdefined( level.challenge_time_limit ) )
time = level.challenge_time_limit - time;
// stupid hack to make this work correctly, because this mission modifies level.challenge_time_limit on the fly
if ( level.script == "so_snowrace2_cliffhanger" )
time = level.challenge_time_limit;
// We cannot have time be 0 when we call SetTenthsTimerStatic()
if ( time <= 0 )
{
time = 0.1;
}
hud_time SetTenthsTimerStatic( time );
if ( !flag_exist( "individual_timers" ) )
return;
if ( flag( "individual_timers" ) )
return;
challenge_timer_destroy( hud_msg, hud_time );
}
challenge_timer_destroy_prematurely( hud_msg, hud_time )
{
level waittill( "new_challenge_timer" );
challenge_timer_destroy( hud_msg, hud_time, true );
}
challenge_timer_destroy( hud_msg, hud_time, destroy_immediately )
{
if ( isdefined( hud_msg ) )
hud_msg thread maps\_specialops::so_remove_hud_item( destroy_immediately );
if ( isdefined( hud_time ) )
hud_time thread maps\_specialops::so_remove_hud_item( destroy_immediately );
}
validate_timer( timer )
{
if ( !isdefined( timer ) )
return false;
if ( timer <= 0 )
return false;
return true;
}
failure_summary_display()
{
if ( getdvarint( "so_nofail" ) )
return;
thread maps\_specialops::so_dialog_mission_failed_generic();
MissionFailed();
specialops_mission_over_setup( false );
// mission failed;
setDvar( "ui_mission_success", 0 );
level notify( "so_generate_deathquote" );
maps\_endmission::coop_eog_summary();
specialops_summary_player_choice();
}
specialops_mission_over_setup( was_success )
{
assertex( isdefined( was_success ), "specialops_mission_over_setup() requires a true or false value for the was_success parameter." );
if ( flag( "special_op_terminated" ) )
{
assertmsg( "The special op has somehow tried to end itself more than once. Current Success = " + was_success + " and Previous Success = " + level.special_op_success );
}
if ( !isdefined( level.challenge_end_time ) )
level.challenge_end_time = gettime();
flag_set( "special_op_terminated" );
level notify( "stop_music" );
// Initiate a pre-fetch of the texture data to help lower load times a bit.
stream_origin = undefined;
if ( isdefined( level.pmc_game ) && level.pmc_game )
stream_origin = pick_starting_location_pmc( true );
else
stream_origin = pick_starting_location_so( true );
if ( isdefined( stream_origin ) )
{
foreach ( player in level.players )
player PlayerSetStreamOrigin( stream_origin );
}
ambientStop( 2 );
music_stop( 1 );
if ( was_success )
thread specialops_mission_over_setup_success();
else
thread specialops_mission_over_setup_failure();
foreach ( player in level.players )
{
player AllowJump( false );
player disableweapons();
player disableusability();
player EnableInvulnerability();
player.ignoreme = true;
}
thread specialops_blur_player_screen();
wait 3;
thread specialops_mission_over_remove_ai();
if ( !flag( "special_op_no_unlink" ) )
{
foreach ( player in level.players )
{
player Unlink();
// org = player spawn_tag_origin();
// player PlayerLinkToDelta( org );
}
}
foreach ( player in level.players )
{
player freezecontrols( true );
}
// This needs to happen last as it's expected for all values used in stat collection to be set by now.
specialops_mission_over_stats( was_success );
}
specialops_blur_player_screen()
{
foreach ( player in level.players )
{
wait 0.1;
player setBlurForPlayer( 6, 1 );
}
}
specialops_mission_over_remove_ai()
{
wait 0.25;
ai_to_delete = getaiarray();
ai_to_delete = array_merge( ai_to_delete , getaiSpeciesArray( "axis", "dog" ) );
foreach ( ai in ai_to_delete )
{
if ( isdefined( ai.magic_bullet_shield ) )
ai stop_magic_bullet_shield();
ai Delete();
}
}
specialops_mission_over_setup_success()
{
flag_set( "special_op_succeeded" );
foreach ( player in level.players )
{
screen_fade = create_client_overlay( "white", 0, player );
screen_fade.color = ( 0.7, 0.7, 1 );
screen_fade thread fade_over_time( 0.25, 2 );
}
if ( isdefined( level.suppress_challenge_success_print ) )
return;
passed_hud = maps\_specialops::so_create_hud_item( 3, 0, &"SPECIAL_OPS_CHALLENGE_SUCCESS" );
passed_hud.alignX = "center";
passed_hud.horzAlign = "center";
passed_hud set_hudelem_blue();
passed_hud SetPulseFX( 60, 2500, 500 );
wait 1.5;
music_play( "so_victory_" + level.so_campaign, undefined, 0, true );
}
specialops_mission_over_setup_failure()
{
flag_set( "special_op_failed" );
passed_hud = maps\_specialops::so_create_hud_item( 3, 0, &"SPECIAL_OPS_CHALLENGE_FAILURE" );
passed_hud.hidewhendead = false;
passed_hud.alignX = "center";
passed_hud.horzAlign = "center";
passed_hud set_hudelem_red();
passed_hud SetPulseFX( 60, 2500, 500 );
foreach ( player in level.players )
{
screen_fade = create_client_overlay( "white", 0, player );
screen_fade.color = ( 1, 0.4, 0.4 );
screen_fade thread fade_over_time( 0.25, 2 );
}
wait 1.5;
music_play( "so_defeat_" + level.so_campaign, undefined, 0, true );
}
is_current_level_locked()
{
specOpsString = self GetLocalPlayerProfileData( "missionSOHighestDifficulty" );
if( !isdefined( specOpsString ) )
return true;
specOpsSum = 0;
for( i=0; i<specOpsString.size; i++ )
specOpsSum += max ( 0, int( specOpsString[i] ) - 1 );
current_group = tablelookup( "sp/specOpsTable.csv", 1, level.script, 13 );
return ( specOpsSum < int( tablelookup( "sp/specOpsTable.csv", 1, current_group, 5 ) ) );
}
is_so_player_signed_in()
{
//return self isSignedIn();
return true; //always true until code gives me a function
}
can_save_to_profile()
{
return self is_so_player_signed_in() && !( self is_current_level_locked() );
}
specialops_achievement_by_stars( specOpsString )
{
specOpsSum = get_total_stars( specOpsString );
// --------------- Gold Star: earn 1 star in special ops
if ( specOpsSum >= 1 )
self player_giveachievement_wrapper( "GOLD_STAR" );
// --------------- Hotel Bravo: earn 4 star in special ops
if ( specOpsSum >= 4 )
self player_giveachievement_wrapper( "HOTEL_BRAVO" );
// --------------- Charlie on our six: earn 8 star in special ops
if ( specOpsSum >= 8 )
self player_giveachievement_wrapper( "CHARLIE_ON_OUR_SIX" );
// --------------- Blackjack: earn 21 star in special ops
if ( specOpsSum >= 21 )
self player_giveachievement_wrapper( "BLACKJACK" );
// --------------- Specialist: earn 30 star in special ops
if ( specOpsSum >= 30 )
self player_giveachievement_wrapper( "SPECIALIST" );
// --------------- Star 69: earn 69 star in special ops
if ( specOpsSum >= 69 )
self player_giveachievement_wrapper( "STAR_69" );
// =============== It Goes to Eleven: 1 star in 11 different SO
if ( get_num_of_levels_with_star( specOpsString, 1 ) >= 11 )
self player_giveachievement_wrapper( "IT_GOES_TO_ELEVEN" );
// =============== Operational Asset: 3 stars in 5 different SO
if ( get_num_of_levels_with_star( specOpsString, 3 ) >= 5 )
self player_giveachievement_wrapper( "OPERATIONAL_ASSET" );
// =============== Honor Roll: 1 star in 23 different SO
if ( get_num_of_levels_with_star( specOpsString, 1 ) >= 23 )
self player_giveachievement_wrapper( "HONOR_ROLL" );
// =============== Operative: 3 stars in 10 different SO
if ( get_num_of_levels_with_star( specOpsString, 3 ) >= 10 )
self player_giveachievement_wrapper( "OPERATIVE" );
// =============== Professional: 3 stars in 15 different SO
if ( get_num_of_levels_with_star( specOpsString, 3 ) >= 15 )
self player_giveachievement_wrapper( "PROFESSIONAL" );
}
get_total_stars( specOpsString )
{
string_size = specOpsString.size;
if ( string_size > level.specOpsSettings.levels.size )
string_size = level.specOpsSettings.levels.size;
specOpsSum = 0;
for( i=0; i<string_size; i++ )
{
specOpsSum += max ( 0, int( specOpsString[i] ) - 1 );
}
return specOpsSum;
}
get_num_of_levels_with_star( specOpsString, stars )
{
string_size = specOpsString.size;
if ( string_size > level.specOpsSettings.levels.size )
string_size = level.specOpsSettings.levels.size;
levels = 0;
for( i=0; i<string_size; i++ )
{
if( max ( 0, int( specOpsString[i] ) - 1 ) >= stars )
levels++;
}
return levels;
}
specialops_mission_over_stats( was_success )
{
if ( !isdefined( was_success ) || !was_success )
return;
// using map name to get dvar used for saving that map's best time
best_time_name = tablelookup( "sp/specOpsTable.csv", 1, level.script, 9 );
// Test maps shouldn't have to SRE out.
if ( best_time_name == "" )
return;
// Early out the player that doesnt have the level unlocked, cause we dont give him reward
foreach( player in level.players )
{
if ( !( player can_save_to_profile() ) )
{
/#
PrintLn( ">> UpdateGamerProfileAll(): [ PLAYER 2 SKIPPED ALL PROFILE UPDATES DUE TO LEVEL LOCKED ]" );
#/
player.eog_noreward = true;
}
}
// PS3 special handler - PS3 splitscreen, guest player always get stars when first player get stars
if ( issplitscreen() && level.ps3 )
level.player2.eog_noreward = false;
assert( isdefined( best_time_name ) );
assert( isdefined( level.challenge_start_time ) );
assert( isdefined( level.challenge_end_time ) );
// time is capped at 24 hours
m_seconds = int( min( ( level.challenge_end_time - level.challenge_start_time ), 86400000 ) );
foreach( player in level.players )
{
if ( isdefined( player.eog_noreward ) && player.eog_noreward )
continue;
current_best_time = player GetLocalPlayerProfileData( best_time_name );
if ( !isdefined( current_best_time ) )
continue; // non local player
never_played = current_best_time == 0;
if ( isdefined( player.finish_time ) && isdefined( level.challenge_start_time ) )
m_seconds = int( min( ( player.finish_time - level.challenge_start_time ), 86400000 ) );
if ( never_played || m_seconds < current_best_time )
player SetLocalPlayerProfileData( best_time_name, m_seconds );
if ( !never_played && m_seconds < current_best_time )
{
player.eog_besttime = true;
player.eog_besttime_value = m_seconds;
}
}
levelIndex = level.specOpsSettings maps\_endmission::getLevelIndex( level.script );
if ( !isDefined( levelIndex ) )
{
// run the same mission again if the nextmission is not defiend.
MissionSuccess( level.script );
return;
}
// update mission difficult dvar
level.specOpsSettings maps\_endmission::setSoLevelCompleted( levelIndex );
foreach( player in level.players )
{
if ( isdefined( player.eog_noreward ) && player.eog_noreward )
continue;
missionSpecOps = player GetLocalPlayerProfileData( "missionSpecOps" );
if ( !isdefined( missionSpecOps ) )
continue;
if ( missionSpecOps < levelindex + 1 )
player SetLocalPlayerProfileData( "missionSpecOps", levelIndex + 1 );
}
foreach( player in level.players )
{
if ( isdefined( player.eog_noreward ) && player.eog_noreward )
continue;
specOpsString = player GetLocalPlayerProfileData( "missionSOHighestDifficulty" );
if( !isdefined( specOpsString ) )
continue;
assertex( isdefined( level.specOpsSettings ), "Special Op levels are not yet initialized in _endmission.gsc and we are already trying to save level difficulty completed data." );
// specOpsString is a string of something like '0123412324200323404...' ranging from 0 to 4, for special ops we need range of 0 to 3.
// string size can not count higher then number of levels or we will have 100%+
string_size = specOpsString.size;
if ( string_size > level.specOpsSettings.levels.size )
string_size = level.specOpsSettings.levels.size;
specOpsSum = 0;
for( i=0; i<string_size; i++ )
specOpsSum += int( max ( 0, int( specOpsString[i] ) - 1 ) );
assertex( specOpsSum >= 0 && specOpsSum <= ( level.specOpsSettings.levels.size * 3 ), "More stars earned than possible!" );
completion_percentage = 0;
completion_fraction = 100 * ( ( specOpsSum ) / ( level.specOpsSettings.levels.size * 3 ) );
assert( isdefined( completion_fraction ) );
// round up or down
if ( int(completion_fraction*100)%100 >= 0.5 )
completion_percentage = int( completion_fraction ) + 1;
else
completion_percentage = int( completion_fraction );
assertex( ( completion_percentage >= 0 && completion_percentage <= 100 ), "Special Ops' completion percentage [ " + completion_percentage + "% ] is outside of 0 to 100 range!" );
player specialops_achievement_by_stars( specOpsString );
/#
setlevel = getdvarint( "ui_debug_setlevel" );
if( setlevel != 0 )
{
player SetLocalPlayerProfileData( "missionspecops", setlevel );
level.specOpsSettings maps\_endmission::setSoLevelCompleted( max( 0, setlevel-1 ) );
setdvar( "ui_debug_setlevel", "" );
}
upto = getdvarint( "ui_debug_setlevel_upto" );
if( upto != 0 )
{
player SetLocalPlayerProfileData( "missionspecops", upto );
difficulty_string = "";
for( i=0; i<upto; i++ )
{
difficulty_string += "4";
level.specOpsSettings maps\_endmission::setSoLevelCompleted( i );
}
player SetLocalPlayerProfileData( "missionsohighestdifficulty", difficulty_string );
setdvar( "ui_debug_setlevel_upto", "" );
}
// Debug prints
PrintLn( ">> SO DEBUG: [ setlevel:" + setlevel + " setlevel_upto:" + upto + " clearall:" + getdvarint( "ui_debug_clearall" ) + " ]" );
PrintLn( ">> SO PLAYER ID: [" + player GetEntityNumber() + "]" );
PrintLn( ">> SO PERCENTAGE COMPLETED: [" + specOpsString + "]" );
PrintLn( ">> SO PLAYER PERCENTAGE: [" + completion_percentage + "%]" );
PrintLn( ">> SO PLAYER TOTAL STARS: [" + specOpsSum + "%]" );
PrintLn( ">> SO LEVEL INDEX: [" + level.specOpsSettings maps\_endmission::getLevelIndex( level.script ) + "]" );
PrintLn( ">> SO LEVEL NAME: [" + level.script + "]" );
PrintLn( ">> SO STARS EARNED: [" + specOpsSum + "]" );
PrintLn( ">> SO MAX LEVELS: [" + level.specOpsSettings.levels.size + "]" );
#/
player SetLocalPlayerProfileData( "percentCompleteSO", specOpsSum );
//player SetLocalPlayerProfileData( "percentCompleteSO", completion_percentage );
}
UpdateGamerProfileAll();
/#
PrintLn( ">> UpdateGamerProfileAll(): [ CALLED ]" );
#/
}
specialops_summary_player_choice()
{
for ( ;; )
{
response = waittill_either_player();
// if player chooses to return to main menu
if ( response == "summary_closed" )
{
ChangeLevel( "" );
return;
}
// if player chooses to play again
if ( response == "summary_closed_play_again" )
{
ChangeLevel( level.script );
return;
}
}
}
wait_all_players_are_touching( trigger_ent )
{
for ( ;; )
{
trigger_ent waittill( "trigger" );
// If not in co-op, then a simple touch is all we need.
if ( !is_coop() )
return;
level.player thread waiting_message_hide();
level.player2 thread waiting_message_hide();
if ( !level.player IsTouching( trigger_ent ) )
{
level.player2 thread display_waiting_message();
continue;
}
if ( !level.player2 IsTouching( trigger_ent ) )
{
level.player thread display_waiting_message();
continue;
}
// If we get here then we've succeeded...
break;
}
}
wait_all_players_have_touched( trigger_ent, touch_style )
{
player1_touched = false;
player2_touched = false;
for ( ;; )
{
trigger_ent waittill( "trigger" );
// If not in co-op, then a simple touch is all we need.
if ( !is_coop() )
return;
level.player thread waiting_message_hide();
level.player2 thread waiting_message_hide();
if ( level.player IsTouching( trigger_ent ) )
{
player1_touched = true;
if ( !player2_touched && !level.player2 IsTouching( trigger_ent ) )
{
thread determine_waiting_message( level.player, touch_style );
continue;
}
}
if ( level.player2 IsTouching( trigger_ent ) )
{
player2_touched = true;
if ( !player1_touched && !level.player IsTouching( trigger_ent ) )
{
thread determine_waiting_message( level.player2, touch_style );
continue;
}
}
// If we get here then we've succeeded...
break;
}
}
disable_mission_end_trigger( trigger_ent )
{
level waittill( "special_op_terminated" );
trigger_ent trigger_off();
}
determine_waiting_message( player, touch_style )
{
switch ( touch_style )
{
case "all" : player display_waiting_message(); break;
case "any" : player display_waiting_message(); break;
case "freeze" : player display_frozen_message(); break;
}
}
display_waiting_message()
{
self endon( "death" );
level endon( "challenge_timer_passed" );
level endon( "challenge_timer_expired" );
level endon( "special_op_terminated" );
level notify( "players_touching_hint" );
level endon( "players_touching_hint" );
if ( !isdefined( self ) )
return;
if ( !isdefined( self.waiting_hud ) )
{
self.waiting_hud = create_waiting_message( self );
}
else
{
self.waiting_hud.alpha = 1;
}
wait 0.05;
self.waiting_hud fadeovertime( 0.25 );
self.waiting_hud.alpha = 0;
}
display_frozen_message()
{
if ( !isdefined( self ) )
return;
// Don't need to fade in again if already active.
if ( isdefined( self.frozen_and_waiting ) && self.frozen_and_waiting )
return;
self.frozen_and_waiting = true;
self EnableInvulnerability();
self FreezeControls( true );
self.ignoreme = true;
self setBlurForPlayer( 6, 1 );
self.waiting_hud = create_waiting_message( self );
}
create_waiting_message( player )
{
self notify( "rebuilding_waiting_hud" );
self endon( "rebuilding_waiting_hud" );
waiting_hud = maps\_specialops::so_create_hud_item( 3, 0, &"SPECIAL_OPS_WAITING_OTHER_PLAYER", player );
waiting_hud.alignX = "center";
waiting_hud.horzAlign = "center";
waiting_hud set_hudelem_blue();
thread waiting_message_delete_on_so_end( waiting_hud );
return waiting_hud;
}
waiting_message_hide()
{
if ( !isdefined( self ) )
return;
if ( !isdefined( self.waiting_hud ) )
return;
if ( isdefined( self.frozen_and_waiting ) && self.frozen_and_waiting )
return;
self.waiting_hud fadeovertime( 0.25 );
self.waiting_hud.alpha = 0;
}
waiting_message_delete_on_so_end( waiting_hud )
{
self endon( "rebuilding_waiting_hud" );
level waittill( "special_op_terminated" );
if ( isdefined( waiting_hud ) )
waiting_hud Destroy();
}
disable_saving()
{
flag_set( "disable_autosaves" );
for ( ;; )
{
flag_wait( "can_save" );
flag_clear( "can_save" );
}
}
disable_escape_warning()
{
if ( flag( "player_has_escaped" ) )
{
return true;
}
if ( self is_touching_escape_trigger() )
{
return false;
}
// self.escape_hint_active = undefined;
// self.escape_hint_active = undefined;
// if ( isdefined( self.ping_escape_splash ) )
// self.ping_escape_splash Destroy();
return true;
}
is_touching_escape_trigger()
{
if ( !IsDefined( level.escape_warning_triggers ) )
{
return false;
}
foreach ( trigger in level.escape_warning_triggers )
{
if ( self IsTouching( trigger ) )
{
return true;
}
}
return false;
}
ping_escape_warning()
{
if ( isdefined( self.ping_escape_splash ) )
return;
self endon( "death" );
self.ping_escape_splash = maps\_specialops::so_create_hud_item( 3.5, 0, &"SPECIAL_OPS_ESCAPE_WARNING", self );
self.ping_escape_splash.alignx = "center";
self.ping_escape_splash.horzAlign = "center";
// self.ping_escape_splash set_hudelem_red();
while ( ping_escape_warning_valid() )
{
// self PlayLocalSound( "coop_player_exit_warning" );
self.ping_escape_splash.alpha = 1;
self.ping_escape_splash FadeOverTime( 1 ) ;
self.ping_escape_splash.alpha = 0.5;
self.ping_escape_splash.fontscale = 1.5;
self.ping_escape_splash ChangeFontScaleOverTime( 1 );
self.ping_escape_splash.fontscale = 1;
wait 1;
}
self.ping_escape_splash.alpha = 0.5;
self.ping_escape_splash FadeOverTime( 0.25 );
self.ping_escape_splash.alpha = 0;
wait 0.25;
self.escape_hint_active = undefined;
if ( isdefined( self.ping_escape_splash ) )
self.ping_escape_splash Destroy();
}
ping_escape_warning_valid()
{
if ( flag( "special_op_terminated" ) )
return false;
// if ( !isdefined( self.escape_hint_active ) )
// {
// return false;
// }
if ( !self is_touching_escape_trigger() )
{
return false;
}
return true;
}
so_dialog_play( dialog, wait_time, force_stop )
{
assertex( isdefined( dialog ), "so_dialog_play() requires valid dialog to be passed in." );
if ( isdefined( wait_time ) )
wait wait_time;
// This isn't a good long term solution to SO spam. The Battle Chatter stuff (reviving) needs to be switched
// to the actual battle chatter system.
if ( isdefined( force_stop ) && force_stop )
radio_dialogue_stop();
radio_dialogue( dialog );
}
specialops_dialog_init()
{
// Let's do this.
// Ready up.
level.scr_radio[ "so_tf_1_plyr_prep" ] = "so_tf_1_plyr_prep";
// That's the way it's done.
// Good job team.
// Mission accomplished.
level.scr_radio[ "so_tf_1_success_generic" ] = "so_tf_1_success_generic";
// Not bad, but I've seen better.
// Well done, but you can do better.
// Not the best, but you made it.
level.scr_radio[ "so_tf_1_success_jerk" ] = "so_tf_1_success_jerk";
//Nicely done, you beat your previous best.
//A new personal record, great work.
//You beat your previous best, keep it up.
//Excellent job, a new personal best.
level.scr_radio[ "so_tf_1_success_best" ] = "so_tf_1_success_best";
// Mission failed. We<57>ll get 'em next time.
// We need to rethink our strategy. Let's run it again.
level.scr_radio[ "so_tf_1_fail_generic" ] = "so_tf_1_fail_generic";
// Well that was a disaster! Let's try it again.
// Bloody 'ell, we just got our arses kicked.
level.scr_radio[ "so_tf_1_fail_generic_jerk" ] = "so_tf_1_fail_generic_jerk";
// We ran outta time. Keep an eye the clock.
// Too slow mate. Next time watch the clock, eh?
level.scr_radio[ "so_tf_1_fail_time" ] = "so_tf_1_fail_time";
// We win as a team, we lose as a team. Got it?
// Look - we work as a team. No one gets left behind!
level.scr_radio[ "so_tf_1_fail_bleedout" ] = "so_tf_1_fail_bleedout";
// We're running out of time!
// The clock's ticking...
// Not much time left!
level.scr_radio[ "so_tf_1_time_generic" ] = "so_tf_1_time_generic";
// Time's running out! Go! Go! Go!
// We're almost outta time! Move! Move!
// Time's almost up! This is gonna be close!!
level.scr_radio[ "so_tf_1_time_hurry" ] = "so_tf_1_time_hurry";
// Watch your fire, avoid civilians!
// Civilian casualties are unacceptable!
// Careful, you're killing innocent civilians!
level.scr_radio[ "so_tf_1_civ_kill_warning" ] = "so_tf_1_civ_kill_warning";
// 5 more.
// 5 left.
// 5 remaining
level.scr_radio[ "so_tf_1_progress_5more" ] = "so_tf_1_progress_5more";
// 4 more.
// 4 left.
// 4 remaining
level.scr_radio[ "so_tf_1_progress_4more" ] = "so_tf_1_progress_4more";
// 3 more.
// 3 left.
// 3 remaining
level.scr_radio[ "so_tf_1_progress_3more" ] = "so_tf_1_progress_3more";
// 2 more.
// 2 left.
// 2 remaining
level.scr_radio[ "so_tf_1_progress_2more" ] = "so_tf_1_progress_2more";
// 1 more.
// 1 left.
// 1 remaining
level.scr_radio[ "so_tf_1_progress_1more" ] = "so_tf_1_progress_1more";
// Cutting it close, need to pick up the pace.
// You're running behind, hurry up or you won't make it.
// Pay attention to the time, you're moving too slow.
level.scr_radio[ "so_tf_1_time_status_late" ] = "so_tf_1_time_status_late";
// Looking good, keep up this pace.
// Your time is solid, keep it up.
// Keep going, you're making good time.
level.scr_radio[ "so_tf_1_time_status_good" ] = "so_tf_1_time_status_good";
// 25% done<6E> keep going.
// You've made it a quarter of the way, don't stop.
// 25% down, 75% to go.
level.scr_radio[ "so_tf_1_progress_3quarter" ] = "so_tf_1_progress_3quarter";
// Hallfway there.
// You're halfway done.
// Halfway through the mission.
level.scr_radio[ "so_tf_1_progress_half" ] = "so_tf_1_progress_half";
// Getting close, keep it up.
// You're doing well, almost done.
// Just a little bit left, keep going.
level.scr_radio[ "so_tf_1_progress_quarter" ] = "so_tf_1_progress_quarter";
}
set_hudelem_white()
{
self maps\_specialops::set_hud_white();
}
set_hudelem_blue()
{
self maps\_specialops::set_hud_blue();
}
set_hudelem_green()
{
self maps\_specialops::set_hud_green();
}
set_hudelem_yellow()
{
self maps\_specialops::set_hud_yellow();
}
set_hudelem_red()
{
self maps\_specialops::set_hud_red();
}
so_hud_pulse_single( scale_start, scale_end, time )
{
self endon( "update_hud_pulse" );
self endon( "destroying" );
self endon( "death" );
self.fontscale = scale_start;
self changefontscaleovertime( time );
self.fontscale = scale_end;
wait time;
}
so_hud_pulse_loop()
{
self endon( "update_hud_pulse" );
self endon( "destroying" );
self endon( "death" );
if ( self.pulse_start_big )
so_hud_pulse_single( self.pulse_scale_big, self.pulse_scale_loop_normal, self.pulse_time );
while( isdefined( self.pulse_loop ) && self.pulse_loop )
{
so_hud_pulse_single( self.pulse_scale_loop_normal, self.pulse_scale_loop_big, self.pulse_time_loop );
so_hud_pulse_single( self.pulse_scale_loop_big, self.pulse_scale_loop_normal, self.pulse_time_loop );
}
}
so_hud_pulse_init()
{
if ( !isdefined( self ) )
return false;
// Bang defaults
if ( !isdefined( self.pulse_time ) )
self.pulse_time = 0.5;
if ( !isdefined( self.pulse_scale_normal ) )
self.pulse_scale_normal = 1.0;
if ( !isdefined( self.pulse_scale_big ) )
self.pulse_scale_big = 1.6;
// Looping defaults
if ( !isdefined( self.pulse_loop ) )
self.pulse_loop = false;
if ( !isdefined( self.pulse_time_loop ) )
self.pulse_time_loop = 1.0;
if ( !isdefined( self.pulse_scale_loop_normal ) )
self.pulse_scale_loop_normal = 1.0;
if ( !isdefined( self.pulse_scale_loop_big ) )
self.pulse_scale_loop_big = 1.15;
if ( !isdefined( self.pulse_start_big ) )
self.pulse_start_big = true;
// Successful initialization!
return true;
}
specialops_detect_death()
{
level endon( "special_op_terminated" );
array_thread( level.players, ::specialops_detect_player_death );
level waittill( "so_player_has_died" );
level.challenge_end_time = gettime();
MissionFailedWrapper();
}
specialops_detect_player_death()
{
level endon( "special_op_terminated" );
self waittill( "death" );
level notify( "so_player_has_died" );
}
waittill_either_player()
{
if ( !flag_exist( "summary_response" ) )
flag_init( "summary_response" );
if( level.players.size > 1 )
{
// We must clear this each time we get in here, incase a menuresponse previously was not desired
// example, options menuresponse or "back" (online player in pause menu when everyone died)
// This will allow us to return to the EOG fine.
flag_clear( "summary_response" );
thread waittill_player_respond( 0 );
thread waittill_player_respond( 1 );
flag_wait( "summary_response" );
return level.summary_response;
}
else
{
level.players[0] waittill( "menuresponse", menu, response );
return response;
}
}
waittill_player_respond( player_num )
{
level endon( "summary_response" );
level.players[ player_num ] waittill( "menuresponse", menu, response );
level.summary_response = response;
flag_set( "summary_response" );
}
so_special_failure_hint_reset_dvars( icon_dvar )
{
setdvar( "ui_dog_death", 0 );
setdvar( "ui_vehicle_death", 0 );
setdvar( "ui_destructible_death", 0 );
setdvar( "ui_barrel_death", 0 );
setdvar( "ui_grenade_death", 0 );
setdvar( "ui_time_failure", 0 );
setdvar( "ui_ff_death", 0 );
setdvar( "ui_juggernaut_death", 0 );
setdvar( "ui_bled_out", 0 );
setdvar( "ui_icon_partner", 0 );
setdvar( "ui_icon_obj", 0 );
setdvar( "ui_icon_obj_offscreen", 0 );
setdvar( "ui_icon_stars", 0 );
setdvar( "ui_icon_claymore", 0 );
setdvar( "ui_icon_stealth_stance", 0 );
if ( isdefined( icon_dvar ) )
setdvar( icon_dvar, 1 );
}
so_special_failure_hint()
{
so_special_failure_hint_reset_dvars();
foreach( player in level.players )
{
player thread maps\_load::player_throwgrenade_timer();
player thread so_special_death_hint_tracker();
}
level waittill( "so_generate_deathquote" );
maps\_quotes::setDeadQuote_so();
}
so_special_death_hint_tracker()
{
level endon( "so_special_failure_hint_set" );
// NOTE: weapon may be undefined, so be sure to check for it if you use it.
self waittill( "death", attacker, cause, weapon );
if ( isdefined( self.coop_death_reason ) )
{
attacker = self.coop_death_reason[ "attacker" ];
cause = self.coop_death_reason[ "cause" ];
weapon = self.coop_death_reason[ "weapon_name" ];
}
if ( so_claymore_death( cause, weapon ) )
return;
if ( so_friendly_fire_death( attacker ) )
return;
if ( so_radiation_death( attacker ) )
return;
if ( so_dog_death( attacker ) )
return;
if ( so_juggernaut_death( attacker ) )
return;
if ( so_grenade_suicide_death( cause ) )
return;
if ( so_destructible_death( attacker, cause ) )
return;
if ( so_exploding_barrel_death( cause ) )
return;
if ( so_grenade_regular_death( cause ) )
return;
if ( so_vehicle_death( attacker, cause ) )
return;
}
so_claymore_death( cause, weapon )
{
if ( !IsDefined( cause ) )
{
return false;
}
if ( !IsDefined( weapon ) || ( IsDefined( weapon ) && weapon != "claymore" ) )
{
return false;
}
// No message if killed by a claymore
return true;
}
so_friendly_fire_death( attacker )
{
if ( !is_coop() )
return false;
if ( !isdefined( attacker ) )
return false;
other_player = get_other_player( self );
if ( other_player != attacker )
return false;
so_special_failure_hint_set( "@DEADQUOTE_SO_FRIENDLY_FIRE_KILL", "ui_ff_death" );
return true;
}
so_radiation_death( attacker )
{
if ( !isdefined( attacker ) || ( attacker.classname != "worldspawn" ) )
return false;
if ( !isdefined( self.radiationDeath ) || !self.radiationDeath )
return false;
so_special_failure_hint_set( "@SCRIPT_RADIATION_DEATH" );
return true;
}
so_dog_death( attacker )
{
if ( !isdefined( attacker ) )
return false;
if ( !isdefined( attacker.weapon ) )
return false;
if ( attacker.weapon != "dog_bite" )
return false;
switch( level.dog_death_type )
{
case "soon": so_special_failure_hint_set( "@NEW_DOG_DEATH_TOO_SOON_ALT", "ui_dog_death" ); break;
case "late": so_special_failure_hint_set( "@NEW_DOG_DEATH_TOO_LATE_ALT", "ui_dog_death" ); break;
default: so_special_failure_hint_set( "@NEW_DOG_DEATH_DO_NOTHING_ALT", "ui_dog_death" ); break;
}
return true;
}
so_juggernaut_death( attacker )
{
if ( !isdefined( attacker ) )
return false;
if ( !isdefined( attacker.juggernaut ) )
return false;
deadquotes = [];
deadquotes[ 0 ] = "@DEADQUOTE_JUGGERNAUT_FLASHBANGS";
deadquotes[ 1 ] = "@DEADQUOTE_JUGGERNAUT_HIGHCALIBER_WEAPONS";
deadquotes[ 2 ] = "@DEADQUOTE_JUGGERNAUT_HEADSHOTS";
deadquotes[ 3 ] = "@DEADQUOTE_JUGGERNAUT_EXPLOSIVES";
deadquotes[ 4 ] = "@DEADQUOTE_JUGGERNAUT_CORNERED";
so_special_failure_hint_set_array( deadquotes, "ui_juggernaut_death" );
return true;
}
so_destructible_death( attacker, cause )
{
if ( !isdefined( cause ) )
return false;
if ( !isdefined( attacker ) )
return false;
if ( cause != "MOD_EXPLOSIVE" )
return false;
if ( !isdefined( attacker.destructible_type ) )
return false;
if ( issubstr( attacker.destructible_type, "vehicle" ) )
{
// You were killed by an exploding vehicle. Vehicles on fire are likely to explode.
so_special_failure_hint_set( "@SCRIPT_EXPLODING_VEHICLE_DEATH", "ui_vehicle_death" );
}
else
{
// You were killed by an explosion.\nSome burning objects can explode.
so_special_failure_hint_set( "@SCRIPT_EXPLODING_DESTRUCTIBLE_DEATH", "ui_destructible_death" );
}
return true;
}
so_exploding_barrel_death( cause )
{
if ( !isdefined( cause ) )
return false;
if ( cause != "MOD_EXPLOSIVE" )
return false;
// check if the death was caused by a barrel
// have to check time and location against the last explosion because the attacker isn't the
// barrel because the ent that damaged the barrel is passed through as the attacker instead
if ( !isdefined( level.lastExplodingBarrel ) )
return false;
// killed the same frame a barrel exploded
if ( getTime() != level.lastExplodingBarrel[ "time" ] )
return false;
// within the blast radius of the barrel that exploded
d = distance( self.origin, level.lastExplodingBarrel[ "origin" ] );
if ( d > level.lastExplodingBarrel[ "radius" ] )
return false;
// You were killed by an exploding barrel. Red barrels will explode when shot.
so_special_failure_hint_set( "@SCRIPT_EXPLODING_BARREL_DEATH", "ui_barrel_death" );
return true;
}
so_grenade_suicide_death( cause )
{
if ( !isdefined( cause ) )
return false;
if ( cause != "MOD_SUICIDE" )
return false;
// magic number copied from fraggrenade asset.
if ( ( self.lastgrenadetime - gettime() ) > 3.5 * 1000 )
return false;
// You died holding a grenade for too long.
// Holding ^3[{+frag}]^7 allows you to cook off live grenades.
so_special_failure_hint_set( "@SCRIPT_GRENADE_SUICIDE_COMBINED" );
return true;
}
so_grenade_regular_death( cause )
{
if ( !isdefined( cause ) )
{
return false;
}
if ( cause != "MOD_GRENADE" && cause != "MOD_GRENADE_SPLASH" )
{
return false;
}
so_special_failure_hint_set( "@SCRIPT_GRENADE_DEATH", "ui_grenade_death" );
return true;
}
so_vehicle_death( attacker, cause )
{
if ( !isdefined( cause ) )
return false;
if ( !isdefined( attacker ) )
return false;
if ( cause != "MOD_CRUSH" )
return false;
if ( attacker.code_classname != "script_vehicle" )
return false;
// You were run over. Keep on eye out for enemy vehicles on the move.
so_special_failure_hint_set( "@DEADQUOTE_SO_RUN_OVER_BY_VEHICLE" );
return true;
}
so_special_failure_hint_set( quote, icon_dvar )
{
maps\_specialops::so_force_deadquote( quote, icon_dvar );
level notify( "so_special_failure_hint_set" );
}
so_special_failure_hint_set_array( quotes, icon_dvar )
{
maps\_specialops::so_force_deadquote_array( quotes, icon_dvar );
level notify( "so_special_failure_hint_set" );
}