boiii-scripts/mp/mp_metro_train.gsc
2023-04-13 17:30:38 +02:00

619 lines
16 KiB
Plaintext

#using scripts\mp\_events;
#using scripts\mp\_util;
#using scripts\mp\gametypes\ctf;
#using scripts\mp\killstreaks\_supplydrop;
#using scripts\codescripts\struct;
#using scripts\shared\clientfield_shared;
#using scripts\shared\exploder_shared;
#using scripts\shared\gameobjects_shared;
#using scripts\shared\util_shared;
#using scripts\shared\weapons\_weaponobjects;
#precache( "fx", "light/fx_light_red_train_track_warning" );
#precache( "fx", "water/fx_water_train_mist_kick_up_metro" );
function init()
{
level.train_positions = [];
level.train_angles = [];
start1 = GetVehicleNode( "train_start_1", "targetname" );
start2 = GetVehicleNode( "train_start_2", "targetname" );
cars1 = [];
cars2 = [];
dividers1 = [];
dividers2 = [];
spawn_start_train( cars1, dividers1, start1, "train1" );
spawn_start_train( cars2, dividers2, start2, "train2" );
gate_inner_left = getentarray("metro_doors_inside_left", "targetname");
gate_outer_left = getentarray("metro_doors_outside_left", "targetname");
gate_end_left = getentarray("metro_doors_end_left", "targetname");
gate_speakers_left = struct::get_array( "metro_train_track_vox_left" );
gate_inner_right = getentarray("metro_doors_inside_right", "targetname");
gate_outer_right = getentarray("metro_doors_outside_right", "targetname");
gate_end_right = getentarray("metro_doors_end_right", "targetname");
gate_speakers_right = struct::get_array( "metro_train_track_vox_right" );
gate_kill_left = getent("train_killtrigger_left", "targetname");
gate_kill_right = getent("train_killtrigger_right", "targetname");
gate_end_kill_left = getent("train_killtrigger_left_end", "targetname");
gate_end_kill_right = getent("train_killtrigger_right_end", "targetname");
security_barriers_1 = getEntArray( "mp_metro_platform_edge_left", "targetname" );
security_barriers_2 = getEntArray( "mp_metro_platform_edge_right", "targetname" );
level._effect[ "fx_light_red_train_track_warning" ] = "light/fx_light_red_train_track_warning";
level._effect[ "fx_water_train_mist_kick_up_metro" ] = "water/fx_water_train_mist_kick_up_metro";
waittillframeend;
if ( level.timelimit )
{
seconds = level.timelimit * 60;
events::add_timed_event( Int( seconds * 0.25 ), "train_start_1" );
events::add_timed_event( Int( seconds * 0.75 ), "train_start_2" );
}
else if ( level.scorelimit )
{
events::add_score_event( Int( level.scorelimit * 0.25 ), "train_start_1" );
events::add_score_event( Int( level.scorelimit * 0.75 ), "train_start_2" );
}
else if( level.roundScoreLimit )
{
events::add_round_score_event( Int( level.roundScoreLimit * 0.25 ), "train_start_1" );
events::add_round_score_event( Int( level.roundScoreLimit * 0.75 ), "train_start_2" );
}
wait ( 1 );
if ( level.gameType == "escort" )
{
return;
}
level thread train_think( cars1, dividers1, "train_start_1", start1, gate_inner_left, gate_outer_left, gate_end_left, security_barriers_1, gate_kill_right, gate_end_kill_right, gate_speakers_right, "right" );
level thread train_think( cars2, dividers2, "train_start_2", start2, gate_inner_right, gate_outer_right, gate_end_right, security_barriers_2, gate_kill_left, gate_end_kill_left, gate_speakers_left, "left" );
}
function setup_gate( gate, gate_kill )
{
gate SetMovingPlatformEnabled(true);
gate.gate_kill = gate_kill;
gate.gate_kill EnableLinkTo();
gate.gate_kill LinkTo( gate );
}
function spawn_start_train( &cars, &dividers, start, name )
{
cars[0] = SpawnVehicle( "train_test_mp", (0,-2000,-200), (0, 0, 0), name );
cars[0] setteam( "neutral" );
cars[0] Ghost();
cars[0].isMagicBullet = true;
max_cars = getdvarint( "train_length", 10 );
for( i = 1; i < max_cars; i++ )
{
if( i == max_cars - 1 )
{
cars[i] = Spawn( "script_model", (0,-2000,-200) );
cars[i] SetModel( "p7_zur_metro_train_cab_module" );
cars[i].rotate180 = true;
}
else
{
cars[i] = Spawn( "script_model", (0,-2000,-200) );
cars[i] SetModel( "p7_zur_metro_train_car_module" );
}
cars[i] Ghost();
dividers[i] = Spawn( "script_model", (0,-2000,-200) );
dividers[i] SetModel( "p7_zur_metro_train_divider" );
dividers[i] Ghost();
}
}
function showAfterTime( time )
{
wait ( time ) ;
self Show();
}
function rotatePieces( gatePieceArray, waitTime, rotateTime, rotateAngles, startFromTop )
{
skip = startFromTop;
foreach( gatePiece in gatePieceArray )
{
if ( !skip )
{
gatePiece rotateTo( gatePiece.originalAngles + rotateAngles, rotateTime );
wait ( waitTime );
}
skip = !skip;
}
foreach( gatePiece in gatePieceArray )
{
if ( !skip )
{
gatePiece rotateTo( gatePiece.originalAngles + rotateAngles, rotateTime );
wait ( waitTime );
}
skip = !skip;
}
}
function train_think( cars, dividers, notifier, start, gate_a, gate_b, gate_end, security_barriers, gate_kill_trigger, gate_end_kill_trigger, train_speakers, trackside )
{
level endon ( "game_ended" );
foreach( gate in gate_a )
{
gate.originalAngles = gate.angles;
}
foreach( gate in gate_b )
{
gate.originalAngles = gate.angles;
}
foreach( gate in gate_end )
{
gate.originalAngles = gate.angles;
}
foreach( barrier in security_barriers )
{
barrier.originalOrigin = barrier.origin;
}
rotateDirection = ( 0, 90, 0 );
if ( trackside == "left" )
{
rotateDirection *= -1;
}
for ( ;; )
{
level waittill( notifier );
foreach( speaker in train_speakers )
{
PlaySoundAtPosition( "vox_metr_metro_approaching", speaker.origin );
}
metro_vox_wait_time = getdvarfloat( "metro_vox_wait_time", 4.0 );
wait( metro_vox_wait_time );
gate_move_time = getdvarfloat( "gate_move_time", 2.0 );
gate_end_move_time = getdvarfloat( "gate_end_move_time", 1.0 );
gate_piece_wait_time = getdvarfloat( "gate_wait_time", 0.3 );
gate_a[0] PlayLoopSound ( "amb_train_alarm" );
gate_b[0] PlayLoopSound ( "amb_train_alarm" );
barrier_move_time = getdvarfloat( "barrier_move_time", 2.0 );
barrier_move_height = getdvarfloat( "barrier_move_height", 30.0 );
foreach( barrier in security_barriers )
{
barrier moveto( barrier.origin + ( 0, 0 , barrier_move_height ), barrier_move_time );
barrier playsound ("evt_wall_up");
}
gate_wait_train_time = getdvarfloat( "gate_wait_train_time", 5.0 );
wait( gate_wait_train_time );
cars[0] AttachPath( start );
cars[0] StartPath();
cars[0] showAfterTime( 0.1 );
cars[0] thread record_positions(trackside);
cars[0] PlayLoopSound ( "amb_train_by" );
max_cars = getdvarint( "train_length", 10 );
for( i = 1; i < max_cars; i++ )
{
wait( .30 );
dividers[i] thread car_move(trackside);
dividers[i] thread watch_player_touch();
wait( .30 );
cars[i] thread car_move(trackside);
cars[i] thread watch_player_touch();
cars[i] PlayLoopSound ( "amb_train_by" );
}
foreach( speaker in train_speakers )
{
PlaySoundAtPosition( "vox_metr_metro_gap", speaker.origin );
}
level thread rotatePieces( gate_end, 1, gate_end_move_time, -rotateDirection, 0 );
gate_end[0] playsound ("evt_gate_open");
gate_end_kill_trigger security_door_close_think( false, 0, gate_end_move_time );
level thread rotatePieces( gate_a, gate_piece_wait_time, gate_move_time, rotateDirection, 0 );
gate_a[0] playsound ("evt_gate_open");
level thread rotatePieces( gate_b, gate_piece_wait_time, gate_move_time, rotateDirection, 1 );
gate_b[0] playsound ("evt_gate_open");
gate_kill_trigger security_door_close_think( true, 0, gate_move_time );
wait ( getdvarfloat( "gate_wait_close_door_end", 8.0 ) );
level thread rotatePieces( gate_end, 1, gate_move_time, (0,0,0), 0 );
gate_end[0] playsound ("evt_gate_close");
gate_end_kill_trigger security_door_close_think( false, 0, gate_move_time );
wait ( getdvarfloat( "gate_wait_close_doors", 4.0 ) );
level thread rotatePieces( gate_a, gate_piece_wait_time, gate_move_time, (0,0,0), 0 );
gate_a[0] playsound ("evt_gate_close");
level thread rotatePieces( gate_b, gate_piece_wait_time, gate_move_time, (0,0,0), 1 );
gate_b[0] playsound ("evt_gate_close");
gate_kill_trigger security_door_close_think( false, 0, gate_move_time );
gate_kill_trigger security_door_close_think( true, gate_move_time, 0.25 );
foreach( barrier in security_barriers )
{
barrier moveto(barrier.originalOrigin, barrier_move_time );
barrier playsound ("evt_wall_down");
}
gate_a[0] StopLoopSound ( 2 );
gate_b[0] StopLoopSound ( 2 );
cars[0] waittill( "reached_end_node" );
cars[0] StopLoopSound ( 2 );
for( i = 1; i < max_cars; i++ )
{
cars[i] ghost();
cars[i] notify( "stop_kill" );
dividers[i] ghost();
dividers[i] notify( "stop_kill" );
cars[i] StopLoopSound ( 2 );
}
cars[0] notify( "stop_kill" );
cars[0] ghost();
}
}
function record_positions( tracknum )
{
self endon( "reached_end_node" );
level.train_positions[tracknum] = [];
level.train_angles[tracknum] = [];
if ( tracknum == "left" )
{
train_position_start_water = getdvarint( "train_position_start_water_left", 205 );
train_dust_kickup_1 = getdvarint( "train_dust_kickup_1_left", 150 );
train_dust_kickup_2 = getdvarint( "train_dust_kickup_2_left", 174 );
train_dust_kickup_3 = getdvarint( "train_dust_kickup_3_left", 200 );
}
else
{
train_position_start_water = getdvarint( "train_position_start_water_right", 205 );
train_dust_kickup_1 = getdvarint( "train_dust_kickup_1_right", 150 );
train_dust_kickup_2 = getdvarint( "train_dust_kickup_1_right", 174 );
train_dust_kickup_3 = getdvarint( "train_dust_kickup_1_right", 200 );
}
for ( ;; )
{
if ( !isdefined( self ) )
return;
level.train_positions[tracknum][ level.train_positions[tracknum].size ] = self.origin;
level.train_angles[tracknum][ level.train_angles[tracknum].size ] = self.angles;
if ( level.train_angles[tracknum].size == train_position_start_water )
{
playfxontag( level._effect[ "fx_water_train_mist_kick_up_metro" ], self, "tag_origin" );
}
else if ( level.train_angles[tracknum].size == train_dust_kickup_1 )
{
level thread dust_kickup( 1, tracknum );
}
else if ( level.train_angles[tracknum].size == train_dust_kickup_2 )
{
level thread dust_kickup( 2, tracknum );
}
else if ( level.train_angles[tracknum].size == train_dust_kickup_3 )
{
level thread dust_kickup( 3, tracknum );
}
wait( 0.05 );
}
}
function dust_kickup( index, trackside )
{
exploderName = "Train_dust_kickup_" + index + "_" + trackside;
exploder::exploder( exploderName );
wait( 5.5 );
exploder::stop_exploder( exploderName );
}
function car_move( tracknum )
{
self endon( "stop_kill" );
if ( tracknum == "left" )
{
train_position_start_water = getdvarint( "train_position_start_water_left", 205 );
}
else
{
train_position_start_water = getdvarint( "train_position_start_water_right", 205 );
}
for( i = 0; i < level.train_positions[tracknum].size; i++ )
{
if ( i == train_position_start_water )
{
playfxontag( level._effect[ "fx_water_train_mist_kick_up_metro" ], self, "tag_origin" );
}
self.origin = level.train_positions[tracknum][ i ];
self.angles = level.train_angles[tracknum][ i ];
if ( isdefined( self.rotate180 ) && self.rotate180 == true )
{
self.angles += ( 0, 180, 0 );
}
wait( 0.05 );
if ( i == 4 )
{
self Show();
}
}
}
function watch_player_touch()
{
self endon( "end_of_track" );
self endon( "stop_kill" );
self endon( "delete" );
self endon( "death" );
self.disableFinalKillcam = true;
for(;;)
{
self waittill( "touch", entity );
if ( isplayer( entity ) )
{
entity DoDamage( entity.health * 2, self.origin + ( 0, 0, 1 ), self, self, 0, "MOD_CRUSH" );
}
}
}
function train_setup_clock()
{
metro_clock_1 = getent("MP_Metro_clock_1", "targetname");
metro_clock_2 = getent("MP_Metro_clock_2", "targetname");
if ( !isdefined( metro_clock_1 ) || !isdefined( metro_clock_2 ) )
{
return false;
}
level.clockModel1 = util::spawn_model( "tag_origin", metro_clock_1.origin, metro_clock_1.angles );
level.clockModel1 clientfield::set( "mp_metro_train_timer", 1 );
level.clockModel2 = util::spawn_model( "tag_origin", metro_clock_2.origin, metro_clock_2.angles );
level.clockModel2 clientfield::set( "mp_metro_train_timer", 1 );
return true;
}
function security_door_close_think( killPlayers, waittime, scantime )
{
self endon( "end_kill_trigger" );
self.disableFinalKillcam = true;
door = self;
corpse_delay = 0;
if ( waittime > 0 )
{
wait( waittime );
}
timescanned = 0;
while( scantime > timescanned )
{
// iprintlnbold("doing it" );
wait( 0.2 );
timescanned += 0.2;
entities = GetDamageableEntArray( self.origin, 200 );
foreach( entity in entities )
{
if ( !entity IsTouching( self ) )
{
continue;
}
if ( !IsAlive( entity ) )
{
continue;
}
if ( IsDefined( entity.targetname ) )
{
if ( entity.targetname == "talon" )
{
entity notify( "death" );
continue;
}
}
if ( IsDefined( entity.helitype ) && entity.helitype == "qrdrone" )
{
watcher = entity.owner weaponobjects::getWeaponObjectWatcher( "qrdrone" );
watcher thread weaponobjects::waitAndDetonate( entity, 0.0, undefined );
continue;
}
if ( entity.classname == "grenade" )
{
if( !IsDefined( entity.name ) )
{
continue;
}
if( !IsDefined( entity.owner ) )
{
continue;
}
if ( entity.name == "proximity_grenade_mp" )
{
watcher = entity.owner weaponobjects::getWatcherForWeapon( entity.name );
watcher thread weaponobjects::waitAndDetonate( entity, 0.0, undefined, "script_mover_mp" );
continue;
}
if( !entity.isEquipment )
{
continue;
}
watcher = entity.owner weaponobjects::getWatcherForWeapon( entity.name );
if( !IsDefined( watcher ) )
{
continue;
}
watcher thread weaponobjects::waitAndDetonate( entity, 0.0, undefined, "script_mover_mp" );
continue;
}
if ( entity.classname == "auto_turret" )
{
if ( !IsDefined( entity.damagedToDeath ) || !entity.damagedToDeath )
{
entity util::DoMaxDamage( self.origin + ( 0, 0, 1 ), self, self, 0, "MOD_CRUSH" );
}
continue;
}
if( IsVehicle( entity ) && ( !isdefined( entity.team ) || entity.team != "neutral" ) ) // vehicles are immune from MOD_CRUSH
{
entity kill();
continue;
}
if( killPlayers == false && IsPlayer( entity ) )
{
continue;
}
entity DoDamage( entity.health * 2, self.origin + ( 0, 0, 1 ), self, self, 0, "MOD_CRUSH" );
if( IsPlayer( entity ) )
{
corpse_delay = GetTime() + 1000;
}
}
self destroy_supply_crates();
if ( GetTime() > corpse_delay )
{
self destroy_corpses();
}
if ( level.gameType == "ctf" )
{
foreach( flag in level.flags )
{
if ( flag.visuals[0] IsTouching( self ) )
{
flag ctf::returnFlag();
}
}
}
else if ( level.gameType == "sd" && !level.multiBomb )
{
if ( level.sdBomb.visuals[0] IsTouching( self ) )
{
level.sdBomb gameobjects::return_home();
}
}
}
}
function destroy_supply_crates()
{
crates = GetEntArray( "care_package", "script_noteworthy" );
foreach( crate in crates )
{
if ( DistanceSquared( crate.origin, self.origin ) < 200 * 200 )
{
if( crate IsTouching( self ) )
{
PlayFX( level._supply_drop_explosion_fx, crate.origin );
PlaySoundAtPosition( "wpn_grenade_explode", crate.origin );
wait ( 0.1 );
crate supplydrop::crateDelete();
}
}
}
}
function destroy_corpses()
{
corpses = GetCorpseArray();
for ( i = 0; i < corpses.size; i++ )
{
if ( DistanceSquared( corpses[i].origin, self.origin ) < 200 * 200 )
{
corpses[i] delete();
}
}
}
function get_closest( org, array )
{
dist = 9999999;
distsq = dist*dist;
if( array.size < 1 )
{
return;
}
index = undefined;
for( i = 0;i < array.size;i++ )
{
newdistsq = distancesquared( array[ i ].origin, org );
if( newdistsq >= distsq )
{
continue;
}
distsq = newdistsq;
index = i;
}
return array[index];
}