#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, ÷rs, 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]; }