#include maps/mp/_scoreevents; #include maps/mp/gametypes/_globallogic_audio; #include maps/mp/_popups; #include maps/mp/gametypes/_damagefeedback; #include maps/mp/gametypes/_globallogic_player; #include maps/mp/gametypes/_weaponobjects; #include maps/mp/_heatseekingmissile; #include maps/mp/killstreaks/_killstreakrules; #include maps/mp/_challenges; #include maps/mp/gametypes/_hostmigration; #include maps/mp/killstreaks/_radar; #include maps/mp/gametypes/_spawnlogic; #include maps/mp/gametypes/_battlechatter_mp; #include maps/mp/killstreaks/_airsupport; #include common_scripts/utility; #include maps/mp/gametypes/_hud_util; #include maps/mp/_utility; init() { level.spyplanemodel = "veh_t6_drone_uav"; level.counteruavmodel = "veh_t6_drone_cuav"; level.u2_maxhealth = 700; level.spyplane = []; level.spyplaneentrancetime = 5; level.spyplaneexittime = 10; level.counteruavweapon = "counteruav_mp"; level.counteruavlength = 25; precachemodel( level.spyplanemodel ); precachemodel( level.counteruavmodel ); level.counteruavplaneentrancetime = 5; level.counteruavplaneexittime = 10; level.counteruavlight = loadfx( "vehicle/light/fx_cuav_lights_red" ); level.uavlight = loadfx( "vehicle/light/fx_u2_lights_red" ); level.fx_spyplane_afterburner = loadfx( "vehicle/exhaust/fx_exhaust_u2_spyplane_afterburner" ); level.fx_spyplane_burner = loadfx( "vehicle/exhaust/fx_exhaust_u2_spyplane_burner" ); level.fx_cuav_afterburner = loadfx( "vehicle/exhaust/fx_exhaust_cuav_afterburner" ); level.fx_cuav_burner = loadfx( "vehicle/exhaust/fx_exhaust_cuav_burner" ); level.satelliteheight = 10000; level.satelliteflydistance = 10000; level.fx_u2_damage_trail = loadfx( "trail/fx_trail_u2_plane_damage_mp" ); level.fx_u2_explode = loadfx( "vehicle/vexplosion/fx_vexplode_u2_exp_mp" ); minimaporigins = getentarray( "minimap_corner", "targetname" ); if ( minimaporigins.size ) { uavorigin = maps/mp/gametypes/_spawnlogic::findboxcenter( minimaporigins[ 0 ].origin, minimaporigins[ 1 ].origin ); } else { uavorigin = ( 0, 0, 1 ); } if ( level.script == "mp_hydro" ) { uavorigin += vectorScale( ( 0, 0, 1 ), 1200 ); } if ( level.teambased ) { _a54 = level.teams; _k54 = getFirstArrayKey( _a54 ); while ( isDefined( _k54 ) ) { team = _a54[ _k54 ]; level.activeuavs[ team ] = 0; level.activecounteruavs[ team ] = 0; level.activesatellites[ team ] = 0; _k54 = getNextArrayKey( _a54, _k54 ); } } else level.activeuavs = []; level.activecounteruavs = []; level.activesatellites = []; level.uavrig = spawn( "script_model", uavorigin + vectorScale( ( 0, 0, 1 ), 1100 ) ); level.uavrig setmodel( "tag_origin" ); level.uavrig.angles = vectorScale( ( 0, 0, 1 ), 115 ); level.uavrig hide(); level.uavrig thread rotateuavrig( 1 ); level.uavrig thread swayuavrig(); level.counteruavrig = spawn( "script_model", uavorigin + vectorScale( ( 0, 0, 1 ), 1500 ) ); level.counteruavrig setmodel( "tag_origin" ); level.counteruavrig.angles = vectorScale( ( 0, 0, 1 ), 115 ); level.counteruavrig hide(); level.counteruavrig thread rotateuavrig( 0 ); level.counteruavrig thread swayuavrig(); level thread uavtracker(); level thread onplayerconnect(); } onplayerconnect() { for ( ;; ) { level waittill( "connected", player ); player.entnum = player getentitynumber(); level.activeuavs[ player.entnum ] = 0; level.activecounteruavs[ player.entnum ] = 0; level.activesatellites[ player.entnum ] = 0; if ( level.teambased == 0 || level.multiteam == 1 ) { player thread watchffaandmultiteamspawn(); } } } watchffaandmultiteamspawn() { self endon( "disconnect" ); for ( ;; ) { self waittill( "spawned_player" ); level notify( "uav_update" ); } } rotateuavrig( clockwise ) { turn = 360; if ( clockwise ) { turn = -360; } for ( ;; ) { if ( !clockwise ) { self rotateyaw( turn, 40 ); wait 40; continue; } else { self rotateyaw( turn, 60 ); wait 60; } } } swayuavrig() { centerorigin = self.origin; for ( ;; ) { z = randomintrange( -200, -100 ); time = randomintrange( 3, 6 ); self moveto( centerorigin + ( 0, 0, z ), time, 1, 1 ); wait time; z = randomintrange( 100, 200 ); time = randomintrange( 3, 6 ); self moveto( centerorigin + ( 0, 0, z ), time, 1, 1 ); wait time; } } callcounteruav( type, displaymessage, killstreak_id ) { timeinair = self maps/mp/killstreaks/_radar::useradaritem( type, self.team, displaymessage ); iscounter = 1; counteruavplane = generateplane( self, timeinair, iscounter ); if ( !isDefined( counteruavplane ) ) { return 0; } counteruavplane thread counteruav_watchfor_gamerules_destruction( self ); counteruavplane setclientflag( 11 ); counteruavplane addactivecounteruav(); self.counteruavtime = getTime(); counteruavplane thread playcounterspyplanefx(); counteruavplane thread counteruavplane_death_waiter(); counteruavplane thread counteruavplane_timeout( timeinair, self ); counteruavplane thread plane_damage_monitor( 0 ); counteruavplane thread plane_health(); counteruavplane.killstreak_id = killstreak_id; counteruavplane.iscounter = 1; counteruavplane playloopsound( "veh_uav_engine_loop", 1 ); return 1; } callspyplane( type, displaymessage, killstreak_id ) { timeinair = self maps/mp/killstreaks/_radar::useradaritem( type, self.team, displaymessage ); iscounter = 0; spyplane = generateplane( self, timeinair, iscounter ); if ( !isDefined( spyplane ) ) { return 0; } spyplane thread spyplane_watchfor_gamerules_destruction( self ); spyplane addactiveuav(); self.uavtime = getTime(); spyplane.leaving = 0; spyplane thread playspyplanefx(); spyplane thread spyplane_timeout( timeinair, self ); spyplane thread spyplane_death_waiter(); spyplane thread plane_damage_monitor( 1 ); spyplane thread plane_health(); spyplane.killstreak_id = killstreak_id; spyplane.iscounter = 0; spyplane playloopsound( "veh_uav_engine_loop", 1 ); return 1; } callsatellite( type, displaymessage, killstreak_id ) { timeinair = self maps/mp/killstreaks/_radar::useradaritem( type, self.team, displaymessage ); satellite = spawn( "script_model", level.mapcenter + ( 0 - level.satelliteflydistance, 0, level.satelliteheight ) ); satellite setmodel( "tag_origin" ); satellite moveto( level.mapcenter + ( level.satelliteflydistance, 0, level.satelliteheight ), timeinair ); satellite.owner = self; satellite.team = self.team; satellite setteam( self.team ); satellite setowner( self ); satellite.targetname = "satellite"; satellite addactivesatellite(); self.satellitetime = getTime(); satellite thread satellite_timeout( timeinair, self ); satellite thread satellite_watchfor_gamerules_destruction( self ); satellite.iscounter = 0; if ( level.teambased ) { satellite thread updatevisibility(); } satellite.killstreak_id = killstreak_id; return 1; } spyplane_watchfor_gamerules_destruction( player ) { self endon( "death" ); self endon( "crashing" ); self endon( "delete" ); player waittill_any( "joined_team", "disconnect", "joined_spectators" ); self spyplane_death(); } counteruav_watchfor_gamerules_destruction( player ) { self endon( "death" ); self endon( "crashing" ); self endon( "delete" ); player waittill_any( "joined_team", "disconnect", "joined_spectators" ); maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); self counteruavplane_death(); } satellite_watchfor_gamerules_destruction( player ) { self endon( "death" ); self endon( "delete" ); player waittill_any( "joined_team", "disconnect", "joined_spectators" ); maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); self removeactivesatellite(); self delete(); } addactivecounteruav() { if ( level.teambased ) { self.owner.activecounteruavs++; level.activecounteruavs[ self.team ]++; _a284 = level.teams; _k284 = getFirstArrayKey( _a284 ); while ( isDefined( _k284 ) ) { team = _a284[ _k284 ]; if ( team == self.team ) { } else { if ( level.activesatellites[ team ] > 0 ) { self.owner maps/mp/_challenges::blockedsatellite(); } } _k284 = getNextArrayKey( _a284, _k284 ); } } else /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activecounteruavs[ self.owner.entnum ]++; keys = getarraykeys( level.activecounteruavs ); i = 0; while ( i < keys.size ) { if ( keys[ i ] == self.owner.entnum ) { i++; continue; } else { if ( level.activecounteruavs[ keys[ i ] ] ) { self.owner maps/mp/_challenges::blockedsatellite(); break; } } else { i++; } } level notify( "uav_update" ); } addactiveuav() { if ( level.teambased ) { self.owner.activeuavs++; level.activeuavs[ self.team ]++; } else { /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activeuavs[ self.owner.entnum ]++; } level notify( "uav_update" ); } addactivesatellite() { if ( level.teambased ) { self.owner.activesatellites++; level.activesatellites[ self.team ]++; } else { /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activesatellites[ self.owner.entnum ]++; } level notify( "uav_update" ); } removeactiveuav() { if ( level.teambased ) { if ( isDefined( self.owner ) && self.owner.spawntime < self.birthtime ) { self.owner.activeuavs--; /# assert( self.owner.activeuavs >= 0 ); #/ if ( self.owner.activeuavs < 0 ) { self.owner.activeuavs = 0; } } level.activeuavs[ self.team ]--; /# assert( level.activeuavs[ self.team ] >= 0 ); #/ if ( level.activeuavs[ self.team ] < 0 ) { level.activeuavs[ self.team ] = 0; } } else { if ( isDefined( self.owner ) ) { /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activeuavs[ self.owner.entnum ]--; /# assert( level.activeuavs[ self.owner.entnum ] >= 0 ); #/ if ( level.activeuavs[ self.owner.entnum ] < 0 ) { level.activeuavs[ self.owner.entnum ] = 0; } } } maps/mp/killstreaks/_killstreakrules::killstreakstop( "radar_mp", self.team, self.killstreak_id ); level notify( "uav_update" ); } removeactivecounteruav() { if ( level.teambased ) { if ( isDefined( self.owner ) && self.owner.spawntime < self.birthtime ) { self.owner.activecounteruavs--; /# assert( self.owner.activecounteruavs >= 0 ); #/ if ( self.owner.activecounteruavs < 0 ) { self.owner.activecounteruavs = 0; } } level.activecounteruavs[ self.team ]--; /# assert( level.activecounteruavs[ self.team ] >= 0 ); #/ if ( level.activecounteruavs[ self.team ] < 0 ) { level.activecounteruavs[ self.team ] = 0; } } else { if ( isDefined( self.owner ) ) { /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activecounteruavs[ self.owner.entnum ]--; /# assert( level.activecounteruavs[ self.owner.entnum ] >= 0 ); #/ if ( level.activecounteruavs[ self.owner.entnum ] < 0 ) { level.activecounteruavs[ self.owner.entnum ] = 0; } } } maps/mp/killstreaks/_killstreakrules::killstreakstop( "counteruav_mp", self.team, self.killstreak_id ); level notify( "uav_update" ); } removeactivesatellite() { if ( level.teambased ) { if ( self.owner.spawntime < self.birthtime && isDefined( self.owner ) ) { self.owner.activesatellites--; /# assert( self.owner.activesatellites >= 0 ); #/ if ( self.owner.activesatellites < 0 ) { self.owner.activesatellites = 0; } } level.activesatellites[ self.team ]--; /# assert( level.activesatellites[ self.team ] >= 0 ); #/ if ( level.activesatellites[ self.team ] < 0 ) { level.activesatellites[ self.team ] = 0; } } else { if ( isDefined( self.owner ) ) { /# assert( isDefined( self.owner.entnum ) ); #/ if ( !isDefined( self.owner.entnum ) ) { self.owner.entnum = self.owner getentitynumber(); } level.activesatellites[ self.owner.entnum ]--; /# assert( level.activesatellites[ self.owner.entnum ] >= 0 ); #/ if ( level.activesatellites[ self.owner.entnum ] < 0 ) { level.activesatellites[ self.owner.entnum ] = 0; } } } maps/mp/killstreaks/_killstreakrules::killstreakstop( "radardirection_mp", self.team, self.killstreak_id ); level notify( "uav_update" ); } playspyplanefx() { wait 0,1; playfxontag( level.fx_spyplane_burner, self, "tag_origin" ); } playspyplaneafterburnerfx() { self endon( "death" ); wait 0,1; playfxontag( level.fx_spyplane_afterburner, self, "tag_origin" ); } playcounterspyplanefx() { wait 0,1; if ( isDefined( self ) ) { playfxontag( level.fx_cuav_burner, self, "tag_origin" ); } } playcounterspyplaneafterburnerfx() { self endon( "death" ); wait 0,1; playfxontag( level.fx_cuav_afterburner, self, "tag_origin" ); } playuavpilotdialog( dialog, owner, delaytime ) { if ( isDefined( delaytime ) ) { wait delaytime; } self.pilotvoicenumber = owner.bcvoicenumber + 1; soundalias = level.teamprefix[ owner.team ] + self.pilotvoicenumber + "_" + dialog; while ( isDefined( owner.pilotisspeaking ) ) { while ( owner.pilotisspeaking ) { while ( owner.pilotisspeaking ) { wait 0,2; } } } if ( isDefined( owner ) ) { owner playlocalsound( soundalias ); owner.pilotisspeaking = 1; owner thread waitplaybacktime( soundalias ); owner waittill_any( soundalias, "death", "disconnect" ); owner.pilotisspeaking = 0; } } generateplane( owner, timeinair, iscounter ) { uavrig = level.uavrig; attach_angle = -90; if ( iscounter ) { uavrig = level.counteruavrig; attach_angle = 90; } plane = spawn( "script_model", uavrig gettagorigin( "tag_origin" ) ); if ( iscounter ) { plane setmodel( level.counteruavmodel ); plane.targetname = "counteruav"; } else { plane setmodel( level.spyplanemodel ); plane.targetname = "uav"; } plane setteam( owner.team ); plane setowner( owner ); target_set( plane ); plane thread play_light_fx( iscounter ); plane.owner = owner; plane.team = owner.team; plane thread updatevisibility(); plane thread maps/mp/_heatseekingmissile::missiletarget_proximitydetonateincomingmissile( "crashing" ); level.plane[ self.team ] = plane; plane.health_low = level.u2_maxhealth * 0,4; plane.maxhealth = level.u2_maxhealth; plane.health = 99999; plane.rocketdamageoneshot = level.u2_maxhealth + 1; plane.rocketdamagetwoshot = ( level.u2_maxhealth / 2 ) + 1; plane setdrawinfrared( 1 ); zoffset = randomintrange( 4000, 5000 ); angle = randomint( 360 ); if ( iscounter ) { radiusoffset = randomint( 1000 ) + 3000; } else { radiusoffset = randomint( 1000 ) + 4000; } xoffset = cos( angle ) * radiusoffset; yoffset = sin( angle ) * radiusoffset; anglevector = vectornormalize( ( xoffset, yoffset, zoffset ) ); anglevector *= randomintrange( 4000, 5000 ); if ( iscounter ) { plane linkto( uavrig, "tag_origin", anglevector, ( 0, angle + attach_angle, -10 ) ); } else { plane linkto( uavrig, "tag_origin", anglevector, ( 0, angle + attach_angle, 0 ) ); } return plane; } play_light_fx( iscounter ) { self endon( "death" ); wait 0,1; if ( iscounter ) { playfxontag( level.counteruavlight, self, "tag_origin" ); } else { playfxontag( level.uavlight, self, "tag_origin" ); } } updatevisibility() { self endon( "death" ); for ( ;; ) { if ( level.teambased ) { self setvisibletoallexceptteam( self.team ); } else { self setvisibletoall(); self setinvisibletoplayer( self.owner ); } level waittill( "joined_team" ); } } debugline( frompoint, topoint, color, durationframes ) { /# i = 0; while ( i < ( durationframes * 20 ) ) { line( frompoint, topoint, color ); wait 0,05; i++; #/ } } plane_damage_monitor( isspyplane ) { self endon( "death" ); self endon( "crashing" ); self endon( "delete" ); self setcandamage( 1 ); self.damagetaken = 0; for ( ;; ) { self waittill( "damage", damage, attacker, direction, point, type, tagname, modelname, partname, weapon ); if ( !isDefined( attacker ) || !isplayer( attacker ) ) { continue; } else { friendlyfire = maps/mp/gametypes/_weaponobjects::friendlyfirecheck( self.owner, attacker ); if ( !friendlyfire ) { break; } else if ( isDefined( self.owner ) && attacker == self.owner ) { break; } else { isvalidattacker = 1; if ( level.teambased ) { if ( isDefined( attacker.team ) ) { isvalidattacker = attacker.team != self.team; } } if ( !isvalidattacker ) { break; } else { if ( maps/mp/gametypes/_globallogic_player::dodamagefeedback( weapon, attacker ) ) { attacker thread maps/mp/gametypes/_damagefeedback::updatedamagefeedback( type ); } self.attacker = attacker; switch( type ) { case "MOD_PISTOL_BULLET": case "MOD_RIFLE_BULLET": if ( attacker hasperk( "specialty_armorpiercing" ) ) { self.damagetaken += int( damage * level.cac_armorpiercing_data ); } else { self.damagetaken += damage; } break; case "MOD_PROJECTILE": self.damagetaken += self.rocketdamageoneshot; break; default: self.damagetaken += damage; break; } self.health += damage; if ( self.damagetaken > self.maxhealth ) { killstreakreference = "radar_mp"; if ( !isspyplane ) { killstreakreference = "counteruav_mp"; } attacker notify( "destroyed_spyplane" ); weaponstatname = "destroyed"; switch( weapon ) { case "auto_tow_mp": case "tow_turret_drop_mp": case "tow_turret_mp": weaponstatname = "kills"; break; } attacker addweaponstat( weapon, weaponstatname, 1 ); level.globalkillstreaksdestroyed++; attacker addweaponstat( killstreakreference, "destroyed", 1 ); maps/mp/_challenges::destroyedaircraft( attacker, weapon ); if ( isspyplane ) { level thread maps/mp/_popups::displayteammessagetoall( &"KILLSTREAK_DESTROYED_UAV", attacker ); if ( isDefined( self.owner ) ) { self.owner maps/mp/gametypes/_globallogic_audio::leaderdialogonplayer( "uav_destroyed", "item_destroyed" ); } if ( !isDefined( self.owner ) || self.owner isenemyplayer( attacker ) ) { thread maps/mp/_scoreevents::processscoreevent( "destroyed_uav", attacker, self.owner, weapon ); attacker maps/mp/_challenges::addflyswatterstat( weapon, self ); break; } spyplane_death(); } else { level thread maps/mp/_popups::displayteammessagetoall( &"KILLSTREAK_DESTROYED_COUNTERUAV", attacker ); if ( isDefined( self.owner ) ) { self.owner maps/mp/gametypes/_globallogic_audio::leaderdialogonplayer( "cuav_destroyed", "item_destroyed" ); } if ( !isDefined( self.owner ) || self.owner isenemyplayer( attacker ) ) { thread maps/mp/_scoreevents::processscoreevent( "destroyed_counter_uav", attacker, self.owner, weapon ); attacker maps/mp/_challenges::addflyswatterstat( weapon, self ); break; } counteruavplane_death(); } return; } } } } } } plane_health() { self endon( "death" ); self endon( "crashing" ); self.currentstate = "ok"; self.laststate = "ok"; while ( self.currentstate != "leaving" ) { if ( self.damagetaken >= self.health_low ) { self.currentstate = "damaged"; } if ( self.currentstate == "damaged" && self.laststate != "damaged" ) { self.laststate = self.currentstate; self thread playdamagefx(); } /# debug_print3d_simple( "Health: " + ( self.maxhealth - self.damagetaken ), self, vectorScale( ( 0, 0, 1 ), 100 ), 20 ); #/ wait 1; } } playdamagefx() { self endon( "death" ); self endon( "crashing" ); playfxontag( level.fx_u2_damage_trail, self, "tag_body" ); } u2_crash() { self notify( "crashing" ); playfxontag( level.fx_u2_explode, self, "tag_origin" ); wait 0,1; self setmodel( "tag_origin" ); wait 0,2; self notify( "delete" ); self delete(); } counteruavplane_death_waiter() { self endon( "delete" ); self endon( "leaving" ); self waittill( "death" ); counteruavplane_death(); } spyplane_death_waiter() { self endon( "delete" ); self endon( "leaving" ); self waittill( "death" ); spyplane_death(); } counteruavplane_death() { self clearclientflag( 11 ); self playsound( "evt_helicopter_midair_exp" ); self removeactivecounteruav(); target_remove( self ); self thread u2_crash(); } spyplane_death() { self playsound( "evt_helicopter_midair_exp" ); if ( !self.leaving ) { self removeactiveuav(); } target_remove( self ); self thread u2_crash(); } counteruavplane_timeout( timeinair, owner ) { self endon( "death" ); self endon( "delete" ); maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); timeremaining = timeinair * 1000; self waittilltimeoutmigrationaware( timeremaining, owner ); self clearclientflag( 11 ); self plane_leave(); wait level.counteruavplaneexittime; self removeactivecounteruav(); target_remove( self ); self delete(); } satellite_timeout( timeinair, owner ) { self endon( "death" ); self endon( "delete" ); maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); timeremaining = timeinair * 1000; self waittilltimeoutmigrationaware( timeremaining, owner ); self removeactivesatellite(); self delete(); } watchforemp() { self endon( "death" ); self endon( "delete" ); self waittill( "emp_deployed", attacker ); weapon = "emp_mp"; maps/mp/_challenges::destroyedaircraft( attacker, weapon ); thread maps/mp/_scoreevents::processscoreevent( "destroyed_satellite", attacker, self.owner, weapon ); attacker maps/mp/_challenges::addflyswatterstat( weapon, self ); self removeactivesatellite(); self delete(); } spyplane_timeout( timeinair, owner ) { self endon( "death" ); self endon( "delete" ); self endon( "crashing" ); maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); timeremaining = timeinair * 1000; self waittilltimeoutmigrationaware( timeremaining, owner ); self plane_leave(); self.leaving = 1; self removeactiveuav(); wait level.spyplaneexittime; target_remove( self ); self delete(); } waittilltimeoutmigrationaware( timeremaining, owner ) { owner endon( "disconnect" ); for ( ;; ) { self.endtime = getTime() + timeremaining; event = level waittill_any_timeout( timeremaining / 1000, "game_ended", "host_migration_begin" ); if ( event != "host_migration_begin" ) { return; } else timeremaining = self.endtime - getTime(); if ( timeremaining <= 0 ) { return; } else { maps/mp/gametypes/_hostmigration::waittillhostmigrationdone(); } } } planestoploop( time ) { self endon( "death" ); wait time; self stoploopsound(); } plane_leave() { self unlink(); if ( isDefined( self.iscounter ) && self.iscounter ) { self thread playcounterspyplaneafterburnerfx(); self playsound( "veh_kls_uav_afterburner" ); self thread play_light_fx( 1 ); self thread planestoploop( 1 ); } else { self thread playspyplaneafterburnerfx(); self playsound( "veh_kls_spy_afterburner" ); self thread play_light_fx( 0 ); self thread planestoploop( 1 ); } self.currentstate = "leaving"; if ( self.laststate == "damaged" ) { playfxontag( level.fx_u2_damage_trail, self, "tag_body" ); } mult = getdvarintdefault( "scr_spymult", 20000 ); tries = 10; yaw = 0; while ( tries > 0 ) { exitvector = anglesToForward( self.angles + ( 0, yaw, 0 ) ) * 20000; if ( isDefined( self.iscounter ) && self.iscounter ) { self thread playcounterspyplanefx(); exitvector *= 1; } exitpoint = ( self.origin[ 0 ] + exitvector[ 0 ], self.origin[ 1 ] + exitvector[ 1 ], self.origin[ 2 ] - 2500 ); exitpoint = self.origin + exitvector; nfz = crossesnoflyzone( self.origin, exitpoint ); if ( isDefined( nfz ) ) { if ( tries != 1 ) { if ( ( tries % 2 ) == 1 ) { yaw *= -1; tries--; continue; } else { yaw += 10; yaw *= -1; } } tries--; continue; } else { tries = 0; } } self thread flattenyaw( self.angles[ 1 ] + yaw ); if ( self.angles[ 2 ] != 0 ) { self thread flattenroll(); } self moveto( exitpoint, level.spyplaneexittime, 0, 0 ); self notify( "leaving" ); } flattenroll() { self endon( "death" ); while ( self.angles[ 2 ] < 0 ) { self.angles = ( self.angles[ 0 ], self.angles[ 1 ], self.angles[ 2 ] + 2,5 ); wait 0,05; } } flattenyaw( goal ) { self endon( "death" ); increment = 3; if ( self.angles[ 1 ] > goal ) { increment *= -1; } while ( abs( self.angles[ 1 ] - goal ) > 3 ) { self.angles = ( self.angles[ 0 ], self.angles[ 1 ] + increment, self.angles[ 2 ] ); wait 0,05; } } uavtracker() { level endon( "game_ended" ); for ( ;; ) { level waittill( "uav_update" ); if ( level.teambased ) { _a1102 = level.teams; _k1102 = getFirstArrayKey( _a1102 ); while ( isDefined( _k1102 ) ) { team = _a1102[ _k1102 ]; updateteamuavstatus( team ); _k1102 = getNextArrayKey( _a1102, _k1102 ); } } else updateplayersuavstatus(); } } updateteamuavstatus( team ) { activeuavs = level.activeuavs[ team ]; activesatellites = level.activesatellites[ team ]; radarmode = 1; if ( activesatellites > 0 ) { maps/mp/killstreaks/_radar::setteamspyplanewrapper( team, 0 ); maps/mp/killstreaks/_radar::setteamsatellitewrapper( team, 1 ); return; } maps/mp/killstreaks/_radar::setteamsatellitewrapper( team, 0 ); if ( !activeuavs ) { maps/mp/killstreaks/_radar::setteamspyplanewrapper( team, 0 ); return; } if ( activeuavs > 1 ) { radarmode = 2; } maps/mp/killstreaks/_radar::setteamspyplanewrapper( team, radarmode ); } updateplayersuavstatus() { i = 0; while ( i < level.players.size ) { player = level.players[ i ]; /# assert( isDefined( player.entnum ) ); #/ if ( !isDefined( player.entnum ) ) { player.entnum = player getentitynumber(); } activeuavs = level.activeuavs[ player.entnum ]; activesatellites = level.activesatellites[ player.entnum ]; if ( activesatellites > 0 ) { player.hassatellite = 1; player.hasspyplane = 0; player setclientuivisibilityflag( "radar_client", 1 ); i++; continue; } else player.hassatellite = 0; if ( activeuavs == 0 && isDefined( player.pers[ "hasRadar" ] ) && !player.pers[ "hasRadar" ] ) { player.hasspyplane = 0; player setclientuivisibilityflag( "radar_client", 0 ); i++; continue; } else { if ( activeuavs > 1 ) { spyplaneupdatespeed = 2; } else { spyplaneupdatespeed = 1; } player setclientuivisibilityflag( "radar_client", 1 ); player.hasspyplane = spyplaneupdatespeed; } i++; } }