IW4-Dump-Files/maps/af_caves_code.gsc

1745 lines
38 KiB
Plaintext

#include maps\_utility;
#include common_scripts\utility;
#include maps\_hud_util;
#include maps\_anim;
#include maps\_stealth_utility;
#include maps\af_caves;
#include maps\_vehicle;
#using_animtree( "generic_human" );
// -----------------------
// --- PLAYER/AI STUFF ---
// -----------------------
teleport_to_node( node )
{
self teleport_to_origin( node.origin, node.angles );
}
teleport_to_origin( origin, angles )
{
if ( !IsDefined( angles ) )
{
angles = ( 0, 0, 0 );
}
if ( !IsPlayer( self ) )
{
self ForceTeleport( groundpos( origin ), angles );
self SetGoalPos( self.origin );
}
else
{
org = level.player spawn_tag_origin();
level.player PlayerLinkTo( org, "tag_origin", 1 );
org MoveTo( origin, 0.05 );
org RotateTo( angles, 0.05 );
wait( 0.1 );
level.player Unlink();
org Delete();
}
}
price_spawn()
{
level.price = self;
level.price.animname = "price";
level.price thread magic_bullet_shield();
level.price cqb_walk( "on" );
level.price AllowedStances( "prone" );
}
turn_off_stealth()
{
disable_stealth_system();
waittillframeend; // wait for stealth system to finish setting ignoreme
level.player player_speed_percent( 100 );
SetSavedDvar( "ai_friendlyFireBlockDuration", "2000" );
level.price.maxsightdistsqrd = 8192 * 8192;
level.price cqb_walk( "off" );
level.price.neverEnableCQB = true;
level.price PushPlayer( false );
level.price.ignoreall = false;
level.price.moveplaybackrate = 1.0;
level.price.dontEverShoot = undefined;
battlechatter_on( "allies" );
}
price_be_stealthy()
{
//level.price.dontshootwhilemoving = true; // SRS not sure if we need this
level.price.dontEverShoot = true;
level.price.baseaccuracy = 1;
level.price.maxsightdistsqrd = level.price_stealth_road_sightDistSqrd;
}
price_be_lethal()
{
level.price.dontEverShoot = undefined;
level.price.baseaccuracy = 5000000;
level.price.maxsightdistsqrd = level.price_weaponsfree_sightDistSqrd;
}
price_kill( guy )
{
guy.dontattackme = undefined;
guy.threatbias = 5000;
guy.health = 1;
level.price.favoriteenemy = guy;
}
price_goto_node_and_wait_for_player( nodeTN, dist )
{
level.price notify( "price_goto_node_and_wait_for_player" );
level.price endon( "price_goto_node_and_wait_for_player" );
thread price_goto_node( nodeTN );
node = GetNode( nodeTN, "targetname" );
price_wait_for_player( dist, node );
}
// destinationEnt: wait for the player to get near the destination rather than near price
price_wait_for_player( dist, destinationEnt )
{
if ( !IsDefined( dist ) )
{
dist = 150;
}
if ( IsDefined( destinationEnt ) )
{
while ( Distance( destinationEnt.origin, level.player.origin ) > dist )
{
wait( 0.05 );
}
}
else
{
while ( Distance( level.price.origin, level.player.origin ) > dist )
{
wait( 0.05 );
}
}
level notify( "player_near_price" );
}
price_goto_node( nodeTN, goalradius )
{
level.price notify( "stop_going_to_node" );
level.price notify( "price_goto_node" );
level.price endon( "price_goto_node" );
if ( !IsDefined( goalradius ) )
{
goalradius = 24;
}
level.price.goalradius = goalradius;
node = GetNode( nodeTN, "targetname" );
level.price SetGoalNode( node );
level.price waittill( "goal" );
level notify( "price_at_node" );
}
restrict_fov_until_stealth_broken()
{
self endon( "death" );
self.fovcosine = .95;
flag_wait( "_stealth_spotted" );
if( !IsAlive( self ) )
{
return;
}
self.fovcosine = .76;
}
player_unsuppressed_weapon_warning()
{
if ( flag( "unsuppressed_weapon_warning_played" ) )
{
return;
}
level notify( "player_unsuppressed_weapon_warning" );
level endon( "player_unsuppressed_weapon_warning" );
level endon( "_stealth_spotted" );
level endon( "steamroom_start" );
while ( 1 )
{
wait( 0.25 );
while ( IsDefined( level.player_radio_emitter ) && IsDefined( level.player_radio_emitter.function_stack ) && level.player_radio_emitter.function_stack.size > 0 )
{
wait( 0.05 );
}
weap = level.player GetCurrentWeapon();
if ( weap != level.primaryweapon && weap != level.secondaryweapon && weap != "mp5_silencer_reflex" && weap != "rappel_knife" && weap != "none" )
{
break;
}
}
flag_set( "unsuppressed_weapon_warning_played" );
// "Make sure you're using a suppressed weapon, otherwise we're dead."
radio_dialogue( "afcaves_pri_suppressedweapon" );
}
player_falling_kill_trigger()
{
trigs = GetEntArray( "player_falling_kill", "targetname" );
array_thread( trigs, ::player_falling_kill_trigger_think );
}
player_falling_kill_trigger_think()
{
self waittill( "trigger" );
if ( flag( "descending" ) )
{
return;
}
flagstr = "player_falling_kill_in_progress";
if ( flag( flagstr ) )
{
return;
}
else
{
flag_set( flagstr );
}
endTime = GetTime() + 2000;
while( !level.player IsOnGround() && GetTime() < endTime )
{
wait( 0.05 );
}
if( level.player IsOnGround() )
{
level.player Kill();
}
else
{
maps\_utility::missionFailedWrapper();
}
//blackout = create_client_overlay( "black", 0, level.player );
//blackout FadeOverTime( 2 );
//blackout.alpha = 1;
//level.player Kill();
}
player_falling_to_death()
{
triggers = GetEntarray( "slide_to_death_triggers", "targetname" ); //includes all of Ned's remove_gun triggers and any other slide triggers I have added to ensure player slides to death
array_thread( triggers,:: player_falling_to_death_think );
}
player_falling_to_death_think()
{
level endon( "player_falling_to_death" );
self waittill( "trigger" );
level.player disableweapons();
flag_clear( "can_save" ); //don't allow saving if we are falling/sliding to death
level notify( "player_falling_to_death" );
}
scr_neverEnableCQB( state )
{
self.neverEnableCQB = state;
}
set_threatbiasgroup( group )
{
Assert( IsDefined( group ) );
self SetThreatBiasGroup( group );
}
playerseek()
{
self ClearGoalVolume();
self SetGoalEntity( level.player );
}
be_aggressive()
{
self.aggressivemode = true;
//self enable_heat_behavior();
self.doorFlashChance = .5;
}
is_dog()
{
return( self.type == "dog" );
}
group_has_live_human( group )
{
foreach ( ai in group )
{
if ( IsAlive( ai ) && !ai is_dog() )
{
return true;
}
}
return false;
}
give_flashlight()
{
self endon( "death" );
self cqb_walk( "on" );
self attach_flashlight();
}
attach_flashlight()
{
PlayFXOnTag( level._effect[ "flashlight" ], self, "tag_flash" );
self.have_flashlight = true;
}
patroller_do_cqbwalk()
{
if ( IsDefined( self.script_patroller ) )
{
wait( 0.05 );
self clear_run_anim();
}
self thread enable_cqbwalk();
self.alertlevel = "alert";
self.disablearrivals = undefined;
self.disableexits = undefined;
self.moveplaybackrate = .8;
thread scan_when_idle();
}
scan_when_idle()
{
self endon( "death" );
self endon( "enemy" );
self endon( "end_scan_when_idle" );
self endon( "end_patrol" );
while ( 1 )
{
self set_generic_idle_anim( "cqb_stand_idle_scan" );
self waittill( "clearing_specialIdleAnim" );
}
}
/* SRS DEPRECATED
friendly_adjust_movement_speed()
{
self notify( "stop_adjust_movement_speed" );
self endon( "death" );
self endon( "stop_adjust_movement_speed" );
for(;;)
{
wait .15;
while( friendly_should_speed_up() )
{
// IPrintLnBold( "friendlies speeding up" );
self.moveplaybackrate = 2.5;
wait 0.05;
}
self.moveplaybackrate = 1.0;
}
}
friendly_should_speed_up()
{
prof_begin( "friendly_movement_rate_math" );
if ( DistanceSquared( self.origin, self.goalpos ) <= level.goodFriendlyDistanceFromPlayerSquared )
{
prof_end( "friendly_movement_rate_math" );
return false;
}
// check if AI is visible in player's FOV
if ( within_fov( level.player.origin, level.player GetPlayerAngles(), self.origin, level.cosine[ "70" ] ) )
{
prof_end( "friendly_movement_rate_math" );
return false;
}
prof_end( "friendly_movement_rate_math" );
return true;
}
*/
force_weapon_when_player_not_looking( weaponName )
{
self endon( "death" );
while ( within_fov( level.player.origin, level.player GetPlayerAngles(), level.price.origin, level.cosine[ "45" ] ) )
{
wait 1;
}
self forceUseWeapon( weaponName, "primary" );
}
spawn_ai_group( aSpawners, doSafe, doStaggered )
{
AssertEx( ( aSpawners.size > 0 ), "The array passed to array_spawn function is empty" );
if ( !IsDefined( doSafe ) )
{
doSafe = false;
}
if ( !IsDefined( doStaggered ) )
{
doStaggered = false;
}
aSpawners = array_randomize( aSpawners );
spawnedGuys = [];
foreach ( index, spawner in aSpawners )
{
guy = spawner spawn_ai();
spawnedGuys[ spawnedGuys.size ] = guy;
if ( doStaggered )
{
if ( index != ( aSpawners.size - 1 ) )
{
wait( RandomFloatRange( .25, 1 ) );
}
}
}
if ( doSafe )
{
//check to ensure all the guys were spawned
AssertEx( ( aSpawners.size == spawnedGuys.size ), "Not all guys were spawned successfully from array_spawn" );
}
return spawnedGuys;
}
// basically copied from move::moveCoverToCover(), with some modifications and hardcoded values
scripted_covercrouch_shuffle_left()
{
self thread scripted_covercrouch_earlyout_notify( "barracks_player_near_stair_shooting_spot", level );
level endon( "barracks_player_near_stair_shooting_spot" );
node = self.scripted_shuffleNode;
Assert( IsDefined( node ) );
serverFPS = 20;
serverSPF = 0.05;
shuffleNodeType = "Cover Crouch";
nodeForwardYaw = node.angles[ 1 ];
moveDir = node.origin - self.origin;
startAnim = %covercrouch_hide_2_shuffleL;
shuffleAnim = %covercrouch_shuffleL;
endAnim = %covercrouch_shuffleL_2_hide;
blendTime = 0.4;
startEndTime = GetNotetrackTimes( startAnim, "finish" )[ 0 ];
startDist = Length( GetMoveDelta( startAnim, 0, startEndTime ) );
shuffleDist = Length( GetMoveDelta( shuffleAnim, 0, 1 ) );
endDist = Length( GetMoveDelta( endAnim, 0, 1 ) );
self ClearAnim( %body, blendTime );
self AnimMode( "zonly_physics", false );
remainingDist = Distance( self.origin, node.origin );
if ( remainingDist > startDist )
{
self OrientMode( "face angle", nodeForwardYaw );
self SetFlaggedAnimRestart( "shuffle_start", startAnim, 1, blendTime );
self animscripts\shared::DoNoteTracks( "shuffle_start" );
self ClearAnim( startAnim, 0.2 );
remainingDist -= startDist;
blendTime = 0.2;// reset blend for looping move
}
else
{
self OrientMode( "face angle", node.angles[ 1 ] );
}
playEnd = false;
if ( remainingDist > endDist )
{
playEnd = true;
remainingDist -= endDist;
}
loopTime = GetAnimLength( shuffleAnim );
playTime = loopTime * ( remainingDist / shuffleDist ) * 0.9;
playTime = floor( playTime * serverFPS ) * serverSPF;
self SetFlaggedAnim( "shuffle", shuffleAnim, 1, blendTime, 0.75 );
self animscripts\shared::DoNoteTracksForTime( playTime, "shuffle" );
// account for loopTime not being exact since loop animation delta isn't uniform over time
for ( i = 0; i < 2; i++ )
{
remainingDist = Distance( self.origin, node.origin );
if ( playEnd )
remainingDist -= endDist;
if ( remainingDist < 4 )
break;
playTime = loopTime * ( remainingDist / shuffleDist ) * 0.9; // don't overshoot
playTime = floor( playTime * serverFPS ) * serverSPF;
if ( playTime < 0.05 )
break;
self animscripts\shared::DoNoteTracksForTime( playTime, "shuffle" );
}
if ( playEnd )
{
// hardcoded here, derived based on node type in animscript
blendTime = 0.2;
self ClearAnim( shuffleAnim, blendTime );
self SetFlaggedAnim( "shuffle_end", endAnim, 1, blendTime );
self animscripts\shared::DoNoteTracks( "shuffle_end" );
// clear animation in moveCoverToCoverFinish if needed
}
self SafeTeleport( node.origin );
self AnimMode( "normal" );
self ClearAnim( %cover_shuffle, 0.2 );
self.shuffleMoveInterrupted = undefined;
self AnimMode( "none", false );
self OrientMode( "face default" );
self notify( "scripted_shuffle_done" );
// now exit the cover
level.scr_anim[ self.animname ][ "scripted_covercrouch_shuffle_exit" ] = %covercrouch_run_out_ML;
self anim_single_run_solo( self, "scripted_covercrouch_shuffle_exit" );
}
scripted_covercrouch_earlyout_notify( killNotify, ent )
{
self endon( "scripted_shuffle_done" );
if( !IsDefined( ent ) )
{
ent = self;
}
ent waittill( killNotify );
self notify( "scripted_shuffle_done" );
}
// ----------------------------------
// --- STEALTH NOSIGHT CLIP LOGIC ---
// ----------------------------------
clip_nosight_logic()
{
if( IsDefined( self.script_parameters ) )
{
if( IsSubStr( self.script_parameters, "difficultymedium" ) )
{
if( level.gameskill > 1 )
{
self Delete();
return;
}
}
}
self endon( "death" );
flag_wait( self.script_flag );
self thread clip_nosight_logic2();
self SetCanDamage( true );
self clip_nosight_wait();
self Delete();
}
clip_nosight_wait()
{
if ( flag( "_stealth_spotted" ) )
return;
level endon( "_stealth_spotted" );
self waittill( "damage" );
}
clip_nosight_logic2()
{
self endon( "death" );
flag_wait_either( "_stealth_spotted", "_stealth_found_corpse" );
self Delete();
}
// ---------------------
// --- PLAYER RAPPEL ---
// ---------------------
delay_lerpViewAngleClamp()
{
wait( 0.2 );
level.player LerpViewAngleClamp( 1, 0.5, 0.5, 45, 45, 45, 45 );
}
should_stop_descend_hint()
{
if ( flag( "rappel_end" ) )
return true;
return flag( "player_braked" );
}
player_gets_groundref_and_opens_fov( tag_origin )
{
level.player PlayerSetGroundReferenceEnt( tag_origin );
wait( 3.8 );
open_up_fov( 0.5, tag_origin, "tag_origin", 20, 20, 12, 12 );
tag_origin waittill( "open_fov" );
open_up_fov( 0.5, tag_origin, "tag_origin", 25, 25, 15, 15 );
}
af_caves_rappel_behavior()
{
SetSavedDvar( "compass", 0 );
SetSavedDvar( "ammoCounterHide", 1 );
SetSavedDvar( "actionSlotsHide", 1 );
SetSavedDvar( "hud_showStance", 0 );
SetSavedDvar( "hud_drawhud", 0 );
level.player DisableWeapons();
level.player DisableOffhandWeapons();
level.player DisableWeaponSwitch();
level.player AllowCrouch( false );
level.player AllowProne( false );
stance = level.player GetStance();
level.player SetStance( "stand" );
if ( stance != "stand" )
wait( 0.5 );
old_weapon = level.player GetCurrentWeapon();
weapon = "rappel_knife";
level.player GiveWeapon( weapon );
level.player SwitchToWeapon( weapon );
ent = GetEnt( "rappel_animent", "targetname" );
// first hook up
player_rig = spawn_anim_model( "player_rig" );
player_rig Hide();
//player_rig thread maps\_debug::drawTagForever( "tag_player", ( 1, 1, 0 ) );
ending_player_rig = spawn_anim_model( "player_rig" );
ending_player_rig Hide();
ending_player_rig DontCastShadows();
//ending_player_rig thread maps\_debug::drawTagForever( "tag_player", ( 0, 1, 1 ) );
node = GetEnt( "guard_assassinate", "script_noteworthy" );
node anim_first_frame_solo( ending_player_rig, "rappel_kill" );
player_rope = spawn_anim_model( "rope" );
player_rope Hide();
rig_and_rope[ 0 ] = player_rig;
rig_and_rope[ 1 ] = player_rope;
ent anim_first_frame( rig_and_rope, "rappel_hookup" );
// wait( 0.05 );
level.player_rig = player_rig;
tag_origin = spawn_tag_origin();
tag_origin LinkTo( player_rig, "tag_player", ( 0, 0, 0 ), ( 0, 0, 0 ) );
time = 0.5;
tag_origin_start = spawn_tag_origin();
tag_origin_start.angles = level.player GetPlayerAngles();
tag_origin_start.origin = level.player.origin;
level.player PlayerLinkTo( tag_origin_start );
wait( 0.05 ); // why?
level.player PlayerLinkToBlend( tag_origin, "tag_origin", time, 0.2, 0.2 );
delayThread( time, ::player_gets_groundref_and_opens_fov, tag_origin );
tag_origin_start Delete();
array_spawn_function_noteworthy( "rappel_guard_2", ::rappel_guard2_patrol );
array_spawn_function_noteworthy( "rappel_guard_2", ::rappel_guard2_kill_player );
array_spawn_function_noteworthy( "rappel_guard_2", ::rappel_guard2_death );
array_spawn_function_noteworthy( "rappel_guard_1", ::rappel_guard1_kill_player );
array_spawn_function_noteworthy( "rappel_guard_2", ::rappel_guards_think );
array_spawn_function_noteworthy( "rappel_guard_1", ::rappel_guards_think );
rappel_baddie_spawners = GetEntArray( "rappel_baddie_spawner", "targetname" );
array_spawn( rappel_baddie_spawners );
delayThread( 6, ::display_hint, "begin_descent" );// 8
player_rig delayCall( 0.6, ::Show );
player_rope delayCall( 0.6, ::Show );
player_rig DontCastShadows();
flag_set( "player_hooking_up" );
ent anim_single( rig_and_rope, "rappel_hookup" );
tag_origin notify( "open_fov" );
flag_set( "player_hooked_up" );
player_rig Hide();
// do some anim of starting carabiner here
flag_set( "descending" );
root_anim = player_rig getanim( "rappel_root" );
player_rig SetAnim( root_anim, 0, 0, 1 );
far_anim = player_rig getanim( "rappel_far" );
far_anim_node = player_rig getanim( "rappel_far_node" );
close_anim = player_rig getanim( "rappel_close" );
close_anim_node = player_rig getanim( "rappel_close_node" );
start_org = GetStartOrigin( ent.origin, ent.angles, far_anim );
start_ang = GetStartAngles( ent.origin, ent.angles, far_anim );
player_rig SetAnimLimited( close_anim, 1, 0, 1 );
player_rig SetAnimLimited( close_anim_node, 1, 0, 1 );
player_rig SetAnimLimited( far_anim, 0.01, 0, 1 );
player_rig SetAnimLimited( far_anim_node, 0.01, 0, 1 );
player_rig SetAnimKnob( root_anim, 1, 1, 1 );
rappel_hookup = player_rig getanim( "rappel_hookup" );
wait( 0.05 );
player_rig ClearAnim( rappel_hookup, 0.2 );
level.player_rig = player_rig;
min_speed = 0.30;// the slowest speed we can rappel
max_speed = 3.5;// the fastest rappelling speed
speed = 1;// ignore this, internal variable
anim_min_time = 0.80;
anim_min_time_clamp_speed = max_speed;
anim_max_time = 0.9;
anim_max_time_clamp_speed = 1.5;
//ending_min_speed = 2; // Min speed during the ending moment
//ending_max_speed = 2; // max speed during ending moment
ending_speed = 0.13;
break_speed = 0.375;// how fast the brakes work, the higher the number the more brakes
nobreak_rate = 0.006;// the speed that we accumulate accelleration while not braking
nobreak_maxspeed = 0.12; // the maximum accelleration while not braking
nobreak_minspeed = 0.08; // our accelleration the moment we stop braking
nobreak_speed = nobreak_minspeed;// internal variable
// effects the way the player pops off the cliff while rappelling
close_anim_dest = 100;
far_anim_dest = 0.1;
far_anim_min = 0.1;
far_anim_max = 50;
far_anim_rate = 1;
old_org = level.player.origin;
// the amount of time you have to be moving at max speed to DIE if you dont brake.
death_buffer = 20000;// no fail on easy / normal
if ( level.gameskill >= 2 )
death_buffer = 1500;
//tag_origin thread liner();
was_breaking = false;
sin_index_old = 0;
sin_index = 0;
sin_index_max = 0;
player_fell = false;
last_time_braked = 0;
speaker = Spawn( "script_origin", ( 0, 0, 0 ) );
speaker.origin = level.player.origin;
speaker LinkTo( level.player );
death_fall_timer = undefined;
speaker PlaySound( "scn_afcaves_rappel_start_plr" );
able_to_break_time = GetTime() + 1500;
for ( ;; )
{
// at % through the anim, go into ending mode with the knife
if ( player_rig GetAnimTime( far_anim ) >= 0.94 )// .94
flag_set( "rappel_end" );
breaking = level.player AdsButtonPressed() || level.player AttackButtonPressed() && !flag( "rappel_end" );
if ( breaking )
flag_set( "player_braked" );
if ( flag( "rappel_end" ) )
{
if ( level.player MeleeButtonPressed() )
break;
}
// last_time_braked + the amount of time you have to fall before you can brake
if ( breaking && GetTime() > last_time_braked + 5 && GetTime() > able_to_break_time )
{
nobreak_speed = nobreak_minspeed;
speed -= break_speed;
if ( speed < min_speed )
speed = min_speed;
player_rig SetAnimLimited( close_anim, 1, 0, speed );
player_rig SetAnimLimited( far_anim, 1, 0, speed );
far_anim_dest -= far_anim_rate * 3;
if ( far_anim_dest <= far_anim_min )
far_anim_dest = far_anim_min;
if ( !was_breaking )
{
was_breaking = true;
death_fall_timer = undefined;
sin_index = 90;
sin_index_max = 180;
sin_index_old = sin_index;
speaker StopSounds();
if ( !flag( "rappel_end" ) )
speaker PlaySound( "scn_afcaves_rappel_stop_plr" );
}
}
else
{
animtime = player_rig GetAnimTime( far_anim );
nobreak_speed += nobreak_rate;
if ( nobreak_speed > nobreak_maxspeed )
nobreak_speed = nobreak_maxspeed;
speed += nobreak_speed;
if ( speed > max_speed )
{
if ( !isdefined( death_fall_timer ) )
{
death_fall_timer = GetTime();
}
speed = max_speed;
if ( GetTime() > death_fall_timer + death_buffer )
{
if ( !flag( "rappel_end" ) )
{
//level.player Unlink();
if ( animtime >= 0.65 && animtime < anim_min_time )
{
player_fell = true;
break;
}
}
}
}
if ( flag( "rappel_end" ) )
{
// blend the current speed with the desired ending_speed
dif = 0.15;
speed = ending_speed * dif + speed * ( 1 - dif );
}
player_rig SetAnimLimited( close_anim, 1, 0, speed );
player_rig SetAnimLimited( far_anim, 1, 0, speed );
if ( was_breaking )
{
speaker StopSounds();
if ( !flag( "rappel_end" ) )
speaker PlaySound( "scn_afcaves_rappel_start_plr" );
last_time_braked = GetTime();
was_breaking = false;
sin_index = 0;
sin_index_max = 90;
sin_index_old = sin_index;
}
if ( !flag( "rappel_end" ) )
{
far_anim_dest += far_anim_rate;
if ( far_anim_dest >= far_anim_max )
far_anim_dest = far_anim_max;
}
else
{
// use the
far_anim_dest -= far_anim_rate * 3;
if ( far_anim_dest <= far_anim_min )
far_anim_dest = far_anim_min;
}
}
player_rig SetAnimLimited( close_anim_node, close_anim_dest, 0, speed );
player_rig SetAnimLimited( far_anim_node, far_anim_dest, 0, speed );
old_org = level.player.origin;
wait( 0.05 );
animtime = player_rig GetAnimTime( far_anim );
max_speed = graph_position( animtime, anim_min_time, anim_min_time_clamp_speed, anim_max_time, anim_max_time_clamp_speed );
max_speed = clamp( max_speed, anim_max_time_clamp_speed, anim_min_time_clamp_speed );
if ( animtime >= 0.98 )
{
break;
}
}
speaker Delete();
percentage = player_rig GetAnimTime( far_anim );
if ( player_fell )
{
for ( ;; )
{
far_anim_dest += far_anim_rate;
close_anim_dest -= far_anim_rate;
speed += nobreak_speed;
player_rig SetAnimLimited( close_anim_node, close_anim_dest, 0, speed );
player_rig SetAnimLimited( far_anim_node, far_anim_dest, 0, speed );
if ( player_rig GetAnimTime( far_anim ) >= 0.78 )
break;
wait( 0.05 );
}
//println( "break!" );
//angles = ( -15, -100, 0 );
angles = tag_origin.angles;
angles = ( 0, angles[ 1 ], 0 );
forward = AnglesToForward( angles );
up = AnglesToUp( angles );
velocity = forward * 750;
// velocity = up * 500;
tag_origin Unlink();
tag_origin MoveSlide( ( 0, 0, 0 ), 32, velocity );
tag_origin delayThread( 0.75, ::hurt_player_on_bounce );
thread player_decent_death();
wait( 3.5 );
level.player Kill();
}
else
{
for ( ;; )
{
if ( !isalive( level.player ) )
break;
if ( level.player MeleeButtonPressed() )
break;
wait( 0.05 );
}
//level.player Unlink();
// since I removed it at the begining no point in reseting it here.
// level.player PlayerSetGroundReferenceEnt( undefined );
// level.player EnableWeapons();
if ( flag( "player_failed_rappel" ) )
return;
wait( 0.1 );
flag_set( "player_killing_guard" );
if ( !isalive( level.player ) )
return;
level.player endon( "death" );
knife = Spawn( "script_model", ( 0, 0, 0 ) );
knife SetModel( "weapon_parabolic_knife" );
knife Hide();
knife DontCastShadows();
knife LinkTo( ending_player_rig, "tag_weapon_left", ( 0, 0, 0 ), ( 0, 0, 0 ) );
// ending_player_rig delayCall( 0.6, ::Show );
// knife delayCall( 0.6, ::Show );
thread hint_fade();
node = GetEnt( "guard_assassinate", "script_noteworthy" );
Assert( IsDefined( node ) );
guard_1 = get_living_ai_array( "rappel_guard_1", "script_noteworthy" );
Assert( IsAlive( guard_1[ 0 ] ) );
enemy = guard_1[ 0 ];
enemy.animname = "guard_1";
guys = [];
guys[ 0 ] = player_rig;
guys[ 1 ] = enemy;
enemy.a.nodeath = true;
// node.origin += (0,0,8);
level.player Unlink();
ending_player_rig relink_player_for_knife_kill( percentage );
ending_player_rig Show();
knife Show();
node.guard = enemy;
//enemy delayThread( 1.5, ::clear_nodeath_and_kill );
enemy gun_remove();
thread lerp_savedDvar( "sm_sunSampleSizeNear", 0.0156, 0.5 );
delayThread( 6.1, ::lerp_savedDvar, "sm_sunSampleSizeNear", 0.25, 1 );
node anim_single_solo( ending_player_rig, "rappel_kill" );
flag_clear( "descending" );
ending_player_rig waittillmatch( "single anim", "end" );
//Print3d( player_rig.origin, ".", (1,0,0), 1, 1, 1000 );
ending_player_rig MoveTo( ending_player_rig.origin + ( 0, 0, 12 ), 0.4, .2, .2 );
if ( old_weapon != level.secondaryweapon )
{
// switch to the default secondary if it's in the player's inventory
weaps = level.player GetWeaponsListAll();
foreach ( weap in weaps )
{
if ( weap == level.secondaryweapon )
{
old_weapon = level.secondaryweapon;
}
}
}
level.player PlayerSetGroundReferenceEnt( undefined );
knife Delete();
flag_set( "end_of_rappel_scene" );
wait( 0.8 );
level.player SwitchToWeapon( old_weapon );
level.player Unlink();
ending_player_rig Delete();
player_rig Delete();
SetSavedDvar( "compass", 1 );
SetSavedDvar( "ammoCounterHide", 0 );
SetSavedDvar( "actionSlotsHide", 0 );
SetSavedDvar( "hud_showStance", 1 );
SetSavedDvar( "hud_drawhud", 1 );
level.player EnableOffhandWeapons();
level.player EnableWeaponSwitch();
level.player AllowCrouch( true );
level.player AllowProne( true );
}
}
// called when a notetrack hits
rappel_guard1_deathgurgle( guard1 )
{
speaker = Spawn( "script_origin", guard1 GetEye() );
speaker LinkTo( guard1 );
speaker PlaySound( "scn_afcaves_rappel_kill_npc_dx", "sounddone" );
speaker waittill( "sounddone" );
speaker Unlink();
speaker Delete();
}
player_decent_death()
{
level.player waittill( "death" );
level notify( "new_quote_string" );
// You did not brake in time.
SetDvar( "ui_deadquote", &"AF_CAVES_FELL_TO_DEATH" );
blackout = create_client_overlay( "black", 0, level.player );
blackout FadeOverTime( 1.5 );
blackout.alpha = 1;
missionfailedwrapper();
}
relink_player_for_knife_kill( percentage )
{
waittillframeend;
/*
if ( percentage < 0.94 )
time = 0.8;
else
if ( percentage < 0.96 )
time = 0.6;
else
time = 0.4;
*/
time = 0.4;
// time = 0.8;//0.4 // 0.866 sec is the length of the melee anim for the rappel_knife weapon
level.player PlayerLinkToBlend( self, "tag_player", time, time * 0.5, time * 0.5 );// 0.5
wait( time );
level.player TakeWeapon( "rappel_knife" );
}
hurt_player_on_bounce()
{
if ( !isalive( level.player ) )
return;
level.player endon( "death" );
org = self.origin;
old_vel = 0;
maxhealth = level.player.maxhealth;
for ( ;; )
{
vec = self.origin - org;
vel = Length( vec );
if ( vel < old_vel - 10 )
{
randomvec = randomvector( 1000 );
level.player DoDamage( maxhealth * 0.35, randomvec );
level.player Kill();
}
//println( vel );
if ( vel > old_vel )
old_vel = vel;
org = self.origin;
wait( 0.05 );
}
}
attach_model_if_not_attached( model, tag )
{
hasModel = false;
attachedCount = self GetAttachSize();
for ( i = 0; i < attachedCount; i++ )
{
if ( self GetAttachModelName( i ) != model )
continue;
hasModel = true;
break;
}
if ( !hasModel )
self Attach( model, tag );
}
liner()
{
for ( ;; )
{
Line( self.origin, level.player.origin );
Print3d( self.origin, "x" );
wait( 0.05 );
}
}
// -----------------
// --- STEAMROOM ---
// -----------------
steamroom_door_crack_open()
{
door = level.steamroom_door;
yawopen = -50;
yawclose = yawopen * -1;
rotateTime = 0.25;
door PlaySound( "door_cargo_container_push_open" );
door RotateTo( door.angles + ( 0, yawopen, 0 ), rotateTime );
door waittill( "rotatedone" );
flag_wait( "steamroom_flash_out" );
wait( 1 );
door RotateTo( door.angles + ( 0, yawclose, 0 ), rotateTime );
door waittill( "rotatedone" );
}
steamroom_door_full_open()
{
door = level.steamroom_door;
yawopen = -90;
rotateTime = 0.5;
door ConnectPaths();
door PlaySound( "door_cargo_container_burst_open" );
door RotateTo( door.angles + ( 0, yawopen, 0 ), rotateTime );
door waittill( "rotatedone" );
door DisconnectPaths();
}
// -----------------------------
// --- EXPLOSION EARTHQUAKES ---
// -----------------------------
setup_barrel_earthquake()
{
array_thread( GetEntArray( "explodable_barrel", "targetname" ), ::barrel_earthquake_notify );
level thread explosion_earthquake();
}
barrel_earthquake_notify()
{
self waittill( "exploding" );
level notify( "explosion_earthquake", self.origin );
start = self.origin + ( 0, 0, 96 );
end = self.origin + ( 0, 0, 1024 );
ceiling = PhysicsTrace( start, end );
if ( ceiling != end )
{
current_fx = getfx( "hallway_collapsing_big" );
PlayFX( current_fx, ceiling );
}
}
explosion_earthquake()
{
fx = [];
fx[ 0 ] = "ceiling_rock_break";
fx[ 1 ] = "ceiling_rock_break";
fx[ 2 ] = "ceiling_rock_break";
fx[ 3 ] = "ceiling_rock_break";
fx[ 4 ] = "ceiling_rock_break";
fx[ 5 ] = "hallway_collapsing_big";
fx[ 6 ] = "hallway_collapsing_big";
fx[ 7 ] = "hallway_collapsing_big";
fx[ 8 ] = "hallway_collapsing_huge";
fx[ 9 ] = "hallway_collapsing_huge";
fx_angles = [];
fx_angles[ 0 ] = ( 90, 154, 11 );
fx_angles[ 1 ] = ( 90, 154, 11 );
fx_angles[ 2 ] = ( 90, 154, 11 );
fx_angles[ 3 ] = ( 90, 154, 11 );
fx_angles[ 4 ] = ( 90, 154, 11 );
fx_angles[ 5 ] = ( 0, 0, 0 );
fx_angles[ 6 ] = ( 0, 0, 0 );
fx_angles[ 7 ] = ( 0, 0, 0 );
fx_angles[ 8 ] = ( 0, 0, 0 );
fx_angles[ 9 ] = ( 0, 0, 0 );
while ( true )
{
level waittill( "explosion_earthquake", exploding_ent_origin );
max_intensity = fx.size - 1;
max_dist = 1500;
dist = Distance( level.player.origin, exploding_ent_origin );
intensity = ( max_dist - dist ) / max_dist;
if ( intensity < 0 )
intensity = 0.01;
intensity = Int( ceil( max_intensity * intensity ) );
duration = intensity / 2.5;
Earthquake( .25, duration, level.player.origin, 1024 );
for ( i = 0; i <= intensity; i++ )
{
direction = flat_angle( level.player.angles ) + ( 0, RandomInt( 80 ) - 40, 0 );
forward = AnglesToForward( direction );
start = level.player.origin + forward * 256 + ( 0, 0, 72 );
end = start + ( 0, 0, 1024 );
ceiling = PhysicsTrace( start, end );
if ( ceiling == end )
continue;
fx_index = intensity - i;
forward = AnglesToForward( fx_angles[ fx_index ] );
up = AnglesToUp( fx_angles[ fx_index ] );
current_fx = getfx( fx[ fx_index ] );
PlayFX( current_fx, ceiling, forward, up );
wait RandomFloat( .5 );
}
}
}
// ----------------------------------
// --- CONTROL ROOM SWINGING LAMP ---
// ----------------------------------
hunted_hanging_light()
{
fx = getfx( "gulag_cafe_spotlight" );
tag_origin = spawn_tag_origin();
tag_origin LinkTo( self.lamp, "j_hanging_light_04", ( 0, 0, -64 ), ( 0, 0, 0 ) );
PlayFXOnTag( fx, tag_origin, "tag_origin" );
flag_wait( "sheppard_southwest" );
StopFXOnTag( fx, tag_origin, "tag_origin" );
}
swing_light_org_think()
{
lamp = spawn_anim_model( "lamp" );
lamp thread lamp_animates( self );
}
swing_light_org_off_think()
{
lamp = spawn_anim_model( "lamp_off" );
lamp thread lamp_animates( self );
}
lamp_animates( root )
{
root.lamp = self;
self.animname = "lamp";// uses one set of anims
self.origin = root.origin;
self DontCastShadows();
// cant blend to the same anim
odd = true;
anims = [];
anims[ 0 ] = self getanim( "swing" );
anims[ 1 ] = self getanim( "swing_dup" );
thread lamp_rotates_yaw();
for ( ;; )
{
level waittill( "swing", mag );
animation = anims[ odd ];
off = !odd;
self SetAnimRestart( animation, 1, 0.3, 1 );
wait( 2.5 );
}
}
lamp_rotates_yaw()
{
ent = spawn_tag_origin();
for ( ;; )
{
yaw = RandomFloatRange( -30, 30 );
ent AddYaw( yaw );
time = RandomFloatRange( 0.5, 1.5 );
self RotateTo( ent.angles, time, time * 0.4, time * 0.4 );
wait( time );
}
}
// --------------
// --- MUSIC ---
// --------------
intro_music()
{
ender = "player_hooking_up";
level endon( ender );
thread kill_intro_music( ender );
alias = "af_caves_desertdrone";
tracktime = MusicLength( alias );
while ( !flag( ender ) )
{
MusicPlayWrapper( alias );
wait( tracktime );
music_stop( 1 );
wait( 1 );
}
}
kill_intro_music( ender )
{
flag_wait( "player_hooking_up" );
music_stop( 5 );
wait( 5 );
}
stealth_music()
{
flag_wait( "player_killing_guard" );
flag1 = "steamroom_price_moveup_2";
flag2 = "_stealth_spotted";
stealthAlias = "af_caves_stealth";
stealth_trackTime = MusicLength( stealthalias );
extraPauseTime = 7;
while( !flag( flag1 ) && !flag( flag2 ) )
{
MusicPlayWrapper( stealthAlias );
endTime = GetTime() + milliseconds( stealth_trackTime );
while( GetTime() < endTime && !flag( flag1 ) && !flag( flag2 ) )
{
wait( 0.1 );
}
music_stop( 1 );
wait( 1 );
endTime = GetTime() + milliseconds( extraPauseTime );
while( GetTime() < endTime && !flag( flag1 ) && !flag( flag2 ) )
{
wait( 0.1 );
}
}
music_stop( 1 );
wait( 1 );
MusicPlayWrapper( "af_caves_stealth_busted" );
}
// ----------------
// --- TV STUFF ---
// ----------------
tv_cinematic_think()
{
// play cinematics on the TVs
SetSavedDvar( "cg_cinematicFullScreen", "0" );
while ( 1 )
{
flag_wait( "backdoor_barracks_tv" );
thread tv_movie();
flag_waitopen( "backdoor_barracks_tv" );
level notify( "stop_cinematic" );
StopCinematicInGame();
}
}
tv_movie()
{
level endon( "stop_cinematic" );
while ( 1 )
{
// SRS TODO need new video
CinematicInGameLoopResident( "gulag_securitycam" );
wait( 5 );
while ( IsCinematicPlaying() )
{
wait( 1 );
}
}
}
barracks_tv_light()// turns off when tv gets shot
{
light = GetEnt( "tv_light", "targetname" );
wait_for_targetname_trigger( "tv_trigger" );
light SetLightIntensity( 0 );
}
barracks_destroy_tv()// destroy it when stealth is broken or if the player passes by the stealth area.
{
flag_wait( "destroy_tv" );
wait( RandomIntRange( 2, 4 ) );
exploder( "stealth_broken" );// destroy the tv
light = GetEnt( "tv_light", "targetname" );
light SetLightIntensity( 0 );
}
// ---------------------
// --- CANYON CONVOY ---
// ---------------------
convoy_loop( vehicleTN, sFlagToStop, minWait, maxWait )
{
canyon_convoy = GetEntArray( vehicleTN, "targetname" );
thread drone_vehicle_flood_start( canyon_convoy, "canyon_convoy", minWait, maxWait );
flag_wait( sFlagToStop );
drone_vehicle_flood_stop( "canyon_convoy" );
}
drone_vehicle_flood_start( aSpawners, groupName, minWait, maxWait, noSound )
{
level endon( "stop_drone_vehicle_flood" + groupName );
vehicle = undefined;
while ( true )
{
aSpawners = array_randomize( aSpawners );
foreach ( spawner in aSpawners )
{
vehicle = spawner thread spawn_vehicle_and_gopath();
vehicle thread friendlyfire_shield();
vehicle godon();
if ( IsDefined( noSound ) )
vehicle Vehicle_TurnEngineOff();
vehicle = undefined;
wait( RandomFloatRange( minWait, maxWait ) );
}
}
}
drone_vehicle_flood_stop( groupName )
{
level notify( "stop_drone_vehicle_flood" + groupName );
}
// ------------
// --- MISC ---
// ------------
get_global_fx( name )
{
fxName = level.global_fx[ name ];
return level._effect[ fxName ];
}
delete_corpse_in_volume( volume )
{
Assert( IsDefined( volume ) );
if ( self IsTouching( volume ) )
self Delete();
}
half_particles_setup()
{
//half buffer particles for PS3/PC
if ( ( level.Console && level.ps3 ) || !level.Console )
{
SetHalfResParticles( true );
}
else
{
return;
}
flag_wait( "disable_half_buffer" );
SetHalfResParticles( false );
}
// if any trigger is activated in a trigger array
waittill_trigger_array( triggers )
{
for ( k = 1; k < triggers.size; k++ )
triggers[ k ] endon( "trigger" );
triggers[ 0 ] waittill( "trigger" );
}
hide_triggers( trigger_name )
{
friendly_trigger = GetEntArray( trigger_name, "script_noteworthy" );
foreach ( trigger in friendly_trigger )
trigger trigger_off();
}
delete_by_targetname_safe( entTN )
{
ent = GetEnt( entTN, "targetname" );
if ( IsDefined( ent ) )
{
ent Delete();
}
}
delete_and_kill_targeted_spawners_by_targetname_safe( entTN )
{
ent = GetEnt( entTN, "targetname" );
if( !IsDefined( ent ) )
{
return;
}
targets = [];
spawners = [];
if( IsDefined( ent.target ) )
{
targets = GetEntArray( ent.target, "targetname" );
}
foreach( target in targets )
{
if( IsSubStr( target.classname, "actor" ) )
{
spawners[ spawners.size ] = target;
}
}
if( spawners.size )
{
array_call( spawners, ::Delete );
}
ent Delete();
}
milliseconds( seconds )
{
return seconds * 1000;
}
seconds( milliseconds )
{
return milliseconds / 1000;
}
dialogue( line )
{
controlflag = "scripted_dialogue";
flag_waitopen( controlflag );
flag_set( controlflag );
self dialogue_queue( line );
flag_clear( controlflag );
}
dialogue_temp( line, timeout )
{
self dialogue_print( line, timeout );
}
dialogue_print( line, timeout )
{
if ( !IsDefined( timeout ) )
{
timeout = 3;
}
prefix = "";
if ( !IsSubStr( line, ":" ) )
{
if ( self == level.player )
{
prefix = "Radio: ";
}
else if ( self == level.price )
{
prefix = "Price: ";
}
}
line = prefix + line;
hintfade = 0.5;
level endon( "clearing_hints" );
if ( IsDefined( level.tempHint ) )
{
level.tempHint destroyElem();
}
level.tempHint = createFontString( "default", 1.5 );
level.tempHint setPoint( "BOTTOM", undefined, 0, -40 );
level.tempHint.color = ( 1, 1, 1 );
level.tempHint SetText( line );
level.tempHint.alpha = 0;
level.tempHint FadeOverTime( 0.5 );
level.tempHint.alpha = 1;
level.tempHint.sort = 1;
wait( 0.5 );
level.tempHint endon( "death" );
wait( timeout );
level.tempHint FadeOverTime( hintfade );
level.tempHint.alpha = 0;
wait( hintfade );
level.tempHint destroyElem();
}
should_not_do_melee_rappel_hint()
{
if ( !isalive( level.player ) )
return true;
return flag( "player_failed_rappel" ) || flag( "player_killing_guard" );
}