1745 lines
38 KiB
Plaintext
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" );
|
|
}
|