cod5-sdk/raw/maps/ber2_event2.gsc
2008-11-20 00:00:00 +00:00

2158 lines
50 KiB
Text

//
// file: ber2_event2.gsc
// description: event 2 script for berlin2
// scripter: slayback
//
#include maps\_utility;
#include common_scripts\utility;
#include maps\_anim;
#include maps\ber2;
#include maps\ber2_util;
#include maps\_music;
#using_animtree( "generic_human" );
// -- STARTS --
// for starting from event 2.
event2_start()
{
warp_players_underworld();
warp_friendlies( "struct_event2_start_friends", "targetname" );
warp_players( "struct_event2_start", "targetname" );
wait( 1 );
if( level.coopOptimize )
{
numToSpawn = 2;
spawner = getent_safe( "spawner_street_extraguy", "targetname" );
for( i = 0; i < numToSpawn; i++ )
{
spawner.count++;
extra = undefined;
while( !IsDefined( extra ) )
{
while( !OkToSpawn() )
{
wait( 0.05 );
}
extra = spawn_guy( spawner );
wait( 0.1 );
}
extra thread magic_bullet_shield_safe();
// just move out of the way
extra SetGoalPos( ( 933, 696, -191 ) );
extra friend_add();
wait( 0.1 );
}
}
set_objective( 5 );
bluetrig = getent_safe( "friendly_respawn_trigger_auto979", "script_noteworthy" );
pinktrig = getent_safe( "friendly_respawn_trigger_auto5246", "script_noteworthy" );
bluetrig notify( "trigger" );
pinktrig notify( "trigger" );
wait( 0.25 );
level thread maps\ber2_event1::event1_action(); // this takes players into event2 stuff once the post-gate trigger is hit
level thread maps\ber2_event1::subway_gate_action();
}
// for starting before the metro wave sequence.
event2_start_metrowave()
{
warp_players_underworld();
warp_friendlies( "struct_event2_metrowave_friends", "targetname" );
warp_players( "struct_event2_metrowave", "targetname" );
set_color_chain( "trig_script_color_allies_b29" );
objectives_skip( 0 );
level thread event2_setup();
flag_set( "subway_gate_closed" );
wait( 2 );
getent_safe( "trigger_fog_ber2_subway", "script_noteworthy" ) notify( "trigger", get_players()[0] );
}
// -- END STARTS --
event2_setup()
{
event2_arty_setup();
thread event2_friends_setup();
thread event2_arty();
thread event2_reset_squad_colors();
thread event2_mgs();
thread event2_exitgate_action();
thread metrowave_init_lights();
thread event2_action_dialogue();
thread metro_ai_wetness_change();
//Kevins notify for starting the lights
SetClientSysState("levelNotify","start_lights");
//Kevin Sending ent name to the client side
sound_subway_lights = getentarray("light_subway_flicker", "targetname");
for(i = 0; i < sound_subway_lights.size; i ++)
{
sound_subway_lights[i] transmittargetname();
}
}
metro_ai_wetness_change()
{
flag_wait( "subway_gate_closed" );
level thread ais_wetness_change( 0.5, 20, false, "allies" );
}
event2_friends_setup()
{
for( i = 0; i < level.friends.size; i++ )
{
guy = level.friends[i];
guy.maxSightDistSqrd = 574 * 574;
if( guy != level.sarge && guy != level.hero1 )
{
guy thread stop_magic_bullet_shield_safe();
}
}
}
event2_reset_squad_colors()
{
trigger_wait( "trig_script_color_allies_b31", "targetname" );
flag_wait( "lights_back_on" );
// put all friendlies back on blue color chain
for( i = 0; i < level.friends.size; i++ )
{
level.friends[i].og_forcecolor = "b"; // in case the lights are off when we try to do this
level.friends[i] set_force_color( "b" );
}
}
event2_mgs()
{
level thread event2_mg_think( "trig_floodspawner_mgLeft", "spawner_metro_mg_left", "turret_metro_mg_left", "left" );
level thread event2_mg_think( "trig_floodspawner_mgRight", "spawner_metro_mg_right", "turret_metro_mg_right", "right" );
}
event2_mg_think( trigSN, spawnerTN, turretSN, mgLocation )
{
trigger_wait( trigSN, "script_noteworthy" );
dismountTrig = undefined;
killTrig = undefined;
ender = undefined;
killAtEnd = true;
if( mgLocation == "left" )
{
dismountTrig = getent_safe( "trig_mgLeft_dismount", "targetname" );
killTrig = getent_safe( "trig_script_color_allies_b32", "targetname" );
ender = "subway_mg_left_dismount";
goalPos = ( -2280, 2248, -528 );
}
else
{
dismountTrig = getent_safe( "trig_mgRight_dismount", "targetname" );
killTrig = getent_safe( "trig_subway_exitGateArea", "targetname" );
ender = "subway_mg_right_dismount";
goalPos = ( -3412, 3646, -584 );
}
spawner = getent_safe( spawnerTN, "targetname" );
gunner = spawn_guy( spawner );
if( !IsDefined( gunner ) )
{
ASSERTMSG( "Can't spawn the gunner from spawner with targetname " + spawnerTN );
return;
}
gunner.isMGer = true;
turret = getent_safe( turretSN, "script_noteworthy" );
level thread event2_mg_dismount( dismountTrig, ender );
gunner thread event2_mg_force( turret, ender, goalPos );
turret waittill( "turretstatechange" );
switch( mgLocation )
{
case "left":
guy = event2_mg_get_speaker( "p" );
guy thread say_dialogue( "metro_mg_notifier", "mg_left" );
break;
case "right":
guy = event2_mg_get_speaker( "b" );
guy thread say_dialogue( "metro_mg_notifier", "mg_right" );
break;
default:
ASSERTMSG( "event2_mg_think(): mgLocation of '" + mgLocation + "' is not recognized." );
}
}
event2_mg_get_speaker( color )
{
guys = undefined;
// guys don't have color chains when the lights are off
if( flag( "lights_back_on" ) )
{
// get a guy on the correct side of the metro
guys = get_friends_by_color( color );
}
else
{
guys[0] = get_randomfriend_notsarge_excluding( level.hero1 );
}
ASSERTEX( array_validate( guys ), "Can't find anybody to say the MG line." );
return get_random( guys );
}
event2_mg_dismount( trig, ender )
{
trig waittill( "trigger" );
level notify( ender );
}
// self = an AI
event2_mg_force( turret, ender, goalPos )
{
self endon( "death" );
self.goalradius = 24;
node = getnode_safe( turret.targetname, "target" );
self SetGoalNode( node );
self.health = 10000;
self thread magic_bullet_shield_safe();
self waittill( "goal" );
self thread stop_magic_bullet_shield_safe();
level thread guy_stay_on_turret( self, turret, ender );
level thread turret_reset( self, turret, ender );
self thread scr_set_health( 150, 3 );
level waittill( ender );
if( is_active_ai( self ) )
{
self StopUseTurret();
self.ignoreall = true;
self SetGoalPos( goalPos );
self waittill( "goal" );
}
if( is_active_ai( self ) )
{
self.ignoreall = false;
self thread bloody_death( true, 5 );
}
}
turret_reset( gunner, turret, ender )
{
thread turret_reset_on_ender( gunner, turret, ender );
level endon( ender );
gunner waittill( "death" );
turret SetMode( "manual_ai" );
}
turret_reset_on_ender( gunner, turret, ender )
{
gunner endon( "death" );
level waittill( ender );
wait( 0.1 );
turret SetMode( "manual_ai" );
}
scr_set_health( health, delay )
{
wait( delay );
self.health = health;
}
// --- metro exit gate stuff, including flash flood wave event ---
event2_exitgate_action()
{
// wait for players to approach the area before starting to think
trigger_wait( "trig_subway_exitGate_start", "targetname" );
// regroup friends at the gate
set_objective( 7 );
level notify( "subway_arty_kill" );
flag_set( "lights_back_on" );
wait( 0.1 );
set_color_chain( "trig_script_color_allies_b42" );
trig = GetEnt( "trig_subway_exitGateArea", "targetname" );
trig waittill( "trigger" );
// spawn the final tunnel defenders
spawners = GetEntArray( "spawner_subway_exitDefenders", "targetname" );
ASSERTEX( IsDefined( spawners ) && spawners.size > 0, "Can't find any spawners for the subway exit defenders!" );
for( i = 0; i < spawners.size; i++ )
{
spawners[i].count = 100;
}
maps\_spawner::flood_spawner_scripted( spawners );
level notify( "subway_exitgate_startDefenders" );
// wait for the opener AI to get in the area
opener = level.sarge;
while( !opener IsTouching( trig ) )
{
wait( 0.5 );
}
// make sure all the players are in the area
waittill_all_players_touching( trig );
// for faster iterations on the wave art
quickWave = GetDvarInt( "quickwave" );
if( IsDefined( quickWave ) && quickWave > 0 )
{
quickWave = 1;
}
else
{
quickWave = 0;
}
// start the flash flood wave event
thread metrowave( opener, quickWave );
level waittill( "subway_exitgate_startRunners" );
spawners = GetEntArray( "spawner_subway_exitRunners", "targetname" );
ASSERTEX( IsDefined( spawners ) && spawners.size > 0, "Can't find any spawners for the subway exit runners!" );
maps\_spawner::flood_spawner_scripted( spawners );
wave_trigger_wait( "struct_metrowave_nearEnemyLine" );
maps\_spawner::kill_spawnerNum( 201 );
}
metrowave_runner_spawnfunc()
{
self.health = 1;
level thread metrowave_runner_killpoints( self );
}
metrowave_runner_killpoints( runner )
{
runner waittill( "death" );
if( IsDefined( runner.attacker ) && IsPlayer( runner.attacker ) )
{
arcademode_assignpoints( "arcademode_score_generic1000", runner.attacker );
}
}
metrowave( opener, quickWave )
{
flag_set( "wave_sequence_started" );
autosave_by_name( "ber2_metrowave_start" );
gate = getent_safe( "sbmodel_subway_exitDoor", "targetname", "subway exit gate" );
animSpot = getnode_safe( "node_subway_exitDoorSpot", "targetname", "metro exit door opening guy's spot" );
// opener goes to gate
opener.og_animname = opener.animname;
opener.animname = "subway_exitgate_opener";
opener.ignoreme = true;
opener.ignoreall = true;
opener PushPlayer( true );
animSpot anim_reach_solo( opener, "doorstuck1" );
//TUEY Sets music state to Subway
setmusicstate("SUBWAY_END");
set_color_chain( "trig_script_color_allies_b22" );
set_objective( 8 );
level thread metrowave_friends_reactions( quickWave );
level thread metrowave_force_camera(); // forces camera and does timescaling
door = getent_safe( "sbmodel_subway_exitDoor", "targetname" );
wave = getent_safe( "smodel_metrowave", "targetname" );
waveCollisionTrig = getent_safe( "trig_metrowave_collision", "targetname" );
waveCollisionTrig_aggressive = getent_safe( "trig_metrowave_collision_aggressive", "targetname" );
// this area basically controls the timing of the whole wave buildup
if( !quickWave )
{
level thread metrowave_rats();
// "Keep firing!... I need to get the gate open!"
level.sarge playsound_generic_facial( "Ber2_IGD_094A_REZN" );
animSpot metrowave_door_anim( "doorstuck1", opener, door );
animSpot anim_single_solo( opener, "twitch4" );
// start wave buildup
level notify( "start_wave_buildup" );
metrowave_quake( "firststrike" );
// Kevin: Notify to play arty hit on metro that starts flood.
level notify( "wave_arty" );
animSpot metrowave_door_anim( "doorstuck2", opener, door );
animSpot anim_single_solo( opener, "twitch2" );
//animSpot metrowave_door_anim( "doorstuck3", opener, door );
animSpot anim_single_solo( opener, "twitch3" );
//animSpot metrowave_door_anim( "doorstuck1", opener, door );
//animSpot anim_single_solo( opener, "twitch4" );
// start rats
// Kevin: Notify to play rats
level notify( "start_rats" );
level thread metrowave_rumble( wave );
animSpot metrowave_door_anim( "doorstuck3", opener, door );
//animSpot anim_single_solo( opener, "twitch4" );
//animSpot metrowave_door_anim( "doorstuck2", opener, door );
// "almost got it..."
animSpot anim_single_solo( opener, "almost" );
}
thread battlechatter_off( "allies" );
//thread battlechatter_off( "axis" );
level notify( "subway_exitgate_startRunners" );
level thread metrowave_move( wave, waveCollisionTrig, waveCollisionTrig_aggressive );
level thread metrowave_impact_ais( waveCollisionTrig_aggressive );
level thread metrowave_turnoff_lights( waveCollisionTrig );
level thread metrowave_blackout( waveCollisionTrig );
//metrowave_quake( "player_approach" );
level thread metrowave_approach_quake( wave );
wave_trigger_wait( "struct_metrowave_nearplayer" );
flag_set( "wave_near_players" );
// make sure he didn't get deleted
if( is_active_ai( opener ) )
{
// "got it!"
animSpot anim_single_solo( opener, "success" );
level.sarge Delete();
}
objective_state( 8, "done" );
}
metrowave_approach_quake( wave )
{
// start the rumble loops
array_thread( get_players(), ::metrowave_approach_rumble, wave );
scale = 0.3;
bigscale = 0.45;
duration = 0.5;
radius = 5000;
// quake based on wave location
while( !flag( "metrowave_blackout" ) )
{
quakeScale = scale;
if( flag( "wave_near_players" ) )
{
scale = bigscale;
}
Earthquake( scale, duration, wave.origin, radius );
wait( duration * 0.5 );
}
}
metrowave_approach_rumble( wave )
{
self endon( "death" );
self endon( "disconnect" );
self PlayRumbleLoopOnEntity( "tank_rumble" );
while( !flag( "metrowave_blackout" ) )
{
wait( 0.05 );
}
self StopRumble( "tank_rumble" );
}
wave_trigger_wait( spotTN )
{
level endon( "wave_finished" );
waveCollisionTrig = getent_safe( "trig_metrowave_collision", "targetname" );
spot = getstruct_safe( spotTN, "targetname" );
// can't test istouching against structs
org = Spawn( "script_origin", spot.origin );
while( !waveCollisionTrig IsTouching( org ) )
{
wait( 0.05 );
}
org Delete();
}
// self = the animSpot
metrowave_door_anim( animeName, opener, door )
{
door thread metro_exitdoor_anim( animeName );
self anim_single_solo( opener, animeName );
}
metrowave_friends_reactions( quickWave )
{
animname = "subway_exitgate_reaction";
if( !quickWave )
{
// wave buildup
level waittill( "start_wave_buildup" );
wait( 2 );
level.hero1 say_dialogue( animname, "doyouhearthat" );
// rats close by
level waittill( "rats_near_player" );
level.hero1 say_dialogue( animname, "rats" );
}
// wave start
level waittill( "subway_exitgate_startRunners" );
level.hero1 say_dialogue( animname, "hurryup" );
// wave near enemies
wave_trigger_wait( "struct_metrowave_nearEnemyLine" );
level.hero1 say_dialogue( animname, "omg" );
}
// handles earthquake types for wave event
metrowave_quake( quakeType )
{
quakeScaleMin = undefined;
quakeScaleMax = undefined;
quakeDuration = undefined;
// figure out quake type
switch( quakeType )
{
case "firststrike":
quakeScaleMin = 0.4;
quakeScaleMax = 0.5;
quakeDuration = 5;
break;
case "low_rumble":
quakeScaleMin = 0.15;
quakeScaleMax = 0.16;
quakeDuration = 10;
break;
case "player_approach":
quakeScaleMin = 0.35;
quakeScaleMax = 0.45;
quakeDuration = 5;
break;
default:
ASSERTMSG( "metrowave_quake(): quakeType '" + quakeType + "' not recognized." );
}
fxMaxDist = 450;
quakeRadius = 128;
darkTimeMin = undefined;
darkTimeMax = undefined;
thread event2_arty_shake( level.metro_arty_emitters, level.metro_flicker_lights, darkTimeMin, darkTimeMax, fxMaxDist, quakeScaleMin, quakeScaleMax, quakeDuration, quakeRadius );
}
metrowave_rats()
{
level endon( "wave_near_players" );
level waittill( "start_rats" );
ratStarts = GetStructArray( "metrowave_rat_start", "targetname" );
ASSERTEX( IsDefined( ratStarts ) && ratStarts.size > 0, "metrowave_rats(): can't find any rat start spots." );
level.ratsMax = 40;
level.ratMoveSpeed = 175;
ratWaitToSpawn_min = 0.2;
ratWaitToSpawn_max = 0.3;
if( level.coopOptimize )
{
level.ratsMax = 20;
level.ratMoveSpeed = 165;
ratWaitToSpawn_min = 0.4;
ratWaitToSpawn_max = 0.65;
}
level.rats = [];
thread metrowave_rats_notify();
while( 1 )
{
// are we maxed out on rats?
if( level.rats.size > level.ratsMax )
{
// delete the oldest rat as we spawn a new one
level thread delete_oldest_rat();
}
get_random( ratStarts ) thread metrowave_rat_init();
wait( RandomFloatRange( ratWaitToSpawn_min, ratWaitToSpawn_max ) );
}
}
metrowave_rats_notify()
{
wait( 3 );
level notify( "rats_near_player" );
}
metrowave_rat_init()
{
rat = Spawn( "script_model", self.origin );
rat SetModel( "sewer_rat" );
rat.angles = self.angles;
rat.pathstart = self;
level.rats[level.rats.size] = rat;
rat thread metrowave_rat_runpath();
}
// self = the rat
metrowave_rat_runpath()
{
self endon( "rat_delete" );
// play anims while running path
self thread metrowave_rat_anims();
// run path
pathpoint = self.pathstart;
while( IsDefined( pathpoint ) )
{
if( IsDefined( pathpoint.target ) )
{
targets = GetStructArray( pathpoint.target, "targetname" );
nextpoint = get_random( targets );
// drop points a bit so they're beneath the water
//zOffset = -0.175;
zOffset = -5;
pathpointOrigin = pathpoint.origin + ( 0, 0, zOffset );
nextpointOrigin = nextpoint.origin + ( 0, 0, zOffset );
// get time to get from one point to the next in order to keep constant speed
// time = distance/speed
ratMoveTime = Distance2D( nextpointOrigin, pathpointOrigin ) / level.ratMoveSpeed;
//ratRotateTime = ratMoveTime / 6;
ratRotateTime = 0.5;
// rotate, if necessary
newAngles = VectorToAngles( nextpointOrigin - pathpointOrigin );
if( self.angles != newAngles )
{
self thread rotate_over_time( newAngles, ratRotateTime );
}
self MoveTo( nextpointOrigin, ratMoveTime );
//rat waittill( "movedone" );
wait( ratMoveTime - 0.05 );
pathpoint = nextpoint;
}
else
{
break;
}
}
self thread rat_delete();
}
delete_oldest_rat()
{
if( IsDefined( level.rats[0] ) )
{
level.rats[0] thread rat_delete();
}
}
rat_delete()
{
self notify( "rat_delete" );
self notify( "rat_stop_anims" );
if( IsDefined( self.deleting ) )
{
return;
}
else
{
self.deleting = true;
}
level.rats = array_remove( level.rats, self );
// sink!
sinktime = 1;
self MoveTo( self.origin + ( 0, 0, -32 ), sinktime );
wait( sinktime );
self Delete();
}
metrowave_rumble( wave )
{
scale = 0.25;
duration = 5;
source = getstruct_safe( "struct_metrowave_nearplayer", "targetname" ).origin;
radius = 64;
// Kevin notify for LFE rumble
level notify( "rumble" );
// scale, duration, source, radius
array_thread4( get_players(), ::scr_earthquake, scale, duration, source, radius );
array_thread( get_players(), ::generic_rumble_loop, duration, "light" );
wait( duration );
scale = 0.65;
duration = 5;
array_thread4( get_players(), ::scr_earthquake, scale, duration, source, radius );
array_thread( get_players(), ::generic_rumble_loop, duration );
}
metrowave_move( wave, waveCollisionTrig, waveCollisionTrig_aggressive )
{
pathStart = getstruct_safe( wave.target, "targetname" );
// build path
wavePath = [];
// set up the pathpoints
pathpoint = pathStart;
arraycount = 0;
while( IsDefined( pathpoint ) )
{
wavePath[arraycount] = pathpoint;
arraycount++;
if( IsDefined( pathpoint.target ) )
{
pathpoint = GetStruct( pathpoint.target, "targetname" );
}
else
{
break;
}
}
ASSERTEX( IsDefined( wavePath ) && wavePath.size > 0, "Couldn't find pathpoints for metrowave!" );
// attach the wave collision triggers to the wave
waveCollisionTrig EnableLinkTo();
waveCollisionTrig LinkTo( wave );
waveCollisionTrig_aggressive EnableLinkTo();
waveCollisionTrig_aggressive LinkTo( wave );
// attach particles to the wave
PlayFxOnTag( level._effect["metrowave_base"], wave, "tag_origin" );
// move wave
waveSpeed = 625;
// this works because the first origin is placed directly beneath the wave model
// if not, you'll have to move the wave to the struct's X/Y and rotate it to the struct's angles
// it also assumes the wave travels along the same Z at all times
for( i = 0; i < wavePath.size; i++ )
{
org = wavePath[i];
nextOrg = undefined;
newAngles = undefined;
// look ahead to next org
if( IsDefined( org.target ) )
{
nextOrg = GetStruct( org.target, "targetname" );
// get time to get from one point to the next in order to keep constant speed
// time = distance/speed
waveMoveTime = Distance2D( nextOrg.origin, org.origin ) / waveSpeed;
waveRotateTime = waveMoveTime / 4;
// rotate, if necessary
newAngles = VectorToAngles( nextOrg.origin - org.origin );
if( wave.angles != newAngles )
{
wave thread rotate_over_time( newAngles, waveRotateTime, ( 0, 90, 0 ) );
}
wave MoveTo( nextOrg.origin, waveMoveTime );
wave waittill( "movedone" );
}
}
}
rotate_over_time( newAngles, rotateTime, anglesOffset )
{
angles = newAngles;
if( IsDefined( anglesOffset ) )
{
angles += anglesOffset;
}
self RotateTo( angles, rotateTime );
}
metrowave_impact_ais( waveCollisionTrig )
{
level endon( "wave_finished" );
while( 1 )
{
enemies = get_ai_group_ai( "ai_metrowave_enemies" );
friends = get_friends( );
guys = array_combine( enemies, friends );
if( IsDefined( guys ) && guys.size > 0 )
{
for( i = 0; i < guys.size; i++ )
{
guy = guys[i];
if( is_active_ai( guy ) && waveCollisionTrig IsTouching( guy ) )
{
if( !IsDefined( guy.waveImpact ) )
{
guy thread metrowave_impact_ai();
}
}
}
}
wait( 0.05 );
}
}
// self = the guy getting hit by the wave
metrowave_impact_ai()
{
self.waveImpact = true;
wait( RandomFloatRange( 0.12, 0.2 ) * GetTimeScale() );
// key friendlies have bullet shield turned on
if( IsDefined( self.magic_bullet_shield ) && self.magic_bullet_shield )
{
self thread stop_magic_bullet_shield();
}
animSpot = SpawnStruct();
animSpot.origin = self.origin;
animSpot.angles = ( 0, 325, 0 );
self.animname = "metrowave_casualty";
animRefs[0] = "wipeout1";
animRefs[1] = "wipeout2";
animRefs[2] = "wipeout3";
animRefs[3] = "wipeout4";
animRefs[4] = "wipeout5";
animRefs[5] = "wipeout6";
animRefs[6] = "wipeout7";
animRefs[7] = "wipeout8";
if( IsDefined( self ) && IsAlive( self ) )
{
animSpot anim_single_solo( self, get_random( animRefs ) );
}
self DoDamage( self.health + 5, ( 0, 0, 0 ) );
}
metrowave_force_camera()
{
lookTarget = getstruct_safe( "struct_metrowave_nearEnemyLine", "targetname" );
wave_trigger_wait( "struct_metrowave_nearEnemyLine" );
// "Dimitri! LOOK OUT!!!"
level.hero1 thread playsound_generic_facial( "Ber2_IGD_415A_CHER" );
wait( 0.25 );
reqDot = 0.77;
viewLerpTime = 0.3;
players = get_players();
for( i = 0; i < players.size; i++ )
{
players[i] EnableInvulnerability( true );
// see if they're looking in that direction
normal = VectorNormalize( lookTarget.origin - players[i].origin );
player_angles = players[i] GetPlayerAngles();
player_forward = AnglesToForward( player_angles );
dot = VectorDot( player_forward, normal );
if( dot < reqDot )
{
// angles from the player eye origin to the optimal look target
anglesToLookOrigin = VectorToAngles( lookTarget.origin - players[i] GetEye() );
players[i] SetStance( "stand" );
//players[i] thread lerp_player_view_to_position( players[i].origin, lookAngles, viewLerpTime, 1, 20, 20, 10, 10 );
players[i] thread lerp_player_view_to_position( players[i].origin, anglesToLookOrigin, viewLerpTime, 1, 0, 0, 0, 0 );
}
}
wait( viewLerpTime * 0.5 );
timescaleSlow = 0.2;
//Kevin adding notify to set slow mo sounds
level notify( "slow_shatter" );
timescale_over_time( timescaleSlow, 0.8 );
wait( 1.35 * timescaleSlow ); // to wait for x seconds of real time, we wait for (x * timescaleSlow) seconds of game time
timescale_over_time( 1, 0.9 );
}
metrowave_init_lights()
{
startIntensity = 2.5;
lightGroups = [];
lightGroups[0] = getstruct_safe( "floodlight_1", "targetname" );
lightGroups[1] = getstruct_safe( "floodlight_2", "targetname" );
lightGroups[2] = getstruct_safe( "floodlight_3", "targetname" );
lightGroups[3] = getstruct_safe( "floodlight_4", "targetname" );
lightGroups[4] = getstruct_safe( "floodlight_5", "targetname" );
for( i = 0; i < lightGroups.size; i++ )
{
// a script_struct
lightGroup = lightGroups[i];
lightGroup.light = getent_safe( lightGroup.target, "targetname" );
lightGroup.light SetLightIntensity( 5.5 );
// set up cone particle w/ d-light
lightGroup.particleLight = Spawn( "script_model", lightGroup.origin );
lightGroup.particleLight.angles = lightGroup.angles;
lightGroup.particleLight SetModel( "tag_origin" );
PlayFxOnTag( level._effect["metro_light_filler_high"], lightGroup.particleLight, "tag_origin" );
}
level.metrowaveLightGroups = lightGroups;
}
metrowave_turnoff_lights( waveCollisionTrig )
{
array_thread( level.metrowaveLightGroups, ::metrowave_turnoff_lightgroup, waveCollisionTrig );
}
metrowave_turnoff_lightgroup( waveCollisionTrig )
{
level endon( "wave_finished" );
lightGroup = self;
org = Spawn( "script_origin", lightGroup.light.origin );
org.angles = ( 0, 325, 0 );
while( !waveCollisionTrig IsTouching( org ) )
{
wait( 0.05 );
}
//Kevin playing light hits by wave
org playsound("bulb_break");
PlayFX( level._effect["light_explode"], org.origin, org.angles );
lightGroup.light light_setintensity( 0, 0.05 );
if( IsDefined( lightGroup.particleLight ) )
{
lightGroup.particleLight Delete();
}
wait( 2 );
org Delete();
}
metrowave_blackout( waveCollisionTrig )
{
// wait for the wave to hit a player
while( 1 )
{
players = get_players();
waveTouch = false;
for( i = 0; i < players.size; i++ )
{
player = players[i];
if( waveCollisionTrig IsTouching( player ) )
{
waveTouch = true;
break;
}
}
if( waveTouch )
{
break;
}
else
{
wait( 0.05 );
}
}
level thread metrowave_kill_all_axis();
wait( 0.1 );
// Kevin: Notify to stop wave looping sound and turn down buses
level notify("stop_wave_sound");
SetClientSysState("levelNotify","set_wave_bus");
players = get_players();
for( i = 0; i < players.size; i++ )
{
players[i] DisableWeapons();
players[i] SetClientDvar( "compass", "0" );
players[i] SetClientDvar( "miniscoreboardhide", "1" );
// lock in place
players[i].lock = Spawn( "script_origin", players[i].origin );
players[i].lock.angles = players[i].angles;
players[i] PlayerLinkTo( players[i].lock, "", 1, 25, 25, 25, 25 );
}
// blackout!
level.blackout = NewHudElem();
level.blackout.x = 0;
level.blackout.y = 0;
level.blackout.horzAlign = "fullscreen";
level.blackout.vertAlign = "fullscreen";
level.blackout.foreground = false; // arcademode compatible
level.blackout.sort = 50; // arcademode compatible
level.blackout SetShader( "black", 640, 480 );
flag_set( "metrowave_blackout" );
players = get_players();
// move playerone to our perfect spot
playerone = players[0];
playerone.lock.origin = ( -3654, 3871, -514 );
playerone.lock.angles = ( 336, 64, -40 );
// if we have more than one player...
if( players.size > 1 )
{
for( i = 0; i < players.size; i++ )
{
// disable bleeding out so we don't restart from checkpoint during black screen
players[i] thread player_prevent_bleedout();
// hide players & warp to playerone's spot
players[i] Hide();
if( players[i] != playerone )
{
players[i].lock.origin = playerone.lock.origin;
players[i].lock.angles = playerone.lock.angles;
}
}
}
wait( 2 );
// set up watery looking stuff
// TODO for now this is just temp
//Kevin adding underwater screams
level notify( "water_scream" );
players = get_players();
for( i = 0; i < players.size; i++ )
{
players[i] VisionSetNaked( "sniper", 0.05 );
}
tscale = 0.5;
SetTimescale( tscale );
// DEPRECATED
//level thread floater( playerone.lock );
// fade in
level.blackout FadeOverTime( 1 * tscale );
level.blackout.alpha = 0;
array_thread( get_players(), ::metrowave_player_bubbles );
wait( 2.5 * tscale );
// fade out
level.blackout FadeOverTime( 0.8 * tscale );
level.blackout.alpha = 1;
wait( 2 * tscale );
// fade in
//Kevin adding underwater screams
level notify( "water_scream" );
level.blackout FadeOverTime( 1 * tscale );
level.blackout.alpha = 0;
array_thread( get_players(), ::metrowave_player_bubbles );
wait( 2 * tscale );
// fade out
level.blackout FadeOverTime( 0.8 * tscale );
level.blackout.alpha = 1;
//Kevin stopping looped sounds
level notify( "loops_stop" );
wait( 6 * tscale );
// if demo, do custom outro
if( level.isDemo )
{
epd_demo_outro();
}
else
{
nextmission();
}
}
metrowave_kill_all_axis()
{
axis = GetAIArray( "axis" );
if( !array_validate( axis ) )
{
return;
}
for( i = 0; i < axis.size; i++ )
{
axis[i].health = 1;
axis[i] delayThread( RandomFloatRange( 2, 5 ), ::bloody_death, true, 2 );
}
}
// stops players from bleeding out in coop
player_prevent_bleedout()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
self.bleedout_time = 100000;
wait( 0.5 );
}
}
/* DEPRECATED
floater( animSpot, isAxis )
{
animname = "metrowave_floater";
animRef = "float";
guy = Spawn( "script_model", animSpot.origin );
guy Hide();
guy.angles = animSpot.angles;
if( !IsDefined( isAxis ) )
{
isAxis = false;
}
if( isAxis )
{
guy maps\ber2_anim::setup_axis_char_model();
}
else
{
guy maps\ber2_anim::setup_ally_char_model();
}
guy UseAnimTree( #animtree );
guy.animname = animname;
animSpot thread anim_single_solo( guy, animRef );
wait( 0.075 );
guy Show();
guy waittillmatch( "single anim", "end" );
guy Delete();
}
*/
// Flamer steez
metrowave_player_bubbles()
{
self endon( "death" );
self endon( "disconnect" );
deleteit = 0;
for (i=0; i < 10; i++)
{
offset1 = (randomint(20), randomint(20), -1*randomint(5));
offset2 = (-1*randomint(20), -1*randomint(20), -1*randomint(5));
offset = offset1 + offset2;
spot1 = spawn("script_model", (self geteye())+(offset) );
spot1 setmodel("tag_origin");
spot2 = spawn("script_model", (self geteye())+(offset) );
spot2 setmodel("tag_origin");
spot1 linkto(self);
spot2 linkto(self);
playfxontag(level._effect["limb_bubbles"], spot1, "tag_origin");
playfxontag(level._effect["torso_bubbles"], spot2, "tag_origin");
if (deleteit == 0)
{
deleteit = 1;
level thread wait_and_trigoff(spot1, randomfloat(2.3, 3) );
spot2 thread drag_bubbles();
}
else if (deleteit == 1)
{
level thread wait_and_trigoff(spot1, randomfloat(2.3, 4) );
level thread wait_and_trigoff(spot2, randomfloat(2.3, 4) );
}
}
}
drag_bubbles()
{
wait 3;
self unlink();
self moveto(self.origin+(0,0,-100), 10);
}
wait_and_trigoff(thing, time)
{
wait time;
if (isdefined(thing))
{
thing unlink();
thing moveto(thing.origin+(0,0,-10000), 0.01);
wait 0.1;
thing delete();
thing = "undefined";
}
}
// handles custom outro stuff for the EPD demo
epd_demo_outro()
{
SetTimescale( 1 );
if( !IsDefined( level.blackout ) )
{
level.blackout = NewHudElem();
level.blackout.x = 0;
level.blackout.y = 0;
level.blackout.horzAlign = "fullscreen";
level.blackout.vertAlign = "fullscreen";
level.blackout.foreground = true;
level.blackout SetShader( "black", 640, 480 );
level.blackout.alpha = 0;
}
// if screen's not black already, fade the black in
if( level.blackout.alpha != 1 )
{
level.blackout FadeOverTime( 0.8 );
level.blackout.alpha = 1;
}
temptext = NewHudElem();
temptext.x = 0;
temptext.y = 0;
temptext.alignX = "center";
temptext.alignY = "middle";
temptext.horzAlign = "center";
temptext.vertAlign = "middle";
temptext.sort = 1;
temptext.foreground = true;
temptext.fontscale = 1.75;
temptext SetText( &"GAME_TO_BE_CONTINUED" );
fadeTime_text = 1.2;
// fade text in
temptext.alpha = 0;
temptext FadeOverTime( fadeTime_text );
temptext.alpha = 1;
wait( 3 + fadeTime_text );
fadeTime_text = 0.25;
// fade text out
temptext FadeOverTime( fadeTime_text );
temptext.alpha = 0;
wait( fadeTime_text );
// change text and fade up
temptext.fontscale = 1.5;
temptext SetText( &"GAME_THANKS_FOR_PLAYING" );
temptext FadeOverTime( fadeTime_text );
temptext.alpha = 1;
wait( 2 + fadeTime_text );
fadeTime_text = 1.2;
// fade text out
temptext FadeOverTime( fadeTime_text );
temptext.alpha = 0;
wait( fadeTime_text );
outroscreen = NewHudElem();
outroscreen.horzAlign = "center";
outroscreen.vertAlign = "middle";
outroscreen.alignX = "center";
outroscreen.alignY = "middle";
outroscreen.sort = 1;
outroscreen.foreground = true;
outroscreen SetShader( "ber2_epd_coming_soon", 400, 400 );
outroscreen.alpha = 0;
// fade the outro art in on top of the black
outroscreen FadeOverTime( 1.2 );
outroscreen.alpha = 1;
wait( 1.2 );
// after some time, you can skip it
wait( 5 );
endTime = GetTime() + ( 15 * 1000 );
host = get_players()[0];
while( GetTime() < endTime )
{
if( host UseButtonPressed() )
{
break;
}
else
{
wait( 0.05 );
}
}
// fade outro art out
outroscreen FadeOverTime( 3 );
outroscreen.alpha = 0;
wait( 3 );
wait( 0.75 );
//CODE MOD: TKEEGAN 8/15/08
nextmission(); // back to title screen
}
// --- end subway exit gate stuff ---
// --- metro arty impact stuff ---
event2_arty_setup()
{
// metro flickery lights get initialized to starting brightness at map start in ber2_fx
emitters = GetStructArray( "struct_metro_artyfx_emitter", "targetname" );
ASSERTEX( IsDefined( emitters ) && emitters.size > 0, "Can't find any metro arty fx emitters." );
level.metro_arty_emitters = emitters;
flag_clear( "lights_back_on" );
}
event2_arty()
{
level endon( "subway_exitgate_startDefenders" );
//flag_wait( "subway_gate_closed" );
// start when players get a ways onto the subway platform
trigger_wait( "trig_floodspawner_mgLeft", "script_noteworthy" );
level.pauseRandomShake = false;
// time between arty strikes (actual time is + darkTimeMax)
minWait = 25;
maxWait = 30;
// time that the lights will be off
darkTimeMin = 8;
darkTimeMax = 12;
// time over which the lights will flicker back on
level.flickerTimeMin = 5;
level.flickerTimeMax = 7;
// quake settings
quakeScaleMin = .34;
quakeScaleMax = .39;
quakeDuration = 3;
quakeRadius = 500;
// max distance from player to fx emitters
fxMaxDist = 650;
isFirstShake = true;
while( 1 )
{
if( !isFirstShake )
{
wait( RandomFloatRange( minWait, maxWait ) );
thread arty_normalshake_friendly_dialogue();
}
// first strike should happen immediately
else
{
thread arty_firstshake_dialogue();
isFirstShake = false;
}
if( !level.pauseRandomShake )
{
//Kevin: Notify to play arty hitting metro.
level notify("metro_arty");
thread event2_arty_shake( level.metro_arty_emitters, level.metro_flicker_lights, darkTimeMin, darkTimeMax, fxMaxDist, quakeScaleMin, quakeScaleMax, quakeDuration, quakeRadius );
// make sure we're not hitting again until the lights come up
wait( darkTimeMax );
}
}
}
arty_firstshake_dialogue()
{
level endon( "subway_arty_kill" );
wait( 1 );
// "Shhhh!"
level.sarge playsound_generic_facial( "Ber2_IGD_081A_REZN" );
// "Stay where you are."
level.sarge playsound_generic_facial( "Ber2_IGD_082A_REZN" );
// "Give your eyes a moment to adjust to the darkness."
level.sarge playsound_generic_facial( "Ber2_IGD_083A_REZN" );
flag_wait( "lights_back_on" );
// "OPEN FIRE!!!"
level.sarge playsound_generic_facial( "Ber2_IGD_084A_REZN" );
}
arty_normalshake_friendly_dialogue()
{
level endon( "subway_arty_kill" );
wait( 1 );
randomTries = 10;
// "Stay on your guard... They may be cowering in the dark."
darkLines[0] = "Ber2_IGD_030A_REZN";
// "Shhhhh!"
darkLines[1] = "Ber2_IGD_008A_REZN";
// "Stay where you are."
darkLines[2] = "Ber2_IGD_082A_REZN";
// "I can barely see."
darkLines[3] = "Ber2_IGD_052A_CHER";
// "Don't move."
darkLines[4] = "Ber2_IGD_401A_REZN";
// "We cannot fight in darkness."
darkLines[5] = "Ber2_IGD_402A_CHER";
// "What do we do now?"
darkLines[6] = "Ber2_IGD_403A_CHER";
// "Wait... be ready..."
darkLines[7] = "Ber2_IGD_404A_REZN";
// "Find your targets as soon as the lights come on."
darkLines[8] = "Ber2_IGD_405A_REZN";
// try to get a unique line
darkLine = get_random_excluding( darkLines, level.lastDarkLine );
level.lastDarkLine = darkLine;
speaker = get_artyshake_speaker( darkLine );
speaker playsound_generic_facial( darkLine );
flag_wait( "lights_back_on" );
// "There! On the platform!"
lightLines[0] = "Ber2_IGD_085A_REZN";
// "In the traincars!"
lightLines[1] = "Ber2_IGD_086A_REZN";
// "Cut them down!"
lightLines[2] = "Ber2_IGD_024A_REZN";
// "Fire!"
lightLines[3] = "Ber2_IGD_025A_REZN";
// "I see them!" (Reznov)
lightLines[4] = "Ber2_IGD_023A_REZN";
// "I see them!" (Chernov)
lightLines[5] = "Ber2_IGD_406A_CHER";
// "Now, Comrades! NOW!!!"
lightLines[6] = "Ber2_IGD_407A_REZN";
// "Send them to their graves!"
lightLines[7] = "Ber2_IGD_408A_REZN";
// try to get a unique line
lightLine = get_random_excluding( lightLines, level.lastLightLine );
level.lastLightLine = lightLine;
// play the line
speaker = get_artyshake_speaker( lightLine );
speaker playsound_generic_facial( lightLine );
}
get_artyshake_speaker( theLine )
{
speaker = level.sarge;
if( IsSubStr( theLine, "CHER" ) )
{
speaker = level.hero1;
}
return speaker;
}
firstshake_lights_back_on_setflag()
{
level waittill( "lights_back_on" );
flag_set( "firstshake_lights_back_on" );
}
// dist = how far away should we look for emitter origins?
event2_arty_shake( emitters, lights, darkTimeMin, darkTimeMax, maxDist, quakeScaleMin, quakeScaleMax, quakeDuration, quakeRadius )
{
fx_dust = level._effect["metro_arty_dust"];
fx_chunks = level._effect["metro_arty_dust_chunks"];
event2_arty_fx_reset( emitters );
players = get_players();
for( i = 0; i < players.size; i++ )
{
player = players[i];
// play the earthquake
player thread generic_rumble_loop( quakeDuration * 0.9 );
Earthquake( RandomFloatRange( quakeScaleMin, quakeScaleMax ), quakeDuration, player.origin, quakeRadius );
if( !flag( "wave_sequence_started" ) )
{
// flicker lights
level.arty_flickerlights_on = 0;
array_thread( lights, maps\ber2_fx::light_arty_flicker, darkTimeMin, darkTimeMax );
thread darkness_think( lights );
//Kevins notify for light manager and to stop the light loops
SetClientSysState("levelNotify","arty_light_hit");
player playsound("subway_debris1");
}
// play particles, if emitters are nearby
for( i = 0; i < emitters.size; i++ )
{
emitter = emitters[i];
if( Distance( player.origin, emitter.origin ) <= maxDist )
{
if( !IsDefined( emitter.arty_isEmitting ) || !emitter.arty_isEmitting )
{
emitter.arty_isEmitting = true;
if( RandomInt( 100 ) < 30 )
{
PlayFx( fx_chunks, emitter.origin );
}
else
{
PlayFx( fx_dust, emitter.origin );
}
}
}
}
}
}
event2_arty_fx_reset( emitters )
{
for( i = 0; i < emitters.size; i++ )
{
emitters[i].arty_isEmitting = false;
}
}
darkness_think( lights )
{
level notify( "lights_off" );
flag_clear( "lights_back_on" );
thread darkness_ai_setup();
thread darkness_stop_wait( lights.size );
}
darkness_ai_setup()
{
// tally kills made in the dark for achievement
thread tally_dark_kills();
thread darkness_battlechatter();
ais = GetAIArray();
array_thread( ais, ::darkness_ai_think );
spawners = GetSpawnerArray();
for( i = 0; i < spawners.size; i++ )
{
spawners[i] thread darkness_ai_spawnerthread();
}
}
darkness_battlechatter()
{
thread battlechatter_off( "allies" );
thread battlechatter_off( "axis" );
flag_wait( "lights_back_on" );
wait( 1.5 ); // in case we're saying scripted lines
thread battlechatter_on( "allies" );
thread battlechatter_on( "axis" );
}
darkness_ai_spawnerthread()
{
level endon( "lights_back_on" );
while( 1 )
{
self waittill( "spawned", spawn );
if( maps\_utility::spawn_failed( spawn ) )
{
continue;
}
wait( 0.05 );
spawn thread darkness_ai_think();
}
}
darkness_ai_think()
{
self endon( "death" );
// MGers don't care about the dark, ever!
if( IsDefined( self.isMGer ) )
{
return;
}
if( self.team == "axis" )
{
self thread dark_playerkill_wait();
}
//self thread darkness_goal_management(); // DEPRECATED
self.ignoreall = true;
self.ignoreme = true;
self thread darkness_proxcheck();
if( get_players().size < 2 )
{
self thread darkness_randomfire();
}
else
{
self thread darkness_coop_unignore();
}
level waittill( "lights_back_on" );
self.ignoreall = false;
self.ignoreme = false;
}
darkness_coop_unignore()
{
self endon( "death" );
wait( RandomFloatRange( 2 ) );
if( is_active_ai( self ) )
{
self.ignoreall = false;
self.ignoreme = false;
}
}
/* DEPRECATED - it's more fun to see the AIs run around in the dark
darkness_goal_management()
{
self endon( "death" );
targetNode = undefined;
// enemy
if( self.team == "axis" )
{
if( IsDefined( self.target ) )
{
targetNode = getnode_safe( self.target, "targetname" );
if( Distance( targetNode.origin, self.origin ) <= 128 )
{
self waittill( "goal" );
}
}
if( !flag( "lights_back_on" ) )
{
self SetGoalPos( self.origin );
}
flag_wait( "lights_back_on" );
if( !IsDefined( self.fallback_node ) )
{
if( IsDefined( targetNode ) )
{
self SetGoalNode( targetNode );
}
}
}
// friendly
else
{
// don't want to mess up existing bullet shields
if( !IsDefined( self.magic_bullet_shield ) || !self.magic_bullet_shield )
{
self thread magic_bullet_shield_safe();
self.darkness_allied_bullet_shield = true;
}
self SetGoalPos( self.origin );
self AllowedStances( "crouch" );
self.og_forcecolor = self get_force_color();
self clear_force_color();
flag_wait( "lights_back_on" );
self AllowedStances( "stand", "crouch", "prone" );
self set_force_color( self.og_forcecolor );
// reset the executioner
if( IsDefined( self.darkness_allied_bullet_shield ) && self.darkness_allied_bullet_shield )
{
self thread stop_magic_bullet_shield_safe();
}
}
}
*/
darkness_proxcheck()
{
level endon( "lights_back_on" );
self endon( "death" );
alertDist = 500;
alertDist *= alertDist; // units
// wait for an enemy to get close
while( 1 )
{
enemies = undefined;
if( self.team == "axis" )
{
enemies = GetAIArray( "allies" );
enemies = array_combine( enemies, get_players() );
}
else
{
enemies = GetAIArray( "axis" );
}
enemy = undefined;
for( i = 0; i < enemies.size; i++ )
{
if( DistanceSquared( enemies[i].origin, self.origin ) < alertDist )
{
self.ignoreall = false;
enemy = enemies[i];
break;
}
}
if( IsDefined( enemy ) )
{
self notify( "enemy_found_in_the_dark" );
// TODO fix or rip out
// this doesn't work because the target origin is inside the enemy
//self.targetOrg = Spawn( "script_model", enemy.origin + ( 0, 0, 48 ) );
//self.targetOrg LinkTo( enemy );
//self SetEntityTarget( self.targetOrg );
self thread darkness_reset_target( enemy );
delayThread( RandomFloatRange( 1.5, 3 ), ::scr_ignoreme, false );
self waittill( "clear_darkness_target" );
/* TODO fix or rip out
if( IsDefined( self.targetOrg ) )
{
self.targetOrg Delete();
}
*/
}
wait( 0.25 );
}
}
darkness_reset_target( enemy )
{
self endon( "death" );
self thread darkness_target_reset_because_lights();
self thread darkness_target_reset_because_targetdead( enemy );
self waittill( "clear_darkness_target" );
// TODO fix or rip out
//self ClearEntityTarget();
}
darkness_target_reset_because_lights()
{
self endon( "clear_darkness_target" );
self endon( "death" );
level waittill( "lights_back_on" );
self notify( "clear_darkness_target" );
}
darkness_target_reset_because_targetdead( enemy )
{
self endon( "clear_darkness_target" );
self endon( "death" );
enemy waittill( "death" );
self notify( "clear_darkness_target" );
}
darkness_randomfire()
{
level endon( "lights_back_on" );
self endon( "death" );
self endon( "enemy_found_in_the_dark" );
waitMin = 1;
waitMax = 4;
while( 1 )
{
wait( RandomFloatRange( waitMin, waitMax ) );
if( self.ignoreall )
{
self.ignoreall = false;
}
if( !self.ignoreall && self darkness_ai_player_nearby() )
{
self.ignoreall = true;
}
}
}
darkness_ai_player_nearby()
{
alertDist = 500;
alertDist *= alertDist; // units
players = get_players();
foundOne = false;
for( i = 0; i < players.size; i++ )
{
if( DistanceSquared( players[i].origin, self.origin ) < alertDist )
{
foundOne = true;
break;
}
}
return foundOne;
}
dark_playerkill_wait()
{
level endon( "lights_back_on" );
self waittill( "death" );
if( IsDefined( self.attacker ) && IsPlayer( self.attacker ) )
{
player = self.attacker;
if( !IsDefined( player.ber2_dark_kills ) )
{
player.ber2_dark_kills = 0;
}
player.ber2_dark_kills++;
}
}
tally_dark_kills()
{
level endon( "lights_back_on" );
// wait for players to get the cheeve
while( 1 )
{
players = get_players();
for( i = 0; i < players.size; i++ )
{
if( !IsDefined( players[i].ber2_dark_kills ) )
{
continue;
}
if( players[i].ber2_dark_kills > 10 )
{
if( !IsDefined( players[i].ber2_dark_kill_got_cheeve ) )
{
players[i].ber2_dark_kill_got_cheeve = true;
players[i] GiveAchievement( "BER2_ACHIEVEMENT_KILL10" );
arcademode_assignpoints( "arcademode_score_generic1000", players[i] );
}
}
}
wait( 0.1 );
}
}
darkness_stop_wait( numLights )
{
onFrac = 0.65;
// wait for an acceptable fraction of the lights to come back on
while( level.arty_flickerlights_on < ( numLights * onFrac ) )
{
wait( 0.1 );
}
// stop tallying dark kills when the lights come back up
flag_set( "lights_back_on" );
}
// --- end metro arty impact stuff ---
event2_action_dialogue()
{
trigger_wait( "trig_floodspawner_mgRight", "script_noteworthy" );
// "The place is collapsing."
level.sarge playsound_generic_facial( "Ber2_IGD_087A_REZN" );
// "Move."
level.sarge playsound_generic_facial( "Ber2_IGD_088A_REZN" );
redshirt = get_randomfriend_notsarge_excluding( level.hero1 );
// "We are going to be crushed - or buried alive!"
redshirt playsound_generic_facial( "Ber2_IGD_089A_RUR2" );
// "Move - faster!"
level.sarge playsound_generic_facial( "Ber2_IGD_090A_REZN" );
wait( 3 );
// "We need to find a way out!"
level.hero1 playsound_generic_facial( "Ber2_IGD_091A_CHER" );
// "We will..."
level.sarge playsound_generic_facial( "Ber2_IGD_092A_REZN" );
// "There will be an exit at the other end of the platform!"
level.sarge playsound_generic_facial( "Ber2_IGD_093A_REZN" );
// "We will regroup there..."
level.sarge playsound_generic_facial( "Ber2_IGD_202A_REZN" );
}
// --- DIFFERENT ANIMTREE ---
#using_animtree( "ber2_rat" );
metrowave_rat_anims( movetime )
{
self endon( "rat_stop_anims" );
self UseAnimTree( #animtree );
fx_splash = level._effect["rat_splash"];
waterHeight = -590;
animHop = level.scr_anim["rat"]["hop_loop"];
animRun = level.scr_anim["rat"]["run_loop"];
hopChance = 65; // percent out of 100
anime = animHop;
runTime = 2;
while( 1 )
{
if( !IsDefined( self ) )
{
break;
}
if( RandomInt( 100 ) < hopChance )
{
if( !level.coopOptimize )
{
self thread metrowave_rat_anim_splash( fx_splash, waterHeight );
}
anime = animHop;
self SetFlaggedAnimKnob( "rat_anim", anime, 1.0, 0.2, 1.0 );
self waittillmatch( "rat_anim", "end" );
}
else
{
anime = animRun;
endTime = GetTime() + ( RandomFloatRange( 0.5, 1.5 ) * 1000 );
while( GetTime() < endTime )
{
if( !level.coopOptimize )
{
if( RandomInt( 100 ) < 25 )
{
PlayFX( fx_splash, ( self.origin[0], self.origin[1], waterHeight ) );
}
}
self SetFlaggedAnimKnob( "rat_anim", anime, 1.0, 0.2, 1.0 );
self waittillmatch( "rat_anim", "end" );
}
}
}
}
metrowave_rat_anim_splash( fx_splash, waterHeight )
{
wait( 0.1 );
PlayFX( fx_splash, ( self.origin[0], self.origin[1], waterHeight ) );
wait( 0.4 );
PlayFX( fx_splash, ( self.origin[0], self.origin[1], waterHeight ) );
}
#using_animtree( "ber2_metro_exit_door" );
// self = the subway exit door
metro_exitdoor_anim( animeName )
{
anime = undefined;
switch( animeName )
{
case "doorstuck1":
anime = level.scr_anim["metro_door_sbmodel"]["doorstuck1"];
break;
case "doorstuck2":
anime = level.scr_anim["metro_door_sbmodel"]["doorstuck2"];
break;
case "doorstuck3":
anime = level.scr_anim["metro_door_sbmodel"]["doorstuck3"];
break;
case "success":
anime = level.scr_anim["metro_door_sbmodel"]["success"];
break;
default:
ASSERTMSG( "metro_exitdoor_anim(): door animation type '" + animeName + "' not recognized." );
}
org = Spawn( "script_model", self.origin );
org SetModel( "tag_origin_animate" );
self LinkTo( org, "origin_animate_jnt" );
org UseAnimTree( #animtree );
org SetFlaggedAnimKnob( "metrodoor_anim", anime, 1.0, 0.2, 1.0 );
org waittillmatch( "metrodoor_anim", "end" );
self Unlink();
wait( 0.1 );
org Delete();
}