1 #using scripts\codescripts\struct;
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\damagefeedback_shared;
6 #using scripts\shared\gameobjects_shared;
7 #using scripts\shared\hostmigration_shared;
8 #using scripts\shared\hud_shared;
9 #using scripts\shared\math_shared;
10 #using scripts\shared\popups_shared;
11 #using scripts\shared\scoreevents_shared;
12 #using scripts\shared\util_shared;
13 #using scripts\shared\weapons\_heatseekingmissile;
14 #using scripts\shared\weapons\_weapon_utils;
15 #using scripts\shared\weapons\_weaponobjects;
17 #using scripts\mp\_challenges;
18 #using scripts\mp\_util;
19 #using scripts\mp\gametypes\_hostmigration;
20 #using scripts\mp\gametypes\_spawning;
21 #using scripts\mp\killstreaks\_airsupport;
22 #using scripts\mp\killstreaks\_helicopter;
23 #using scripts\mp\killstreaks\_killstreakrules;
24 #using scripts\mp\killstreaks\_killstreaks;
25 #using scripts\mp\killstreaks\_uav;
27 #insert scripts\mp\_hacker_tool.gsh;
28 #insert scripts\shared\clientfields.gsh;
29 #insert scripts\shared\shared.gsh;
31 #precache( "material", "compass_lodestar" );
32 #precache( "string", "KILLSTREAK_EARNED_REMOTE_MORTAR" );
33 #precache( "string", "KILLSTREAK_REMOTE_MORTAR_NOT_AVAILABLE" );
34 #precache( "string", "KILLSTREAK_REMOTE_MORTAR_NOT_USABLE" );
35 #precache( "string", "KILLSTREAK_REMOTE_MORTAR_INBOUND" );
36 #precache( "string", "KILLSTREAK_REMOTE_MORTAR_HACKED" );
37 #precache( "eventstring", "remotemortar" );
38 #precache( "eventstring", "mpl_killstreak_planemortar" );
39 #precache( "fx", "killstreaks/fx_lstar_laser_loop" );
40 #precache( "fx", "killstreaks/fx_lstar_exp" );
42 #namespace remotemortar;
46 level.remote_mortar_fx[
"laserTarget"] =
"killstreaks/fx_lstar_laser_loop";
47 level.remote_mortar_fx[
"missileExplode"] =
"killstreaks/fx_lstar_exp" ;
51 killstreaks::register_strings(
"remote_mortar", &
"KILLSTREAK_EARNED_REMOTE_MORTAR", &
"KILLSTREAK_REMOTE_MORTAR_NOT_AVAILABLE", &
"KILLSTREAK_REMOTE_MORTAR_INBOUND", &
"KILLSTREAK_REMOTE_MORTAR_HACKED" );
52 killstreaks::register_dialog(
"remote_mortar",
"mpl_killstreak_planemortar",
"kls_reaper_used",
"",
"kls_reaper_enemy",
"",
"kls_reaper_ready" );
58 level.remore_mortar_infrared_vision =
"remote_mortar_infrared";
59 level.remore_mortar_enhanced_vision =
"remote_mortar_enhanced";
61 minimapOrigins = getEntArray(
"minimap_corner",
"targetname" );
62 if ( miniMapOrigins.size )
67 if( level.script ==
"mp_la" )
68 uavOrigin = uavOrigin + ( 1200, 0, 0 );
69 if( level.script ==
"mp_hydro" )
70 uavOrigin = uavOrigin + ( 0, 2000, 0 );
71 if( level.script ==
"mp_concert" )
72 uavOrigin = uavOrigin + ( 0, -750, 0 );
73 if( level.script ==
"mp_vertigo" )
74 uavOrigin = uavOrigin + ( -500, 0, 0 );
76 level.remoteMortarRig =
spawn(
"script_model", uavOrigin );
77 level.remoteMortarRig setModel(
"tag_origin" );
78 level.remoteMortarRig.angles = (0,115,0);
79 level.remoteMortarRig hide();
83 level.remote_zOffset = 8000;
84 level.remote_radiusOffset = 9000;
85 remote_mortar_height =
struct::get(
"remote_mortar_height",
"targetname");
86 if ( isdefined(remote_mortar_height) )
88 level.remote_radiusOffset = (remote_mortar_height.origin[2]/level.remote_zOffset) * level.remote_radiusOffset;
89 level.remote_zOffset = remote_mortar_height.origin[2];
100 self iPrintLnBold( &
"KILLSTREAK_REMOTE_MORTAR_NOT_USABLE" );
106 self DisableWeaponCycling();
114 self notify(
"remote_mortar_unlock" );
116 self EnableWeaponCycling();
123 if ( killstreak_id == -1 )
126 self EnableWeaponCycling();
127 self notify(
"remote_mortar_unlock" );
134 remote SetDrawInfrared(
true );
143 remote.killstreak_id = killstreak_id;
147 remote playloopsound(
"mpl_ks_reaper_exterior_loop", 1 );
149 self.pilotTalking =
false;
150 remote.copilotVoiceNumber =
self.bcVoiceNumber;
151 remote.pilotVoiceNumber =
self.bcVoiceNumber + 1;
152 if (remote.pilotVoiceNumber > 3)
154 remote.pilotVoiceNumber = 0;
169 self AddWeaponStat( GetWeapon(
"remote_mortar" ),
"used", 1 );
174 level waittill(
"remote_unlinked" );
176 if ( isdefined( remote ) )
177 remote stoploopsound( 4 );
179 if ( !isdefined(
self ) )
192 level endon(
"remote_end" );
199 wait RandomFloatRange (4.5, 15);
204 level endon(
"remote_end" );
205 assert( isdefined(
self.owner ) );
206 assert( IsPlayer(
self.owner ) );
215 level endon(
"remote_end" );
217 self.owner waittill(
"teamKillKicked" );
223 level endon(
"remote_end" );
230 while(
self.owner UseButtonPressed() )
233 if ( timeUsed > 0.25 )
246 level endon(
"remote_end" );
247 assert( isdefined(
self.owner ) );
248 assert( IsPlayer(
self.owner ) );
250 level waittill(
"game_ended" );
259 remote = SpawnPlane(
self,
"script_model", level.remoteMortarRig GetTagOrigin(
"tag_origin" ) );
260 assert( isdefined( remote ) );
262 remote SetModel(
"veh_t6_drone_pegasus_mp" );
263 remote.targetname =
"remote_mortar";
265 remote SetOwner(
self );
266 remote SetTeam(
self.team );
267 remote.team =
self.team;
269 remote.numFlares = 2;
270 remote.flareOffset = (0,0,-256);
272 remote.attackers = [];
273 remote.attackerData = [];
274 remote.attackerDamage = [];
275 remote.flareAttackerDamage = [];
277 remote.pilotVoiceNumber =
self.bcVoiceNumber + 1;
278 if (remote.pilotVoiceNumber > 3)
280 remote.pilotVoiceNumber = 0;
284 angle = randomInt( 360 );
285 xOffset = cos( angle ) * level.remote_radiusOffset;
286 yOffset = sin( angle ) * level.remote_radiusOffset;
287 angleVector = vectorNormalize( (xOffset,yOffset,level.remote_zOffset) );
288 angleVector = ( angleVector * 6100 );
289 remote LinkTo( level.remoteMortarRig,
"tag_origin", angleVector, (0,angle-90,0) );
292 objective_add( remoteObjIDFriendly,
"invisible", remote.origin, &
"remotemortar",
self );
293 objective_state( remoteObjIDFriendly,
"active" );
294 Objective_OnEntity( remoteObjIDFriendly, remote );
295 objective_team( remoteObjIDFriendly,
self.team );
296 self.remoteObjIDFriendly = remoteObjIDFriendly;
300 remote.fx =
spawn(
"script_model", (0,0,0) );
301 remote.fx SetModel(
"tag_origin" );
304 remote.fx SetInvisibleToPlayer( remote.owner,
true );
309 Target_SetTurretAquire( remote,
true );
324 self rotateyaw( turn, 30 );
329 self rotateyaw( turn, 45 );
337 players = GetPlayers();
339 foreach( player
in players )
341 if ( player ==
self.owner )
343 self SetInvisibleToPlayer( player );
347 self SetVisibleToPlayer( player );
353 player endon(
"disconnect");
354 self endon(
"death" );
355 self endon(
"remote_end");
357 self.lockSounds =
spawn(
"script_model",
self.origin);
359 self.lockSounds LinkTo(
self,
"tag_player" );
363 self waittill(
"locking on" );
372 self PlaySoundToPlayer(
"uin_alert_lockon", player );
378 self PlaySoundToPlayer(
"uin_alert_lockon", player );
392 if ( isdefined(
self.locking_on) &&
self.locking_on )
400 if ( isdefined(
self.locked_on) &&
self.locked_on )
408 self.missile_hud = newclienthudelem(
self );
409 self.missile_hud.alignX =
"left";
410 self.missile_hud.alignY =
"bottom";
411 self.missile_hud.horzAlign =
"user_left";
412 self.missile_hud.vertAlign =
"user_bottom";
413 self.missile_hud.font =
"small";
414 self.missile_hud SetText(
"[{+attack}]" +
"Fire Missile");
415 self.missile_hud.hidewheninmenu =
true;
416 self.missile_hud.hideWhenInDemo =
true;
417 self.missile_hud.x = 5;
418 self.missile_hud.y = -40;
419 self.missile_hud.fontscale = 1.25;
421 self.zoom_hud = newclienthudelem(
self );
422 self.zoom_hud.alignX =
"left";
423 self.zoom_hud.alignY =
"bottom";
424 self.zoom_hud.horzAlign =
"user_left";
425 self.zoom_hud.vertAlign =
"user_bottom";
426 self.zoom_hud.font =
"small";
427 self.zoom_hud SetText(&
"KILLSTREAK_INCREASE_ZOOM");
428 self.zoom_hud.hidewheninmenu =
true;
429 self.zoom_hud.hideWhenInDemo =
true;
431 self.zoom_hud.y = -25;
432 self.zoom_hud.fontscale = 1.25;
434 self.hud_prompt_exit = newclienthudelem(
self );
435 self.hud_prompt_exit.alignX =
"left";
436 self.hud_prompt_exit.alignY =
"bottom";
437 self.hud_prompt_exit.horzAlign =
"user_left";
438 self.hud_prompt_exit.vertAlign =
"user_bottom";
439 self.hud_prompt_exit.font =
"small";
440 self.hud_prompt_exit.fontScale = 1.25;
441 self.hud_prompt_exit.hidewheninmenu =
true;
442 self.hud_prompt_exit.hideWhenInDemo =
true;
443 self.hud_prompt_exit.archived =
false;
444 self.hud_prompt_exit.x = 5;
445 self.hud_prompt_exit.y = -10;
446 self.hud_prompt_exit SetText(level.remoteExitHint);
453 self endon(
"disconnect" );
454 remote endon(
"death" );
460 if ( !isdefined(
self.missile_hud))
464 self.missile_hud.alpha -= 0.025;
465 self.zoom_hud.alpha -= 0.025;
470 self.missile_hud.alpha = 0;
471 self.zoom_hud.alpha = 0;
476 if ( isdefined(
self.missile_hud) )
478 if ( isdefined(
self.zoom_hud) )
480 if ( isdefined(
self.hud_prompt_exit) )
487 level notify(
"remote_end" );
492 if ( !isdefined( disconnected ) )
493 disconnected =
false;
495 if ( isdefined(
self.owner ) )
497 if ( disconnected ==
false )
501 self.owner SendKillstreakDamageEvent( 600 );
507 self.owner SendKillstreakDamageEvent( 600 );
515 self.owner EnableWeaponCycling();
518 if ( isdefined(level.gameEnded) && level.gameEnded )
524 if ( isdefined(
self.influencers ) )
528 Objective_Delete(
self.owner.remoteObjIDFriendly );
531 Target_SetTurretAquire(
self,
false );
533 level notify(
"remote_unlinked" );
537 if ( isdefined(
self.owner ) )
539 self.owner SetInfraredVision(
false );
540 self.owner UseServerVisionset(
false );
543 if ( isdefined(
self.fx) )
559 if ( isdefined( level.remoteMotarViewLeft ) )
561 leftArc = level.remoteMotarViewLeft;
564 if ( isdefined( level.remoteMotarViewRight ) )
566 rightArc = level.remoteMotarViewRight;
569 if ( isdefined( level.remoteMotarViewUp ) )
571 upArc = level.remoteMotarViewUp;
574 if ( isdefined( level.remoteMotarViewDown ) )
576 downArc = level.remoteMotarViewDown;
580 leftArc = GetDvarInt(
"scr_remotemortar_right", leftArc );
581 rightArc = GetDvarInt(
"scr_remotemortar_left", rightArc );
582 upArc = GetDvarInt(
"scr_remotemortar_up", upArc );
583 downArc = GetDvarInt(
"scr_remotemortar_down", downArc );
585 self PlayerLinkWeaponViewToDelta( remote,
"tag_player", 1.0, leftArc, rightArc, upArc, downArc );
593 lookVec = VectorToAngles( level.UAVRig.origin -
self GetEye() );
594 self SetPlayerAngles( lookVec );
599 level endon(
"remote_end" );
603 PlayFxOnTag( level.remote_mortar_fx[
"laserTarget" ], remote.fx,
"tag_origin" );
604 remote.fx playloopsound(
"mpl_ks_reaper_laser" );
608 origin =
self GetEye();
609 forward = AnglesToForward(
self GetPlayerAngles() );
610 endpoint = origin + forward * 15000;
612 trace = BulletTrace( origin, endpoint,
false, remote );
613 remote.fx.origin =
trace[
"position" ];
614 remote.fx.angles = VectortoAngles(
trace[
"normal" ]);
618 if ( isdefined(
self.active_pegasus ) )
629 level endon(
"remote_end" );
631 end_time = GetTime() + ( GetDvarFloat(
"scr_remote_mortar_lifetime" ) * 1000 );
635 while( GetTime() < end_time )
637 self.active_pegasus = undefined;
639 if ( !
self AttackButtonPressed() )
645 self playLocalSound(
"mpl_ks_reaper_fire" );
646 self PlayRumbleOnEntity(
"sniper_fire" );
650 if ( isdefined(remote.owner) && isdefined(remote.owner.pilotTalking) && remote.owner.pilotTalking )
654 shot = ( shot + 1 ) % 3;
656 origin =
self GetEye();
657 Earthquake( 0.3, 0.5, origin, 256 );
659 angles =
self GetPlayerAngles();
660 forward = AnglesToForward( angles );
661 right = AnglesToRight( angles );
662 up = AnglesToUp( angles );
664 offset = origin + ( forward * 100 ) + ( right * -40 ) + ( up * -100 );
666 missile = MagicBullet( GetWeapon(
"remote_mortar_missile" ), offset, origin + ( forward * 1000 ) + ( up * -100 ),
self, remote.fx );
668 self.active_pegasus = missile;
672 missile waittill(
"death" );
674 self playlocalsound(
"mpl_ks_reaper_explosion" );
684 self endon(
"death" );
688 playFX( level.remote_mortar_fx[
"missileExplode"],
self.origin );
694 level endon(
"remote_end" );
696 self.health = 999999;
697 maxHealth = level.heli_amored_maxhealth;
699 self.lowHealth =
false;
701 self SetCanDamage(
true );
702 Target_Set(
self, ( 0, 0, 30 ) );
706 self waittill(
"damage",
damage, attacker, direction_vec, point, meansOfDeath, tagName, modelName, partname, weapon );
707 self.health = 999999;
712 if( !heli_friendlyfire )
715 if( IsPlayer( attacker ) )
719 if ( attacker HasPerk(
"specialty_armorpiercing" ) )
721 if( meansOfDeath ==
"MOD_RIFLE_BULLET" || meansOfDeath ==
"MOD_PISTOL_BULLET" )
728 if( meansOfDeath ==
"MOD_RIFLE_BULLET" || meansOfDeath ==
"MOD_PISTOL_BULLET" )
730 damage *= level.heli_armor_bulletdamage;
733 if( weapon == level.weaponNone )
738 if ( isdefined( weapon.isLauncherWeapon ) && weapon.isLauncherWeapon )
748 self.owner PlayLocalSound(
"reaper_damaged" );
750 self.owner SendKillstreakDamageEvent(
int(
damage) );
753 if ( damageTaken >= maxHealth )
759 attacker AddWeaponStat( weapon,
"destroyed_controlled_killstreak", 1 );
772 else if(!
self.lowHealth && damageTaken >= maxHealth / 2)
774 PlayFXOnTag( level.fx_u2_damage_trail,
self,
"tag_origin" );
775 self.lowHealth =
true;
782 level endon(
"game_ended" );
783 self endon(
"death" );
793 exitVector = ( anglestoforward(
self.angles + (0, yaw, 0)) * 20000 );
795 exitPoint = (
self.origin[0] + exitVector[0],
self.origin[1] + exitVector[1],
self.origin[2] - 2500);
796 exitPoint =
self.origin + exitVector;
801 if ( tries % 2 == 1 && tries != 1)
805 else if ( tries != 1 )
818 self thread airsupport::flattenYaw(
self.angles[1] + yaw );
820 self moveTo( exitPoint, 8, 4 );
823 PlayFXOnTag( level.chopper_fx[
"damage"][
"heavy_smoke"],
self,
"tag_origin" );
833 self.exhaustFX =
spawn(
"script_model",
self.origin );
834 self.exhaustFX SetModel(
"tag_origin" );
835 self.exhaustFX LinkTo(
self,
"tag_turret", (0,0,25) );
837 PlayFXOnTag( level.fx_cuav_burner,
self.exhaustFX,
"tag_origin" );
842 if ( !isdefined(
self.exhaustFX ) )
844 self.exhaustFX =
spawn(
"script_model",
self.origin );
845 self.exhaustFX SetModel(
"tag_origin" );
846 self.exhaustFX LinkTo(
self,
"tag_turret", (0,0,25) );
848 self endon(
"death" );
850 PlayFXOnTag( level.fx_cuav_afterburner,
self.exhaustFX,
"tag_origin" );
855 self notify(
"death" );
857 forward = ( AnglesToForward(
self.angles ) * 200 );
858 playFx ( level.fx_u2_explode,
self.origin, forward );
859 self playsound (
"evt_helicopter_midair_exp" );
861 self notify(
"delete" );
867 self endon(
"disconnect" );
868 level endon(
"remote_end" );
872 self SetInfraredVision(
true );
873 self UseServerVisionset(
true );
874 self SetVisionSetForPlayer( level.remore_mortar_infrared_vision, 1 );
878 if (
self ChangeSeatButtonPressed() )
882 self SetInfraredVision(
true );
883 self SetVisionSetForPlayer( level.remore_mortar_infrared_vision, 0.5 );
884 self PlayLocalSound (
"mpl_ks_reaper_view_select");
888 self SetInfraredVision(
false );
889 self SetVisionSetForPlayer( level.remore_mortar_enhanced_vision, 0.5 );
890 self PlayLocalSound (
"mpl_ks_reaper_view_select");
893 inverted = !inverted;
896 while (
self ChangeSeatButtonPressed() )