IW4-Dump-Files/maps/favela_code.gsc

1133 lines
26 KiB
Plaintext

#include maps\_utility;
#include maps\_vehicle;
#include common_scripts\utility;
#include maps\_anim;
#using_animtree( "generic_human" );
ENEMY_BASE_ACCURACY = 0.6;
//########################################
// VISION SETS
//########################################
vision_chase()
{
flag_wait( "visionset_chase" );
time = 6;
maps\_utility::set_vision_set( "favela_chase", time );
//setExpFog( 708.893, 5902.43, 0.402663, 0.456692, 0.520202, 0.721229, 0, 0.562109, 0.600449, 0.678415, (0.89008, -0.302316, -0.341119), 0, 51.1533, 1.80097 );
}
vision_torture()
{
flag_wait( "visionset_torture" );
time = 1;
maps\_utility::set_vision_set( "favela_torture", time );
//setExpFog( 708.893, 5902.43, 0.402663, 0.456692, 0.520202, 0.721229, 0, 0.562109, 0.600449, 0.678415, (0.89008, -0.302316, -0.341119), 0, 51.1533, 1.80097 );
}
//########################################
//########################################
movePlayerToStartPoint( sTargetname )
{
assert( isdefined( sTargetname ) );
start = getent( sTargetname, "targetname" );
level.player SetOrigin( start.origin );
lookat = undefined;
if ( isdefined( start.target ) )
{
lookat = getent( start.target, "targetname" );
assert( isdefined( lookat ) );
}
if ( isdefined( lookat ) )
level.player setPlayerAngles( vectorToAngles( lookat.origin - start.origin ) );
else
level.player setPlayerAngles( start.angles );
}
modify_battlechatter_times()
{
MULT = 0.25;
// delay to make sure these get set at the level load first
wait 0.1;
// "contact to the north!" etc.
anim.eventActionMinWait[ "threat" ][ "self" ] *= MULT; // 14000
anim.eventActionMinWait[ "threat" ][ "squad" ] *= MULT; // 10000
// "cover me!" / "suppressing fire!" / "let's go!" etc.
anim.eventActionMinWait[ "order" ][ "self" ] *= MULT; // 8000;
anim.eventActionMinWait[ "order" ][ "squad" ] *= MULT; // 10000;
// "reloading!" / "grenade out!"
anim.eventActionMinWait[ "inform" ][ "self" ] *= MULT; // 6000;
anim.eventActionMinWait[ "inform" ][ "squad" ] *= MULT; // 8000;
// specific categories of the above
anim.eventTypeMinWait[ "inform" ][ "reloading" ] *= MULT; // 20000;
anim.eventTypeMinWait[ "inform" ][ "killfirm" ] *= MULT; // 15000;
// "Man down!"
anim.eventTypeMinWait[ "reaction" ][ "casualty" ] *= MULT; // 14000;
// this is the one that I think might make a big difference as long as these enemies have "hostile bursts"
anim.eventTypeMinWait[ "reaction" ][ "taunt" ] *= MULT; // 30000;
}
adjustAccuracy()
{
self endon( "death" );
wait 0.2;
self.baseaccuracy = ENEMY_BASE_ACCURACY;
}
start_traffic_group( delay, targetname1, targetname2, targetname3 )
{
level endon( "stop_street_traffic" );
assert( isdefined( delay ) );
assert( isdefined( targetname1 ) );
carTargetNames[ 0 ] = targetname1;
if ( isdefined( targetname2 ) )
carTargetNames[ 1 ] = targetname2;
if ( isdefined( targetname3 ) )
carTargetNames[ 2 ] = targetname3;
for(;;)
{
thread traffic_car_go( carTargetNames[ randomint( carTargetNames.size ) ] );
wait delay;
}
}
stop_traffic()
{
level notify( "stop_street_traffic" );
thread delete_cars_far_away();
}
delete_cars_far_away()
{
cars = getentarray( "script_vehicle", "code_classname" );
foreach( car in cars )
{
if ( !car ent_flag_exist( "dont_delete_me" ) )
continue;
if ( car ent_flag( "dont_delete_me" ) )
continue;
car delete();
}
}
traffic_car_go( sTargetname )
{
assert( isdefined( sTargetname ) );
car = spawn_vehicle_from_targetname_and_drive( sTargetname );
assert( isdefined( car ) );
car ent_flag_init( "dont_delete_me" );
car waittill( "reached_end_node" );
car delete();
}
delete_ai_at_path_end()
{
self endon( "death" );
self waittill( "reached_path_end" );
delete_ai( self );
}
delete_ai( ai )
{
guys[ 0 ] = ai;
level thread AI_delete_when_out_of_sight( guys, 512 );
}
delete_ai_at_path_end_no_choke()
{
self.usechokepoints = false;
self thread delete_ai_at_path_end();
}
delete_ai_at_goal( ignoreCanSeeChecks )
{
self endon( "death" );
self waittill( "goal" );
if ( isdefined( ignoreCanSeeChecks ) && ignoreCanSeeChecks )
{
if ( isdefined( self.magic_bullet_shield ) )
self stop_magic_bullet_shield();
self delete();
}
else
delete_ai( self );
}
dog_seek_player()
{
self endon( "death" );
if ( isdefined( self.target ) )
self waittill( "goal" );
self setgoalentity( level.player );
self.goalradius = 300;
}
seek_player()
{
self endon( "death" );
if ( isdefined( self.target ) )
self waittill( "goal" );
self setgoalentity( level.player );
self.goalradius = 1000;
}
gag_fence_dog()
{
trigger_wait( "fence_dog_gag", "targetname" );
// spawn the dog
spawner = getent( "fence_dog_spawner", "targetname" );
dog = spawner stalingradSpawn();
spawn_failed( dog );
dog endon( "death" );
dog.animname = "dog";
old_maxsightdistsqrd = dog.maxsightdistsqrd;
dog.maxsightdistsqrd = 0;
dog set_ignoreall( true );
animNode = getent( "fence_dog_node", "targetname" );
dog setlookatEntity( level.player );
animNode anim_reach_solo( dog, "fence_attack" );
dog.allowdeath = true;
animNode anim_single_solo( dog, "fence_attack" );
dog.maxsightdistsqrd = old_maxsightdistsqrd;
dog set_ignoreall( false );
dog thread dog_seek_player();
wait 1;
dog setlookatEntity();
}
dont_see_player()
{
self endon( "death" );
self addAIEventListener( "bulletwhizby" );
self.usechokepoints = false;
self.interval = 0;
self.fovcosine = 0.7;
self.pathenemyfightdist = 512;
self waittill_either( "damage", "bulletwhizby" );
self.goalradius = level.default_goalradius;
self setgoalpos( self.origin );
}
window_smasher()
{
self endon( "death" );
self.dontevershoot = true;
// get nearest window_smash ent
window = self getWindowParts();
// wait until AI is at the window node
windowNode = self getWindowNode();
self.goalradius = 16;
self setGoalNode( windowNode );
// play melee anim
windowNode thread anim_generic( self, "window_smash" );
thread open_window( window, 0.1 );
wait 0.3;
self stopAnimScripted();
wait 0.3;
self.dontevershoot = undefined;
wait 1.0;
self.goalradius = 75;
}
getWindowNode()
{
nodes = getnodearray( "window_smash_node", "targetname" );
index = get_closest_index( self.origin, nodes );
return nodes[ index ];
}
getWindowParts()
{
windows = getentarray( "window_smash", "targetname" );
index = get_closest_index( self.origin + ( 0, 0, 48 ), windows );
windowEnt = windows[ index ];
windowParts = getentarray( windowEnt.target, "targetname" );
assert( windowParts.size == 2 );
leftWindow = undefined;
rightWindow = undefined;
foreach( part in windowParts )
{
if ( part.script_noteworthy == "left" )
leftWindow = part;
else if ( part.script_noteworthy == "right" )
rightWindow = part;
}
assert( isdefined( leftWindow ) );
assert( isdefined( rightWindow ) );
ents = [];
ents[ "left" ] = leftWindow;
ents[ "right" ] = rightWindow;
return ents;
}
open_window( window, delay )
{
if ( isdefined( delay ) )
wait delay;
thread play_sound_in_space( "scn_favela_npc_open_shutters", window[ "left" ].origin );
window[ "left" ] rotateYaw( 155, 0.5, 0.0 );
window[ "right" ] rotateYaw( -155, 0.4, 0.0 );
wait 0.5;
window[ "left" ] rotateYaw( -15, 1.0, 1.0 );
window[ "left" ] rotateYaw( 15, 1.0, 1.0 );
}
play_sound_trigger()
{
assert( isdefined( self.script_noteworthy ) );
assert( isdefined( self.target ) );
soundEnt = getent( self.target, "targetname" );
assert( isdefined( soundEnt ) );
self waittill( "trigger" );
thread play_sound_in_space( self.script_noteworthy, soundEnt.origin );
}
gag_civilian_window_1()
{
trigger_wait( "gag_civilian_window_1", "targetname" );
// spawn character
spawner = getent( "window_civilian_spawner_1", "targetname" );
guy = spawner spawn_ai( true );
guy endon( "death" );
// play anim
windowNode = getent( "civilian_window_node1", "targetname" );
windowNode anim_generic( guy, "civilian_window_1" );
// run away and delete
runawayNode = getnode( "window_civilian_spawner_runto_node", "targetname" );
guy.goalradius = 16;
guy setGoalNode( runawayNode );
delete_ai( self );
guy thread delete_ai_at_goal();
}
ignored_until_goal()
{
// AI is ignored by enemy AI until he gets to his goal
self endon( "death" );
self.ignoreme = true;
self waittill( "goal" );
wait randomfloatrange( 1.0, 2.0 );
self.ignoreme = false;
}
ignore_and_delete_on_goal( ignoreCanSeeChecks )
{
self thread set_ignoreme( true );
self thread set_ignoreall( true );
self thread delete_ai_at_goal( ignoreCanSeeChecks );
}
faust_spawn_func()
{
if ( isdefined( level.faust ) )
{
if ( isdefined( level.faust.magic_bullet_shield ) )
{
level.faust stop_magic_bullet_shield();
wait 0.05;
}
level.faust delete();
level.faust = undefined;
}
level.faust = self;
// he runs his path. When he gets to the end of his path he gets deleted
level.faust endon( "death" );
level.faust set_ignoreall( true );
level.faust set_ignoreme( true );
level.faust thread magic_bullet_shield();
level.faust thread faust_spills_money();
level.faust thread faust_mission_fail();
level.faust waittill( "reached_path_end" );
if ( isdefined( level.faust.magic_bullet_shield ) )
level.faust stop_magic_bullet_shield();
wait 0.05;
level.faust delete();
level.faust = undefined;
}
faust_spills_money()
{
self endon( "death" );
for(;;)
{
playfxontag( getfx( "cash_trail" ), self, "J_Hip_LE" );
wait randomfloatrange( 0.2, .5);
}
}
faust_mission_fail()
{
self endon( "reached_path_end" );
for(;;)
{
self waittill( "damage", damage, attacker );
if ( !isdefined( attacker ) )
continue;
if ( attacker != level.player )
continue;
if ( damage <= 1 )
continue;
break;
}
self stop_magic_bullet_shield();
wait 0.05;
self kill( self.origin, level.player );
setdvar( "ui_deadquote", "@FAVELA_ROJAS_KILLED" );
maps\_utility::missionFailedWrapper();
}
trigger_spawn_chance()
{
spawners = getentarray( self.target, "targetname" );
assert( spawners.size > 0 );
self waittill( "trigger" );
chance_percent = 25;
if ( isdefined( self.script_noteworthy ) )
chance_percent = int( self.script_noteworthy );
if ( randomint( 100 ) > chance_percent )
return;
spawners = array_removeundefined( spawners );
array_thread( spawners, ::spawn_ai );
}
desert_eagle_guy()
{
self endon( "death" );
self forceUseWeapon( "deserteagle", "sidearm" );
anim.shootEnemyWrapper_func = animscripts\utility::ShootEnemyWrapper_shootNotify;
self.weapon = self.sidearm;
self.favoriteenemy = level.player;
self.disablearrivals = true;
self.disableexits = true;
self.animname = "desert_eagle_guy";
self.baseaccuracy = 1;
self.noAttackerAccuracyMod = true;
self.accuracy = 1;
self.goalradius = 16;
self thread delayThread( 3.0, ::set_goalradius, 300 );
self thread delayThread( 3.0, ::set_goal_player );
self playsound( "generic_meleecharge_russian_" + randomintrange( 1, 8 ) );
while ( level.player.health > 0 )
{
level waittill( "an_enemy_shot", guy );
if ( guy != self )
continue;
num = 1;
while ( num )
{
wait .25;
self shoot();
num -- ;
}
}
self.ignoreme = true;
}
set_goal_player()
{
if ( !isAlive( self ) )
return;
if ( !isAlive( level.player ) )
return;
self setGoalPos( level.player.origin );
}
process_ai_script_parameters()
{
if ( !isdefined( self.script_parameters ) )
return;
parms = strtok( self.script_parameters, ":;, " );
foreach( parm in parms )
{
parm = tolower( parm );
if ( parm == "balcony" )
self.deathFunction = ::try_balcony_death;
}
}
try_balcony_death()
{
// always return false in this function because we want the death
// animscript to continue after this function no matter what
if ( !isdefined( self ) )
return false;
if ( self.a.pose == "prone" ) // allow crouch
return false;
if ( !isdefined( self.prevnode ) )
return false;
if ( !isdefined( self.prevnode.script_balcony ) )
return false;
angleAI = self.angles[ 1 ];
angleNode = self.prevnode.angles[ 1 ];
angleDiff = abs( angleAI - angleNode );
if ( angleDiff > 15 )
return false;
d = distance( self.origin, self.prevnode.origin );
if ( d > 16 )
return false;
if ( !isdefined( level.last_balcony_death ) )
level.last_balcony_death = getTime();
elapsedTime = getTime() - level.last_balcony_death;
// if one just happened within 5 seconds dont do it
if ( elapsedTime < 5 * 1000 )
return false;
deathAnims = [];
deathAnims[0] = %death_rooftop_A;
deathAnims[1] = %death_rooftop_B;
deathAnims[2] = %death_rooftop_D;
deathAnims[3] = %bog_b_rpg_fall_death;
self.deathanim = deathAnims[ randomint( deathAnims.size ) ];
return false;
}
control_run_speed()
{
level endon( "runner_shot" );
self endon( "death" );
// speed and slows runner's run speed so the player can't catch him but also doesn't get left too far behind
targetSpeed = undefined;
//self.moveplaybackrate = 1.2;
//self.sprint = true;
flag_wait( "soap_control_run_speed" );
/*
for(;;)
{
targetSpeed = self get_best_run_speed();
self thread set_run_speed( targetSpeed );
wait 0.2;
}
*/
}
get_best_run_speed()
{
ai_dist = distance( self.origin, self.last_set_goalnode.origin );
player_dist = distance( level.player.origin, self.last_set_goalnode.origin );
offset = ai_dist - player_dist;
RATE_MIN = 1.0;
RATE_MAX = 1.5;
DISTANCE_MIN = -450;
DISTANCE_MAX = 0;
offset = cap_value( offset, DISTANCE_MIN, DISTANCE_MAX );
// player is far behind, normal run speed
if ( offset < DISTANCE_MIN )
return RATE_MIN;
// player is ahead of AI, max run speed
if ( offset >= DISTANCE_MAX )
return RATE_MAX;
// player is close behind the AI, control run speed to make sure AI stays ahead
fraction = get_fraction( offset, DISTANCE_MIN, DISTANCE_MAX );
targetSpeed = RATE_MAX - ( ( RATE_MAX - RATE_MIN ) * fraction );
assert( targetSpeed > 0 );
return targetSpeed;
}
set_run_speed( targetSpeed )
{
assert( isdefined( targetSpeed ) );
self.moveplaybackrate = targetSpeed;
}
get_fraction( value, min, max )
{
fraction = abs( ( value - min ) / ( min - max ) );
fraction = abs( 1 - fraction );
fraction = cap_value( fraction, 0.0, 1.0 );
return fraction;
}
physics_drop()
{
assert( isdefined( self.target ) );
orgs = getentarray( self.target, "targetname" );
assert( orgs.size > 0 );
self waittill( "trigger" );
array_thread( orgs, ::physics_drop_model );
}
physics_drop_model()
{
model = spawn( "script_model", self.origin );
model setModel( level.physics_drop_models[ randomint( level.physics_drop_models.size ) ] );
vec = anglesToForward( self.angles );
vec *= 2000;
model PhysicsLaunchClient( model.origin + ( 0, 0, 0 ), vec );
}
forklift_blocker()
{
forklift_before = getentarray( "forklift_before", "targetname" );
forklift_before_clip = getent( "forklift_before_clip", "targetname" );
forklift_after = getentarray( "forklift_after", "targetname" );
forklift_after_clip = getent( "forklift_after_clip", "targetname" );
// hide after
array_call( forklift_after, ::hide );
forklift_after_clip notsolid();
flag_wait( "block_alley" );
// show after, hide before
array_call( forklift_after, ::show );
forklift_after_clip solid();
array_call( forklift_before, ::delete );
forklift_before_clip delete();
}
car_anims()
{
// attach hula girl
tag = "tag_hulagirl_attach";
level.hula_girl = spawn_anim_model( "hula_girl", self getTagOrigin( tag ) );
level.hula_girl.angles = self getTagAngles( tag );
level.hula_girl linkTo( self, tag );
level.hula_girl setAnim( level.scr_anim[ "hula_girl" ][ "bobble" ] );
self setAnim( level.scr_anim[ "car" ][ "driving" ] );
self waittill( "reached_end_node" );
self clearAnim( level.scr_anim[ "car" ][ "driving" ], 1.0 );
level.hula_girl clearAnim( level.scr_anim[ "hula_girl" ][ "bobble" ], 1.0 );
level.hula_girl setAnim( level.scr_anim[ "hula_girl" ][ "bobble_stop" ] );
wait 1.55;
level.hula_girl clearAnim( level.scr_anim[ "hula_girl" ][ "bobble_stop" ], 1.0 );
// opens the door when soap exists the vehicle
flag_wait( "soap_exits_car" );
self setAnim( level.scr_anim[ "car" ][ "run_and_wave" ] );
self waittill( "door_open" );
self thread play_sound_on_entity( "scn_favela_player_door_open" );
self setAnim( level.scr_anim[ "car" ][ "door_open" ] );
}
car_driver_anims()
{
driver = make_car_driver();
assert( isdefined( driver ) );
driver linkTo( self, "tag_driver" );
self thread anim_loop_solo( driver, "idle", "stop_drive_idle", "tag_driver" );
wait 13;
self notify( "stop_drive_idle" );
self setanimknob( level.scr_anim[ "car" ][ "center2right" ], 1, 0, 1 );
self anim_single_solo( driver, "center2right", "tag_driver" );
wait 1;
self clearAnim( level.scr_anim[ "car" ][ "center2right" ], 0 );
self setanimknob( level.scr_anim[ "car" ][ "right2center" ], 1, 0, 1 );
self anim_single_solo( driver, "right2center", "tag_driver" );
self clearAnim( level.scr_anim[ "car" ][ "right2center" ], 0 );
self thread anim_loop_solo( driver, "idle", "stop_drive_idle", "tag_driver" );
flag_wait( "opening_scene_started" );
self thread play_sound_on_entity( "scn_favela_driver_killed" );
self anim_single_solo( driver, "react", "tag_driver" );
}
make_car_driver()
{
guy = spawn_targetname( "car_driver" );
model = spawn( "script_model", guy.origin );
model.angles = guy.angles;
model setmodel( guy.model );
numAttached = guy getattachsize();
for ( i = 0; i < numAttached; i++ )
{
modelname = guy getattachmodelname( i );
tagname = guy getattachtagname( i );
model attach( modelname, tagname, true );
}
model.animname = "driver";
model UseAnimTree( #animtree );
guy delete();
return model;
}
trigger_cleanup()
{
assert( isdefined( self.target ) );
areas = getentarray( self.target, "targetname" );
assert( areas.size > 0 );
self waittill( "trigger" );
foreach( area in areas )
{
array_thread( area get_ai_touching_volume( "axis" ), ::delete_ai_not_bullet_shielded );
}
}
delete_ai_not_bullet_shielded()
{
if ( isdefined( self.magic_bullet_shield ) )
return;
self delete();
}
bike_rider( pathTargetname )
{
bike_path_start = getent( pathTargetname, "targetname" );
bike_path_end = getent( bike_path_start.target, "targetname" );
bike = spawn( "script_model", bike_path_start.origin );
bike setModel( "com_bike_animated" );
bike useAnimTree( level.scr_animtree[ "bike" ] );
rider = spawn( "script_model", bike.origin );
rider useAnimTree( #animtree );
if ( !isdefined( level.spawned_bike_rider ) )
{
level.spawned_bike_rider = true;
rider character\character_civilian_slum_male_aa::main();
}
else
{
rider character\character_civilian_slum_male_ab::main();
}
rider.origin = bike getTagOrigin( "j_frame" );
rider.origin += ( -12, 0, -30 );
rider.angles = bike getTagAngles( "j_frame" );
rider.angles += ( 0, 180, 0 );
rider linkTo( bike, "j_frame" );
ang = vectorToAngles( bike_path_start.origin - bike_path_end.origin );
bike.angles = ( 0, ang[ 1 ], 0 );
bike setanim( level.scr_anim[ "bike" ][ "pedal" ] );
rider setanim( level.scr_anim[ "generic" ][ "bike_rider" ] );
moveTime = 10;
bike MoveTo( bike_path_end.origin, moveTime, 0, 0 );
wait moveTime;
rider delete();
bike delete();
}
potted_plant()
{
forward = anglesToForward( self.angles );
up = anglesToUp( self.angles );
pos = self.origin;
trig = undefined;
if ( isdefined( self.target ) )
trig = getent( self.target, "targetname" );
self thread potted_plant_damage();
if ( isdefined( trig ) )
self thread potted_plant_triggered( trig );
self waittill( "fall" );
fx = undefined;
switch( self.model )
{
case "com_potted_plant_small":
fx = getfx( "plant_small_thrower" );
break;
case "com_potted_plant_medium":
fx = getfx( "plant_medium_thrower" );
break;
case "com_potted_plant_large":
fx = getfx( "plant_large_thrower" );
break;
}
assert( isdefined( fx ) );
self delete();
playFX( fx, pos, forward, up );
}
potted_plant_damage()
{
self endon( "fall" );
self setCanDamage( true );
self waittill( "damage" );
self notify( "fall" );
}
potted_plant_triggered( trig )
{
self endon( "fall" );
trig waittill( "trigger" );
wait randomfloatrange( 0.0, 0.2 );
self notify( "fall" );
}
play_fx_trig()
{
assert( isdefined( self.script_noteworthy ) );
fx = self.script_noteworthy;
assert( isdefined( level._effect[ fx ] ) );
assert( isdefined( self.target ) );
fxEnt = getent( self.target, "targetname" );
fxID = getfx( fx );
for(;;)
{
self waittill( "trigger" );
playFX( fxID, fxEnt.origin );
wait 1.0;
}
}
civilian_flee_walla()
{
self endon( "death" );
// civillians don't do wallas until you're in the favela
if ( !flag( "civilians_walla" ) )
return;
wait 0.05;
while( self.alertLevelInt <= 1 )
wait 0.05;
if ( !isdefined( level.nextWallaIndex ) )
level.nextWallaIndex = 0;
elapsedTime = getTime() - level.lastWallaTime;
if ( elapsedTime < 5000 )
return;
level.lastWallaTime = getTime();
// walla
animScene = level.fleeing_civilian_wallas[ level.nextWallaIndex ];
self.allowdeath = true;
self thread anim_generic( self, animScene );
level.nextWallaIndex++;
if ( level.nextWallaIndex >= level.fleeing_civilian_wallas.size )
nextWallaIndex = 0;
}
ending_car_fx( vehicle )
{
exploder ( "car_crush_cash" );
wait 0.1;
exploder ( "car_crush" );
playfxontag( getFX( "car_crush_glass_med" ), vehicle, "tag_window_left_glass_fx" );
playfxontag( getFX( "car_crush_glass_med" ), vehicle, "tag_window_right_glass_fx" );
playfxontag( getFX( "car_crush_glass_large" ), vehicle, "tag_windshield_back_glass_fx" );
playfxontag( getFX( "car_crush_glass_large" ), vehicle, "tag_windshield_front_glass_fx" );
}
dive_through_glass( guy )
{
PlayFXOnTag( getFX( "glass_dust_trail" ), guy, "J_SpineLower" );
guy thread maps\favela::ending_sequence_slowmo();
}
delete_ai_during_blackscreen()
{
ai = getAIArray();
foreach( guy in ai )
{
if ( isdefined( guy.magic_bullet_shield ) )
guy stop_magic_bullet_shield();
guy notify( "deleted" );
}
array_call( getAIArray(), ::delete );
}
curtain_pulldown( bWaitForPlayer )
{
if ( !isdefined( bWaitForPlayer ) )
bWaitForPlayer = false;
assert( isdefined( self.target ) );
node = self curtain_pulldown_getnode();
assert( isdefined( node ) );
curtain = spawn_anim_model( "curtain" );
node thread anim_first_frame_solo( curtain, "pulldown" );
self waittill( "spawned", guy );
if ( spawn_failed( guy ) )
return;
guy endon( "death" );
guy.animname = "curtain_pull";
guy.disablepain = true;
guy set_ignoreme( true );
guy.usechokepoints = false;
wait 0.05;
guy_and_curtain[ 0 ] = guy;
guy_and_curtain[ 1 ] = curtain;
node anim_reach_solo( guy, "pulldown" );
if ( bWaitForPlayer )
{
node anim_first_frame_solo( guy, "pulldown" );
waittill_player_lookat( 0.9, undefined, true, 5.0 );
}
// Don't allow guy to die until 1.5 seconds in so the curtain doesn't fall on it's own
guy.allowdeath = false;
guy thread allow_death_delayed( 1.5 );
node anim_single( guy_and_curtain, "pulldown" );
guy endon( "death" );
guy set_ignoreme( false );
guy.goalradius = 1000;
guy setGoalPos( guy.origin );
guy.usechokepoints = true;
}
allow_death_delayed( delay )
{
wait delay;
if ( isdefined( self ) )
self.allowdeath = true;
}
curtain_pulldown_getnode()
{
nodes = getentarray( self.target, "targetname" );
foreach( node in nodes )
{
if ( node.classname == "script_origin" )
return node;
}
assertMsg( "curtain pulldown guy doesn't target a script_origin" );
}
car_screech_node()
{
self waittill( "trigger", vehicle );
assert( isdefined( vehicle ) );
sound[ 0 ] = "scn_favela_car_traffic_skid1";
sound[ 1 ] = "scn_favela_car_traffic_skid2";
sound[ 2 ] = "scn_favela_car_traffic_skid3";
if ( !isdefined( level.next_skid_sound ) )
level.next_skid_sound = 0;
vehicle playSound( sound[ level.next_skid_sound ] );
level.next_skid_sound++;
if ( level.next_skid_sound >= sound.size )
level.next_skid_sound = 0;
}
retreat_trigger()
{
assert( isdefined( self.target ) );
node = getnode( self.target, "targetname" );
assert( isdefined( node ) );
assert( isdefined( node.radius ) );
volume = getent( self.target, "targetname" );
assert( isdefined( volume ) );
self waittill( "trigger" );
// get all AI in the volume
ai = volume get_ai_touching_volume( "axis" );
// make all ai touching the volume go to the specified node with it's radius
foreach( guy in ai )
{
guy.goalradius = node.radius;
guy set_goal_node( node );
}
}
timed_favela_autosaves()
{
flag_wait( "player_entered_favela" );
while( !flag( "cleared_favela" ) )
{
wait 60;
if ( flag( "cleared_favela" ) )
return;
thread autosave_by_name( "lower_favela" );
}
}
civilian_driver()
{
self.disablepain = true;
self.a.nodeath = true;
self.health = 10000000000;
}
faust_assistant_kill_player_monitor()
{
self endon( "death" );
distSq = 400 * 400;
cos90 = cos( 90 );
for(;;)
{
wait 0.05;
// player must be within range of Faust's assistant
d = DistanceSquared( self.origin, level.player.origin );
if ( d > distSq )
continue;
// player must be in front of Faust's assistant
FOV = within_fov( self.origin, self.angles, level.player.origin, cos90 );
if ( !FOV )
continue;
// Faust's assisstant should now kill the player for getting in front of him
self thread faust_assistant_kill_player();
return;
}
}
faust_assistant_kill_player()
{
self endon( "death" );
level.player endon( "death" );
// kill the player
createThreatBiasGroup( "player" );
createThreatBiasGroup( "makarov" );
level.player setThreatBiasGroup( "player" );
self setThreatBiasGroup( "makarov" );
setThreatBias( "makarov", "player", 100000 );
self.maxsightdistsqrd = 8000 * 8000;
self set_ignoreall( false );
self set_ignoreme( true );
self.goalradius = 16;
self setGoalPos( self.origin );
level.player.health = 1;
self waittill( "shooting" );
wait 0.05;
if ( isalive( level.player ) )
level.player kill();
}