mirror of
https://github.com/reaaLx/nx1-gsc-dump.git
synced 2025-04-22 09:05:45 +00:00
1501 lines
35 KiB
Plaintext
1501 lines
35 KiB
Plaintext
//****************************************************************************
|
|
// **
|
|
// Confidential - (C) Activision Publishing, Inc. 2010 **
|
|
// **
|
|
//****************************************************************************
|
|
// **
|
|
// Module: Mission Utils **
|
|
// **
|
|
// Created: DATE - CREATOR **
|
|
// **
|
|
//****************************************************************************
|
|
|
|
#include maps\_utility;
|
|
#include common_scripts\utility;
|
|
#include maps\_vehicle;
|
|
|
|
// Use more
|
|
// AssertEx( IsDefined( object ), "Assert message" );
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
pre_turret_event()
|
|
{
|
|
smoke_plumes_hide();
|
|
pre_turret_destruction_event();
|
|
}
|
|
|
|
post_turret_event()
|
|
{
|
|
smoke_plumes_show();
|
|
post_turret_destruction_event();
|
|
}
|
|
|
|
// Hide all the plumes
|
|
smoke_plumes_hide()
|
|
{
|
|
smoke_plumes = GetEntArray( "rocket_fuel_smoke", "targetname" );
|
|
foreach( plume in smoke_plumes )
|
|
{
|
|
//iprintln( "hiding plume" );
|
|
plume hide();
|
|
}
|
|
}
|
|
|
|
// Show all the plumes
|
|
smoke_plumes_show()
|
|
{
|
|
smoke_plumes = GetEntArray( "rocket_fuel_smoke", "targetname" );
|
|
foreach( plume in smoke_plumes )
|
|
{
|
|
//iprintln( "showing plume" );
|
|
plume show();
|
|
}
|
|
}
|
|
|
|
// SHOW/HIDE VARIOUS OBJECTS BEFORE TURRET DESTRUCTION.
|
|
pre_turret_destruction_event()
|
|
{
|
|
pre_destruction_objects = GetEntArray( "pre_turret_destruction_event", "targetname" );
|
|
foreach( object in pre_destruction_objects )
|
|
{
|
|
object show();
|
|
}
|
|
|
|
post_destruction_objects = GetEntArray( "post_turret_destruction_event", "targetname" );
|
|
foreach( object in post_destruction_objects )
|
|
{
|
|
object hide();
|
|
}
|
|
}
|
|
|
|
// SHOW/HIDE VARIOUS OBJECTS AFTER TURRET DESTRUCTION.
|
|
post_turret_destruction_event()
|
|
{
|
|
pre_destruction_objects = GetEntArray( "pre_turret_destruction_event", "targetname" );
|
|
foreach( object in pre_destruction_objects )
|
|
{
|
|
object hide();
|
|
}
|
|
|
|
post_destruction_objects = GetEntArray( "post_turret_destruction_event", "targetname" );
|
|
foreach( object in post_destruction_objects )
|
|
{
|
|
object show();
|
|
}
|
|
}
|
|
|
|
// Causes an APC's turret to fire at target
|
|
// JR - Add a distance check
|
|
apc_turret_logic( main_target, other_targets )
|
|
{
|
|
self endon( "death" );
|
|
self thread apc_chooses_target( main_target, other_targets );
|
|
|
|
for(;;)
|
|
{
|
|
shots = randomintrange( 5, 10 );
|
|
for( i = 0 ; i < shots ; i++ )
|
|
{
|
|
self fireWeapon();
|
|
wait 0.1;
|
|
}
|
|
wait randomfloatrange( 1.0, 3.0 );
|
|
}
|
|
}
|
|
|
|
apc_chooses_target( main_target, other_targets )
|
|
{
|
|
self endon( "death" );
|
|
main_target endon( "death" );
|
|
|
|
self.dummy_target = spawn( "script_origin", self.origin + ( 0, 0, 70 ) );
|
|
self thread delete_on_death( self.dummy_target );
|
|
self SetTurretTargetEnt( self.dummy_target );
|
|
self.accuracy = 0.1; // Default
|
|
|
|
if ( !isDefined( self.kill_player_max_dist_sqr ) )
|
|
{
|
|
self.kill_player_max_dist_sqr = 3500 * 3500;
|
|
}
|
|
|
|
if ( !isDefined( self.kill_player_time ) )
|
|
{
|
|
self.kill_player_time = 2.0;
|
|
}
|
|
|
|
if ( !isDefined( self.kill_player_fov_cos ) )
|
|
{
|
|
self.kill_player_fov_cos = 0.3;
|
|
}
|
|
|
|
time_in_kill_player_range = 0.0;
|
|
killing_player = false;
|
|
|
|
while ( 1 )
|
|
{
|
|
dist_sqr_to_main = DistanceSquared( main_target.origin, self.origin );
|
|
//println( "APC dist to player: " + Distance( main_target.origin, self.origin ) );
|
|
if ( dist_sqr_to_main < self.kill_player_max_dist_sqr )
|
|
{
|
|
player_copter_right = AnglesToRight( main_target.angles );
|
|
player_to_apc = VectorNormalize( self.origin - main_target.origin );
|
|
dot = VectorDot( player_copter_right, player_to_apc );
|
|
//println( "APC dot: " + dot );
|
|
if ( dot > self.kill_player_fov_cos )
|
|
{
|
|
tag_flash = self GetTagOrigin( "tag_flash" );
|
|
bullet_trace = BulletTracePassed( tag_flash, level._player GetEye(), false, self );
|
|
if ( bullet_trace )
|
|
{
|
|
// Player should see APC, start counting time_in_kill_player_range
|
|
time_in_kill_player_range += 0.5;
|
|
//Println( "APC KILL COUNTDOWN: " + time_in_kill_player_range );
|
|
}
|
|
else
|
|
{
|
|
//println( "Bullet Trace FAILED" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
time_in_kill_player_range = 0.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
time_in_kill_player_range = 0.0;
|
|
if ( killing_player )
|
|
{
|
|
killing_player = false;
|
|
self SetVehWeapon( "nx_btr80_rocket_turret" );
|
|
//iPrintLn( "APC Killing player CLEARED" );
|
|
}
|
|
}
|
|
|
|
if ( time_in_kill_player_range >= self.kill_player_time )
|
|
{
|
|
// Kill the player
|
|
//iPrintLn( "APC Killing player SET" );
|
|
//self SetVehWeapon( "btr80_turret" );
|
|
self SetTurretTargetEnt( level._player );
|
|
killing_player = true;
|
|
self.accuracy = self.accuracy + 0.2;
|
|
if ( isdefined ( self.mgturret [ 0 ] ))
|
|
{
|
|
self.mgturret [ 0 ] SetAISpread ( 0.1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Don't kill the player
|
|
dist_sqr_to_best_other = dist_sqr_to_main;
|
|
|
|
best_other = undefined;
|
|
foreach( other_target in other_targets )
|
|
{
|
|
if ( !isAlive( other_target ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
dist_sqr_to_other = DistanceSquared( other_target.origin, self.origin );
|
|
if ( dist_sqr_to_other < dist_sqr_to_best_other )
|
|
{
|
|
best_other = other_target;
|
|
dist_sqr_to_best_other = dist_sqr_to_other;
|
|
}
|
|
}
|
|
|
|
// Fire at the other target if it is closer than the player and in front of the player
|
|
target = level._player;
|
|
if ( isDefined( best_other ) && dist_sqr_to_best_other < dist_sqr_to_main && within_fov( level._player GetEye(), level._player.angles, best_other.origin, 90 ) )
|
|
{
|
|
target = best_other;
|
|
}
|
|
|
|
self SetTurretTargetEnt( target );
|
|
|
|
// Show target debug
|
|
//line( self.origin, target.origin, (1,0,0) );
|
|
}
|
|
|
|
wait 0.5;
|
|
}
|
|
}
|
|
|
|
update_fake_spread( target )
|
|
{
|
|
self endon( "death" );
|
|
target endon( "death" );
|
|
|
|
self notify( "stop_update_fake_spread" );
|
|
self endon( "stop_update_fake_spread" );
|
|
|
|
dummy_target = self.dummy_target;
|
|
dummy_target Unlink();
|
|
min_miss_dist_sqr = 512 * 512;
|
|
|
|
while ( 1 )
|
|
{
|
|
accuracy_test = RandomFloat( 1.0 );
|
|
dist_sqr = DistanceSquared( target.origin, self.origin );
|
|
|
|
// This looks bad at short distances, so never miss if we're close.
|
|
if ( dist_sqr < min_miss_dist_sqr || accuracy_test < self.accuracy )
|
|
{
|
|
// Hit
|
|
self SetTurretTargetEnt( target );
|
|
}
|
|
else
|
|
{
|
|
// Miss!
|
|
offset = ( RandomFloatRange( 100, 200 ), RandomFloatRange( 100, 200 ), RandomFloatRange( 100, 200 ) );
|
|
dummy_target LinkTo( target, undefined, offset, target.angles );
|
|
//box( target.origin + offset, 16, target.angles[1], (1,0,0), 1, 1, 5 );
|
|
self SetTurretTargetEnt( dummy_target );
|
|
}
|
|
wait .3;
|
|
}
|
|
}
|
|
|
|
// Blockout spawning script for groups of enemies
|
|
spawn_guys_from_targetname( targetname )
|
|
{
|
|
new_guys = [];
|
|
guys = getentarray( targetname, "targetname" );
|
|
foreach ( guy in guys )
|
|
{
|
|
if( IsDefined( guy.script_drone ) && guy.script_drone == 1 )
|
|
{
|
|
new_guy = dronespawn( guy );
|
|
new_guys[ new_guys.size ] = new_guy;
|
|
}
|
|
else
|
|
{
|
|
new_guy = guy stalingradSpawn();
|
|
if ( spawn_failed( new_guy ) )
|
|
{
|
|
//iprintlnbold( "force_spawn_guys failed" );
|
|
continue;
|
|
}
|
|
new_guys[ new_guys.size ] = new_guy;
|
|
}
|
|
}
|
|
return new_guys;
|
|
}
|
|
|
|
|
|
// Safely delete an object
|
|
safe_delete( object )
|
|
{
|
|
if( isDefined( object ))
|
|
{
|
|
object delete();
|
|
}
|
|
}
|
|
|
|
// Safely deletes a bunch of objects
|
|
safe_delete_array( array )
|
|
{
|
|
foreach( object in array )
|
|
{
|
|
safe_delete( object );
|
|
}
|
|
}
|
|
|
|
spawn_ai_group( spawner_value, spawner_key )
|
|
{
|
|
ai_array = [];
|
|
foreach( spawner in GetEntArray( spawner_value, spawner_key ) )
|
|
{
|
|
ai = spawner spawn_ai();
|
|
ai_array[ ai_array.size ] = ai;
|
|
wait 0.25;
|
|
}
|
|
|
|
return ai_array;
|
|
}
|
|
|
|
|
|
// Copied from dcburning.gsc
|
|
// Spawns and endless stream of drones a random interval apart
|
|
// Be sure to set "script_noteworthy = delete_on_goal" on the spawners
|
|
drone_flood_start( aSpawners, groupName, r1, r2, immediate )
|
|
{
|
|
level endon( "stop_drone_flood" + groupName );
|
|
|
|
if( isDefined( immediate ))
|
|
{
|
|
foreach( spawner in aSpawners )
|
|
{
|
|
dronespawn( spawner );
|
|
}
|
|
}
|
|
|
|
while( true )
|
|
{
|
|
foreach( spawner in aSpawners )
|
|
{
|
|
delaythread( randomfloatrange( r1, r2 ), ::dronespawn, spawner );
|
|
}
|
|
wait( randomfloatrange( r1, r2 ) );
|
|
}
|
|
}
|
|
|
|
drone_flood_stop( groupName )
|
|
{
|
|
level notify( "stop_drone_flood" + groupName );
|
|
}
|
|
|
|
// Delays a thread untill a specific notify occurs
|
|
delayThreadNotify( event, func, param1, param2, param3 )
|
|
{
|
|
self waittill( event );
|
|
if ( !IsDefined( param1 ) )
|
|
{
|
|
assertex( !isdefined( param2 ), "delayThreadNotify does not support vars after undefined." );
|
|
assertex( !isdefined( param3 ), "delayThreadNotify does not support vars after undefined." );
|
|
thread [[ func ]]();
|
|
}
|
|
else
|
|
if ( !IsDefined( param2 ) )
|
|
{
|
|
assertex( !isdefined( param3 ), "delayThreadNotify does not support vars after undefined." );
|
|
thread [[ func ]]( param1 );
|
|
}
|
|
else
|
|
if ( !IsDefined( param3 ) )
|
|
{
|
|
thread [[ func ]]( param1, param2 );
|
|
}
|
|
else
|
|
{
|
|
thread [[ func ]]( param1, param2, param3 );
|
|
}
|
|
}
|
|
|
|
|
|
delete_objects_on_notify( event, objects )
|
|
{
|
|
//iprintln( "waiting" );
|
|
self waittill( event );
|
|
//iprintln( "delete objects on notify" );
|
|
safe_delete_array( objects );
|
|
}
|
|
|
|
set_goal_volume_array( actors, volume_targetname )
|
|
{
|
|
foreach( actor in actors )
|
|
{
|
|
actor thread set_goal_volume( volume_targetname );
|
|
}
|
|
}
|
|
|
|
set_goal_volume( volume_targetname )
|
|
{
|
|
goal_volume = GetEnt( volume_targetname, "targetname" );
|
|
|
|
self.goalheight = 80;
|
|
self.fixednode = false;
|
|
|
|
self ClearGoalVolume();
|
|
self SetGoalPos( goal_volume.origin );
|
|
self waittill( "goal" );
|
|
self SetGoalVolume( goal_volume );
|
|
self.goalradius = 2000;
|
|
}
|
|
|
|
|
|
// Helper script for timing dialogue
|
|
wait_play_dialogue_wait( wait_in, dialogue1, wait_out, flag )
|
|
{
|
|
wait( wait_in );
|
|
|
|
radio_dialogue( dialogue1 );
|
|
|
|
if( isDefined( flag ))
|
|
{
|
|
flag_set( flag );
|
|
}
|
|
|
|
if( isDefined( wait_out ))
|
|
{
|
|
wait( wait_out );
|
|
}
|
|
}
|
|
|
|
|
|
// Nags the player to fire the railgun
|
|
nag_for_fire_railgun( event )
|
|
{
|
|
level endon( event );
|
|
while( 1 )
|
|
{
|
|
wait RandomIntRange( 8, 12 );
|
|
|
|
if( cointoss() )
|
|
{
|
|
maps\nx_rocket_util::wait_play_dialogue_wait( 0, "roc_bak_alpha_paintrocket" );
|
|
}
|
|
else
|
|
{
|
|
maps\nx_rocket_util::wait_play_dialogue_wait( 0, "roc_bak_alpha_painttargetnow" );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*******************************************************************
|
|
// OBJECTIVES *
|
|
// *
|
|
//*******************************************************************
|
|
add_objective( objective_name )
|
|
{
|
|
if( !IsDefined( level._mission_objective ) )
|
|
level._mission_objective = [];
|
|
|
|
level._mission_objective[ objective_name ] = level._mission_objective.size;
|
|
}
|
|
|
|
get_objective( objective_name )
|
|
{
|
|
return level._mission_objective[ objective_name ];
|
|
}
|
|
|
|
//*******************************************************************
|
|
// SQUAD *
|
|
// *
|
|
//*******************************************************************
|
|
squad_teleport( teleport_info )
|
|
{
|
|
// teleport_info should be an array with entries that follow the form:
|
|
// teleport_info[ "ALLY_NAME" ] = "SCRIPT_ORIGIN_NOTEWORTHY";
|
|
// ALLY_NAME should match one of the keys in level.squad (see nx_rocket.gsc)
|
|
|
|
foreach( ally_name, origin_noteworthy in teleport_info )
|
|
{
|
|
ally = level.squad[ ally_name ];
|
|
|
|
origin = GetEnt( origin_noteworthy, "script_noteworthy" );
|
|
|
|
ally ForceTeleport( origin.origin, origin.angles );
|
|
}
|
|
}
|
|
|
|
squad_ally( spawner_script_noteworthy, animname, color )
|
|
{
|
|
spawner = GetEnt( spawner_script_noteworthy, "script_noteworthy" );
|
|
ai = spawner spawn_ai( true );
|
|
|
|
ai thread magic_bullet_shield();
|
|
ai.animname = animname;
|
|
ai.ai_color = color;
|
|
ai ai_color_reset();
|
|
|
|
return ai;
|
|
}
|
|
|
|
squad_color_reset()
|
|
{
|
|
ai_array_color_reset( level.squad );
|
|
}
|
|
|
|
//*******************************************************************
|
|
// AI *
|
|
// *
|
|
//*******************************************************************
|
|
ai_color_reset( color )
|
|
{
|
|
if( !IsDefined( color ) )
|
|
{
|
|
if( IsDefined( self.ai_color ) )
|
|
color = self.ai_color;
|
|
}
|
|
|
|
if( IsDefined( color ) )
|
|
self set_force_color( color );
|
|
}
|
|
|
|
ai_array_color_reset( ai_array, color )
|
|
{
|
|
foreach( ai in ai_array )
|
|
{
|
|
ai ai_color_reset( color );
|
|
}
|
|
}
|
|
|
|
// The AI will run to their goal node, then become aggresive
|
|
// Do this:
|
|
// array_spawn_function_targetname( "base_alpha_roof_runners_1", ::run_to_goal_then_aggro );
|
|
run_to_goal_then_aggro()
|
|
{
|
|
//self.script_forcegoal = true;
|
|
//self.ignoreall = true;
|
|
|
|
self waittill( "goal" );
|
|
self.ignoreall = false;
|
|
}
|
|
|
|
|
|
//*******************************************************************
|
|
// HELICOPTER *
|
|
// *
|
|
//*******************************************************************
|
|
heli_shoots_rockets_at_ent( target )
|
|
{
|
|
attractor = missile_createAttractorEnt( target, 100000, 60000 );
|
|
self maps\_helicopter_globals::fire_missile( "mi28_seeker", 3, target, .75 );
|
|
wait( 5 );
|
|
missile_deleteAttractor( attractor );
|
|
}
|
|
|
|
// Changes the spread on allied choppers turrets
|
|
// This effects their accuracy
|
|
// Default 2
|
|
set_ally_chopper_spread( spread )
|
|
{
|
|
foreach ( turret in self.mgturret )
|
|
{
|
|
turret SetAISpread( spread ); // Default is 2
|
|
}
|
|
}
|
|
|
|
heli_start_path( path_value, path_key )
|
|
{
|
|
// Get rid of old path
|
|
self thread vehicle_detachfrompath();
|
|
|
|
// Get the new path
|
|
transition_node = getstruct( path_value, path_key );
|
|
|
|
// Use new patch
|
|
self.currentnode = transition_node;
|
|
|
|
//iprintln( "new path go" );
|
|
|
|
// Continue on new path
|
|
self thread vehicle_resumepath();
|
|
self GoPath();
|
|
}
|
|
|
|
// Moves a chopper from one path to another
|
|
transition_chopper_to_new_path( new_path_start )
|
|
{
|
|
AssertEx( maps\_vehicle::ishelicopter(), "Called transition_chopper_to_new_path, but self isnt a chopper" );
|
|
|
|
self thread vehicle_detachfrompath();
|
|
self notify( "newpath" );
|
|
transition_node = getstruct( new_path_start, "targetname" );
|
|
|
|
self.currentnode = transition_node;
|
|
self thread vehicle_resumepath();
|
|
self thread GoPath();
|
|
}
|
|
|
|
// Moves a chopper from one path to another
|
|
transition_chopper_to_new_path_noteworthy( new_path_start )
|
|
{
|
|
AssertEx( maps\_vehicle::ishelicopter(), "Called transition_chopper_to_new_path, but self isnt a chopper" );
|
|
|
|
self thread vehicle_detachfrompath();
|
|
self notify( "newpath" );
|
|
transition_node = getstruct( new_path_start, "script_noteworthy" );
|
|
|
|
self.currentnode = transition_node;
|
|
self thread vehicle_resumepath();
|
|
self thread GoPath();
|
|
}
|
|
|
|
|
|
// Low powered earthquake used to simulate chopper rumble
|
|
slightly_vibrate_camera()
|
|
{
|
|
level endon( "end_camera_vibrate" );
|
|
for( ;; )
|
|
{
|
|
Earthquake( 0.05, 60, level._player.origin, 0 );
|
|
wait 5;
|
|
}
|
|
}
|
|
|
|
|
|
slightly_vibrate_camera_end()
|
|
{
|
|
level notify( "end_camera_vibrate" );
|
|
|
|
// HACK!
|
|
// In order to clear out the long duration earthquakes in slightly_vibrate_camera(),
|
|
// use four short duration earthquakes that are slightly stronger.
|
|
// This works because the game only remembers the four largest earthquakes (MAX_CAMERA_SHAKE == 4).
|
|
Earthquake( 0.06, 0.05, level._player.origin, 0 );
|
|
Earthquake( 0.06, 0.05, level._player.origin, 0 );
|
|
Earthquake( 0.06, 0.05, level._player.origin, 0 );
|
|
Earthquake( 0.06, 0.05, level._player.origin, 0 );
|
|
}
|
|
|
|
/#
|
|
// Debug helper
|
|
draw_chopper_name( text )
|
|
{
|
|
self endon( "death" );
|
|
while ( true )
|
|
{
|
|
Print3D( self.origin, text );
|
|
//println( self GetEntNum() );
|
|
wait 0.05;
|
|
}
|
|
}
|
|
#/
|
|
|
|
// Displays a 3d hint text untill the specified notify is hit
|
|
display_hint_until_notify( text, location, event )
|
|
{
|
|
level endon( event );
|
|
|
|
for( ;; )
|
|
{
|
|
Print3d( location.origin, text, (1,1,1), 1, 1, 1 );
|
|
wait(0.05);
|
|
}
|
|
}
|
|
|
|
dialogue_nag_temp( actor, line, display_time, wait_min, wait_max, end_on )
|
|
{
|
|
level endon( end_on );
|
|
|
|
while( 1 )
|
|
{
|
|
if( flag(end_on) )
|
|
return;
|
|
|
|
level thread add_dialogue_line( actor, line, undefined, display_time );
|
|
wait display_time;
|
|
wait RandomFloatRange( wait_min, wait_max );
|
|
}
|
|
}
|
|
|
|
dialogue_nag( line, wait_min, wait_max, end_on )
|
|
{
|
|
level endon( end_on );
|
|
|
|
while( 1 )
|
|
{
|
|
if( flag(end_on) )
|
|
return;
|
|
|
|
wait_play_dialogue_wait(0, line );
|
|
wait RandomFloatRange( wait_min, wait_max );
|
|
}
|
|
}
|
|
|
|
aa_turret_fire( target, hit_offset )
|
|
{
|
|
if( !IsDefined( hit_offset ) )
|
|
hit_offset = (0, 0, 0);
|
|
|
|
MagicBullet( "nx_rocket_aa_turret", self.origin, target.origin + hit_offset );
|
|
|
|
angles_to_target = VectorToAngles( target.origin - self.origin );
|
|
|
|
fx_forward = AnglesToForward( angles_to_target );
|
|
fx_up = AnglesToUp( angles_to_target );
|
|
fx_org = self.origin;
|
|
playfx( level._effect[ "nx_rocket_aa_flash_view" ], fx_org, fx_forward, fx_up );
|
|
self stopsounds();
|
|
}
|
|
|
|
track_anim_speed()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "end_track_anim_velocity" );
|
|
|
|
speed = 0;
|
|
while ( true )
|
|
{
|
|
prev_origin = self.origin;
|
|
wait 0.05;
|
|
self.anim_speed = speed; // track previous frame's speed, as all anims seem to have one frame of reduced velocity at their end
|
|
speed = Length( ( self.origin - prev_origin ) / 0.05 );
|
|
}
|
|
}
|
|
|
|
rescue_chopper_setup( chopper_value, chopper_key )
|
|
{
|
|
chopper = vehicle_spawn( GetEnt( chopper_value, chopper_key ) );
|
|
|
|
chopper rescue_chopper_player_setup();
|
|
chopper rescue_chopper_allies_setup();
|
|
|
|
chopper thread godon();
|
|
chopper SetMaxPitchRoll( 10, 10 );
|
|
|
|
chopper GoPath();
|
|
|
|
return chopper;
|
|
}
|
|
|
|
rescue_chopper_allies_setup()
|
|
{
|
|
level.squad[ "ALLY_WILLIAMS" ].script_startingposition = 7;
|
|
level.squad[ "ALLY_JENKINS" ].script_startingposition = 2;
|
|
level.squad[ "ALLY_BAKER" ].script_startingposition = 3;
|
|
|
|
foreach( guy in level.squad )
|
|
{
|
|
self guy_enter_vehicle( guy );
|
|
}
|
|
}
|
|
|
|
rescue_chopper_player_setup()
|
|
{
|
|
player_tag = spawn_tag_origin();
|
|
tag_name = "tag_guy2";
|
|
player_tag.angles = self GetTagAngles( tag_name );
|
|
player_tag_forward = AnglesToForward( player_tag.angles );
|
|
player_tag_offset = player_tag_forward * 30 + (0, 0, -25);
|
|
player_tag.origin = self GetTagOrigin( tag_name ) + player_tag_offset;
|
|
|
|
level thread draw_line_for_time( player_tag.origin, player_tag.origin + player_tag_offset, 1, 1, 1, 10 );
|
|
|
|
level._player SetOrigin( player_tag.origin );
|
|
level._player SetPlayerAngles( player_tag.angles );
|
|
level._player PlayerLinkToDelta( player_tag, "tag_origin", 1, 90, 90, 35, 100, true );
|
|
|
|
player_tag LinkTo( self, tag_name );
|
|
}
|
|
|
|
player_prevent_damage_from_behind_until_flag( flag_name )
|
|
{
|
|
// Dan: While close to working, this script does not work
|
|
// because previous_normal_health does not know about
|
|
// any regeneration which may have occured since the last
|
|
// damage event. Disabling for now. Justin has said it is
|
|
// OK for this to be changed so that actors which are out of
|
|
// view have very low accuracy.
|
|
//
|
|
// Also, Justin has said that he would like this to not be
|
|
// based directly on the player's view, but rather the
|
|
// general facing of the helicopter. (So the player can not
|
|
// look away from enemies to get them to miss.)
|
|
|
|
|
|
/*
|
|
self endon( "death" );
|
|
self endon( flag_name );
|
|
|
|
while ( 1 )
|
|
{
|
|
previous_normal_health = level._player GetNormalHealth();
|
|
self waittill( "damage", damage, attacker, direction_vec );
|
|
|
|
playerangles = level._player GetPlayerAngles();
|
|
player_forward = AnglesToForward( playerangles );
|
|
anglesFromPlayer = VectorToAngles( direction_vec );
|
|
forward_to_self = AnglesToForward( anglesFromPlayer );
|
|
|
|
dot = vectordot( player_forward, forward_to_self );
|
|
//iPrintln( "Direction_vec: " + direction_vec + " dot: " + dot );
|
|
|
|
// Heal health from behind
|
|
if ( dot > 0.2 )
|
|
{
|
|
level._player SetNormalHealth( previous_normal_health );
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
// Let the player take damage but not die
|
|
heli_god_mode( end_notify )
|
|
{
|
|
self endon( end_notify );
|
|
|
|
while( true )
|
|
{
|
|
self waittill( "damage", damage, attacker, direction_vec, point, damageType, modelName, tagName );
|
|
|
|
//iprintln( "Dmg: " + damage + " from " + attacker.className );
|
|
|
|
normal_health = level._player GetNormalHealth();
|
|
if ( normal_health < 0.02 )
|
|
{
|
|
level._player SetNormalHealth( 0.02 );
|
|
}
|
|
|
|
// Dan: Note that this wait opens a window in which the player can die.
|
|
//wait 0.05;
|
|
}
|
|
}
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
CINEMATIC_LINK_VIEW_FRACTION = 0.9;
|
|
GAMEPLAY_LINK_VIEW_FRACTION = 0.1;
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
set_link_view_fraction_cinematic( lerp_duration )
|
|
{
|
|
if ( !IsDefined( lerp_duration ) )
|
|
{
|
|
lerp_duration = 0;
|
|
}
|
|
level._player LerpLinkViewFraction( CINEMATIC_LINK_VIEW_FRACTION, lerp_duration );
|
|
}
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
set_link_view_fraction_gameplay( lerp_duration )
|
|
{
|
|
if ( !IsDefined( lerp_duration ) )
|
|
{
|
|
lerp_duration = 0;
|
|
}
|
|
level._player LerpLinkViewFraction( GAMEPLAY_LINK_VIEW_FRACTION, lerp_duration );
|
|
}
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
lerp_link_view_fraction_cinematic_trigger()
|
|
{
|
|
lerp_link_view_fraction_trigger( CINEMATIC_LINK_VIEW_FRACTION );
|
|
}
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
lerp_link_view_fraction_gameplay_trigger()
|
|
{
|
|
lerp_link_view_fraction_trigger( GAMEPLAY_LINK_VIEW_FRACTION );
|
|
}
|
|
|
|
//*******************************************************************
|
|
// *
|
|
// *
|
|
//*******************************************************************
|
|
lerp_link_view_fraction_trigger( view_fraction )
|
|
{
|
|
self waittill( "trigger", ent );
|
|
assert( IsPlayer( ent ) );
|
|
|
|
level._player LerpLinkViewFraction( view_fraction, 3 );
|
|
//IPrintLnBold( "level._player LerpLinkViewFraction( " + view_fraction + ", 3 );");
|
|
|
|
// exit; trigger only works once
|
|
|
|
count = 3 / 0.05;
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
//IPrintLn( "lerping to " + view_fraction );
|
|
wait 0.05;
|
|
}
|
|
//IPrintLnBold( "Done!");
|
|
}
|
|
|
|
player_ledge_walk( trigger )
|
|
{
|
|
self endon( "end_ledge" );
|
|
|
|
curr_node = undefined;
|
|
dest_node = undefined;
|
|
|
|
if( IsDefined( trigger.target ) )
|
|
{
|
|
curr_node = GetEnt( trigger.target, "targetname" );
|
|
}
|
|
|
|
move_speed = 20.0; // units per second
|
|
interval = 0.05;
|
|
|
|
mover = spawn_tag_origin();
|
|
// mover.origin = curr_node.origin;
|
|
// mover.angles = curr_node.angles;
|
|
|
|
while( 1 )
|
|
{
|
|
flag_wait( trigger.script_flag );
|
|
self SetMoveSpeedScale( 0.3 );
|
|
self HideViewModel();
|
|
self DisableWeapons();
|
|
|
|
mover.origin = self.origin;
|
|
mover.angles = self.angles;
|
|
self PlayerLinkToDelta( mover, "tag_origin", 1.0, 45, 45, 15, 60, true );
|
|
|
|
mover RotateTo( curr_node.angles, 0.65 );
|
|
mover waittill( "rotatedone" );
|
|
|
|
while( flag( trigger.script_flag ) )
|
|
{
|
|
if( DistanceSquared( mover.origin, curr_node.origin ) <= curr_node.radius * curr_node.radius )
|
|
{
|
|
if( IsDefined( curr_node.target ) )
|
|
curr_node = GetEnt( curr_node.target, "targetname" );
|
|
else
|
|
break;
|
|
}
|
|
|
|
dest_org = curr_node.origin - mover.origin;
|
|
dest_angles = curr_node.angles - mover.angles;
|
|
|
|
movement_scale = self GetNormalizedMovement();
|
|
|
|
dir = VectorNormalize( dest_org);
|
|
|
|
velocity = dir * movement_scale[ 1 ] * move_speed;
|
|
|
|
mover.origin += velocity * interval;
|
|
// mover.angles += dest_angles * interval * movement_scale[ 1 ];
|
|
|
|
wait interval;
|
|
}
|
|
|
|
self SetMoveSpeedScale( 1.0 );
|
|
self ShowViewModel();
|
|
self Enableweapons();
|
|
self Unlink();
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
trigger_waittill_use( hint_text )
|
|
{
|
|
self trigger_on();
|
|
self SetHintString( hint_text );
|
|
self waittill( "trigger" );
|
|
self trigger_off();
|
|
}
|
|
|
|
ignore_until_damage()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.ignoreAll = true;
|
|
self.ignoreMe = true;
|
|
|
|
self waittill( "damage" );
|
|
|
|
self.ignoreAll = false;
|
|
self.ignoreMe = false;
|
|
}
|
|
|
|
ignore_until_damage_group( team )
|
|
{
|
|
self.ignoreAll = true;
|
|
self.ignoreMe = true;
|
|
|
|
self waittill( "damage" );
|
|
|
|
guys = array_removedead( team );
|
|
|
|
foreach( guy in guys )
|
|
{
|
|
guy.ignoreAll = false;
|
|
guy.ignoreMe = false;
|
|
}
|
|
}
|
|
|
|
ignore_until_flag( flag_name )
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.ignoreAll = true;
|
|
self.ignoreMe = true;
|
|
|
|
flag_wait( flag_name );
|
|
|
|
self.ignoreAll = false;
|
|
self.ignoreMe = false;
|
|
}
|
|
|
|
vehicle_enable_fire( enable )
|
|
{
|
|
foreach( turret in self.mgturret )
|
|
{
|
|
if( enable )
|
|
turret TurretFireEnable();
|
|
else
|
|
turret TurretFireDisable();
|
|
}
|
|
}
|
|
|
|
vehicle_search_ents( ents, end_on )
|
|
{
|
|
if( IsDefined( end_on ) )
|
|
{
|
|
self endon( end_on );
|
|
level endon( end_on );
|
|
}
|
|
|
|
self endon( "death" );
|
|
|
|
while( 1 )
|
|
{
|
|
self SetTurretTargetEnt( random( ents ) );
|
|
wait RandomFloatRange( 1.0, 3.0 );
|
|
}
|
|
}
|
|
|
|
vehicle_firing( fire_min, fire_max, hold_min, hold_max, end_on )
|
|
{
|
|
if( IsDefined( end_on ) )
|
|
{
|
|
self endon( end_on );
|
|
level endon( end_on );
|
|
}
|
|
|
|
self endon( "death" );
|
|
|
|
enable = false;
|
|
|
|
while( 1 )
|
|
{
|
|
enable = !enable;
|
|
self maps\nx_rocket_util::vehicle_enable_fire( enable );
|
|
if(enable)
|
|
wait RandomFloatRange( fire_min, fire_max );
|
|
else
|
|
wait RandomFloatRange( hold_min, hold_max );
|
|
}
|
|
}
|
|
|
|
VIEW_DOT = 0.25; //Goes from 0-1, smaller numbers mean larger fov.
|
|
//called on an actor.
|
|
protect_player_helicopter_rear()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.oldbaseaccuracy = self.baseAccuracy;
|
|
|
|
while( true )
|
|
{
|
|
if( !IsDefined( level.playerHeli ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//The player is in the right bay door, so we use Angles to Right. Then see if the actor's position puts them too
|
|
//far behind. If it does, then set the accuracy low.
|
|
if( vectordot(self.origin - level.playerHeli.origin, AnglesToRight( level.playerHeli.angles )) > VIEW_DOT ) //actor "in view".
|
|
{
|
|
self.baseAccuracy = self.oldbaseaccuracy;
|
|
///#debug_draw_origin( self.origin, true);#/
|
|
}
|
|
else
|
|
{
|
|
self.baseAccuracy = 0;
|
|
///#debug_draw_origin( self.origin, false);#/
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
//called on a vehicle.
|
|
protect_player_helicopter_rear_from_vehicle()
|
|
{
|
|
self endon( "death" );
|
|
|
|
//bail if the vehicle doesn't have a turret so we can call this on vehicles blindly.
|
|
if( !IsDefined( self.mgturret ) || self.mgturret.size < 1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
old_accuracy = [];
|
|
|
|
//some have multiple turrets, so grab each one.
|
|
for ( i = 0; i < self.mgturret.size; i++ )
|
|
{
|
|
old_accuracy[i] = self.mgturret[i].accuracy;
|
|
}
|
|
|
|
while( true )
|
|
{
|
|
if( !IsDefined( level.playerHeli ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//The player is in the right bay door, so we use Angles to Right. Then see if the actor's position puts them too
|
|
//far behind. If it does, then set the accuracy low.
|
|
if( vectordot(self.origin - level.playerHeli.origin, AnglesToRight( level.playerHeli.angles )) > VIEW_DOT ) //actor "in view".
|
|
{
|
|
for ( i = 0; i < self.mgturret.size; i++ )
|
|
{
|
|
self.mgturret[ i ].accuracy = old_accuracy[i];
|
|
}
|
|
///#debug_draw_origin( self.origin, true);#/
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < self.mgturret.size; i++ )
|
|
{
|
|
self.mgturret[ i ].accuracy = 0;
|
|
}
|
|
///#debug_draw_origin( self.origin, false);#/
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
protect_player_helicopter_rear_from_each_vehicle( vehicles )
|
|
{
|
|
//to make this as unlikely to fail as possible, check for the case where what's returned is a single item and not an array.
|
|
if( IsArray( vehicles ) )
|
|
{
|
|
foreach ( vehicle in vehicles )
|
|
{
|
|
vehicle thread protect_player_helicopter_rear_from_vehicle();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vehicles thread protect_player_helicopter_rear_from_vehicle();
|
|
}
|
|
}
|
|
|
|
/#
|
|
debug_draw_origin( origin, on )
|
|
{
|
|
draw_color = ( 1, 0, 0 );
|
|
if( on )
|
|
{
|
|
draw_color = ( 0, 1, 0 );
|
|
}
|
|
|
|
Line( origin + ( 16, 0, 0 ), origin + ( -16, 0, 0 ), draw_color, 1, 0, 1 );
|
|
Line( origin + ( 0, 16, 0 ), origin + ( 0, -16, 0 ), draw_color, 1, 0, 1 );
|
|
Line( origin + ( 0, 0, 16 ), origin + ( 0, 0, -16 ), draw_color, 1, 0, 1 );
|
|
}
|
|
#/
|
|
|
|
// FLASHLIGHT ON GUN
|
|
attach_flashlight_gun( state )
|
|
{
|
|
effect_id = level._effect[ "flashlight" ];
|
|
effect_tag = "tag_flash";
|
|
|
|
if( state )
|
|
{
|
|
PlayFXOnTag( effect_id, self, "tag_flash" );
|
|
self thread detach_flashlight_gun_on_death();
|
|
}
|
|
else
|
|
{
|
|
StopFXOnTag( effect_id, self, "tag_flash" );
|
|
}
|
|
|
|
self.have_flashlight = state;
|
|
}
|
|
|
|
detach_flashlight_gun()
|
|
{
|
|
self attach_flashlight_gun( false );
|
|
}
|
|
|
|
detach_flashlight_gun_on_death()
|
|
{
|
|
self waittill( "death" );
|
|
self detach_flashlight_gun();
|
|
}
|
|
|
|
// FLASHLIGHT IN HAND
|
|
attach_flashlight( state )
|
|
{
|
|
self attach( "com_flashlight_on", "tag_inhand", true );
|
|
self.have_flashlight = true;
|
|
self flashlight_light( state );
|
|
self thread detach_flashlight_on_death();
|
|
}
|
|
|
|
detach_flashlight_on_death()
|
|
{
|
|
self waittill( "death" );
|
|
if ( isdefined( self ) )
|
|
self detach_flashlight();
|
|
}
|
|
|
|
detach_flashlight()
|
|
{
|
|
if ( !isdefined( self.have_flashlight ) )
|
|
return;
|
|
self detach( "com_flashlight_on", "tag_inhand" );
|
|
self flashlight_light( false );
|
|
self.have_flashlight = undefined;
|
|
}
|
|
|
|
flashlight_light( state )
|
|
{
|
|
flash_light_tag = "tag_light";
|
|
|
|
if ( state )
|
|
{
|
|
flashlight_fx_ent = spawn( "script_model", ( 0, 0, 0 ) );
|
|
flashlight_fx_ent setmodel( "tag_origin" );
|
|
flashlight_fx_ent hide();
|
|
flashlight_fx_ent linkto( self, flash_light_tag, ( 0, 0, 0 ), ( 0, 0, 0 ) );
|
|
|
|
self thread flashlight_light_death( flashlight_fx_ent );
|
|
playfxontag( level._effect[ "flashlight" ], flashlight_fx_ent, "tag_origin" );
|
|
}
|
|
else if ( isdefined( self.have_flashlight ) )
|
|
self notify( "flashlight_off" );
|
|
}
|
|
|
|
flashlight_light_death( flashlight_fx_ent )
|
|
{
|
|
self waittill_either( "death", "flashlight_off" );
|
|
|
|
flashlight_fx_ent delete();
|
|
self.have_flashlight = undefined;
|
|
|
|
}
|
|
|
|
caravan_setup( caravan_targetname, end_flag )
|
|
{
|
|
caravan = [];
|
|
for ( i = 1 ;; i++)
|
|
{
|
|
targetname_concatenated = caravan_targetname + i;
|
|
vehicle_spawner = GetEnt( targetname_concatenated , "targetname");
|
|
if ( !isdefined( vehicle_spawner ) )
|
|
break;
|
|
vehicle = spawn_vehicle_from_targetname_and_drive ( targetname_concatenated );
|
|
caravan [caravan.size] = vehicle;
|
|
// lag mitigator, so they don't all spawn on the same frame
|
|
wait .1;
|
|
}
|
|
protect_player_helicopter_rear_from_each_vehicle( caravan );
|
|
level thread handle_caravan_stopping_2( caravan, end_flag );
|
|
return caravan;
|
|
}
|
|
|
|
get_my_index( caravan )
|
|
{
|
|
foreach ( index, vehicle in caravan )
|
|
{
|
|
if ( vehicle == self )
|
|
break;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
handle_caravan_stopping_2( caravan, end_flag )
|
|
{
|
|
level endon( end_flag );
|
|
|
|
while ( 1 )
|
|
{
|
|
foreach( vehicle in caravan )
|
|
{
|
|
healthbuffer = 0;
|
|
if ( isDefined( vehicle.healthbuffer ) )
|
|
{
|
|
healthbuffer = vehicle.healthbuffer;
|
|
}
|
|
|
|
if ( !isAlive( vehicle ) || vehicle.health - healthbuffer <= 1 )
|
|
{
|
|
|
|
if ( isdefined (vehicle) )
|
|
{
|
|
dead_index = vehicle get_my_index ( caravan );
|
|
foreach ( remaining_vehicle in caravan )
|
|
{
|
|
living_index = remaining_vehicle get_my_index ( caravan );
|
|
if ( living_index > dead_index )
|
|
{
|
|
remaining_vehicle thread stop_caravan_vehicle ( );
|
|
}
|
|
}
|
|
if( vehicle Vehicle_IsPhysVeh())
|
|
{
|
|
vehicle VehPhys_Crash ();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
handle_caravan_stopping( vehicles, end_flag )
|
|
{
|
|
level endon( end_flag );
|
|
while ( 1 )
|
|
{
|
|
foreach( vehicle in vehicles )
|
|
{
|
|
healthbuffer = 0;
|
|
if ( isDefined( vehicle.healthbuffer ) )
|
|
{
|
|
healthbuffer = vehicle.healthbuffer;
|
|
}
|
|
|
|
if ( !isAlive( vehicle ) || vehicle.health - healthbuffer <= 1 )
|
|
{
|
|
|
|
if ( isdefined (vehicle) && vehicle Vehicle_IsPhysVeh() )
|
|
{
|
|
// speed = vehicle Vehicle_GetSpeed ( );
|
|
// vehicle VehPhys_Launch( (0,4,4), 0.7 );
|
|
vehicle VehPhys_Crash ();
|
|
}
|
|
|
|
// Stop caravan
|
|
stop_caravan( vehicles );
|
|
return;
|
|
}
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
stop_caravan( vehicles )
|
|
{
|
|
foreach ( vehicle in vehicles )
|
|
{
|
|
if ( isAlive( vehicle ) )
|
|
{
|
|
vehicle delayThread( RandomFloatRange( 0.0, 0.2 ), ::stop_caravan_vehicle );
|
|
}
|
|
}
|
|
}
|
|
|
|
stop_caravan_vehicle()
|
|
{
|
|
self endon( "death" );
|
|
self Vehicle_SetSpeed( 0.0, RandomFloatRange( 55.0, 75.0 ) );
|
|
wait .3;
|
|
self vehicle_unload();
|
|
|
|
}
|
|
|
|
vehicle_follow( target, dist, min_speed, max_speed, look_at )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "reached_dynamic_path_end" );
|
|
self endon( "reached_end_node" );
|
|
self endon( "end_follow" );
|
|
|
|
|
|
if( self isHelicopter() && IsDefined( look_at ) )
|
|
{
|
|
self SetLookAtEnt( look_at );
|
|
}
|
|
|
|
interval = 0.05;
|
|
|
|
while( 1 )
|
|
{
|
|
// if( DistanceSquared( target.origin, self.origin ) >= ( dist * dist ) )
|
|
if( !within_fov( target.origin, target.angles, self.origin, cos( 90 ) ) )
|
|
{
|
|
if( self Vehicle_GetSpeed() <= max_speed )
|
|
self Vehicle_SetSpeed( self Vehicle_GetSpeed() + 1.0, 15 );
|
|
}
|
|
else if( self Vehicle_GetSpeed() > min_speed )
|
|
self Vehicle_SetSpeed( self Vehicle_GetSpeed() - 1.0, 10 );
|
|
|
|
wait interval;
|
|
}
|
|
}
|
|
|
|
ShootEnemyWrapper_blanks()
|
|
{
|
|
// Shoot blanks if we're using a rifle like weapon
|
|
if ( !animscripts\utility::usingRifleLikeWeapon() )
|
|
{
|
|
animscripts\utility::shootEnemyWrapper_shootNotify();
|
|
return;
|
|
}
|
|
|
|
self.a.lastShootTime = gettime();
|
|
|
|
// set accuracy at time of shoot rather than in a separate thread that is vulnerable to timing issues
|
|
maps\_gameskill::set_accuracy_based_on_situation();
|
|
|
|
self notify( "shooting" );
|
|
self ShootBlank();
|
|
}
|
|
|
|
// DIALOGUE
|
|
actor_dialogue_queue( dialogue_line, delay )
|
|
{
|
|
if( IsDefined( delay ) )
|
|
wait delay;
|
|
|
|
self dialogue_queue( dialogue_line );
|
|
}
|
|
|
|
// ALLY CHOPPER
|
|
intro_chopper_allies_setup()
|
|
{
|
|
level.squad[ "ALLY_WILLIAMS" ].script_startingposition = 4;
|
|
level.squad[ "ALLY_JENKINS" ].script_startingposition = 3;
|
|
level.squad[ "ALLY_BAKER" ].script_startingposition = 2;
|
|
|
|
foreach( guy in level.squad )
|
|
{
|
|
guy notify( "newanim" );
|
|
self guy_enter_vehicle( guy );
|
|
}
|
|
}
|
|
|
|
chopper_allies_remove()
|
|
{
|
|
foreach( guy in level.squad )
|
|
{
|
|
guy notify( "newanim" );
|
|
self guy_exit_vehicle( guy );
|
|
// guy notify( "animontagdone", "end" );
|
|
self StopAnimScripted();
|
|
self Unlink();
|
|
}
|
|
}
|
|
|
|
|
|
// Sends a notify when a rocket is 10s from launching
|
|
launch_coutdown_logic( timer, id, cancel_flag )
|
|
{
|
|
level endon( cancel_flag );
|
|
AssertEx( timer > 10 , "launch_coutdown_logic only works with a LAUNCH_DELAY > 10" );
|
|
wait (timer-10);
|
|
|
|
// Safety check to make sure the rocket wasnt destroyed during this window
|
|
if( flag( cancel_flag ))
|
|
{
|
|
return;
|
|
}
|
|
|
|
level notify( "rocket_" + id + "_10s_warning" );
|
|
}
|
|
|
|
|
|
chopper_debug_speed()
|
|
{
|
|
while( isDefined( self ))
|
|
{
|
|
speed = self vehicle_getSpeed();
|
|
iprintln( speed );
|
|
wait 0.25;
|
|
}
|
|
}
|