1 #using scripts\codescripts\struct;
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\hud_shared;
6 #using scripts\shared\math_shared;
7 #using scripts\shared\scoreevents_shared;
8 #using scripts\shared\util_shared;
10 #using scripts\mp\_util;
11 #using scripts\mp\gametypes\_battlechatter;
12 #using scripts\mp\gametypes\_globallogic_audio;
13 #using scripts\mp\gametypes\_spawning;
14 #using scripts\mp\killstreaks\_killstreakrules;
15 #using scripts\mp\killstreaks\_killstreaks;
16 #using scripts\shared\visionset_mgr_shared;
18 #insert scripts\mp\_hacker_tool.gsh;
19 #insert scripts\mp\killstreaks\_killstreaks.gsh;
20 #using scripts\mp\killstreaks\_killstreak_bundles;
21 #using scripts\mp\killstreaks\_killstreak_detect;
22 #using scripts\mp\killstreaks\_killstreak_hacking;
23 #insert scripts\shared\shared.gsh;
24 #insert scripts\shared\version.gsh;
25 #insert scripts\shared\clientfields.gsh;
28 #define REMOTE_MISSILE_MAX_OTHER_TARGETS_HUD 3
29 #define REMOTE_MISSILE_TARGETING_RADIUS 600
30 #define REMOTE_MISSILE_BOMBLETS_NUMBER 6
31 #define REMOTE_MISSILE_FRAMES_BETWEEN_TARGET_SCAN 5
32 #define REMOTE_MISSILE_MAP_ICON_DELAY 0.1
33 #define REMOTE_MISSILE_BRAKE_TIMEOUT 1.5
34 #define REMOTE_MISSILE_ICON_SIZE 175
37 #precache( "material", "hud_remote_missile_target" );
38 #precache( "string", "KILLSTREAK_EARNED_REMOTE_MISSILE" );
39 #precache( "string", "KILLSTREAK_REMOTE_MISSILE_NOT_AVAILABLE" );
40 #precache( "string", "KILLSTREAK_REMOTE_MISSILE_INBOUND" );
41 #precache( "string", "KILLSTREAK_REMOTE_MISSILE_HACKED" );
42 #precache( "eventstring", "mpl_killstreak_cruisemissile" );
43 #precache( "fx", "killstreaks/fx_predator_trigger" );
45 #namespace remotemissile;
47 #define REMOTE_MISSILE_NAME "remote_missile"
56 killstreaks::register_strings(
"remote_missile", &
"KILLSTREAK_EARNED_REMOTE_MISSILE", &
"KILLSTREAK_REMOTE_MISSILE_NOT_AVAILABLE", &
"KILLSTREAK_REMOTE_MISSILE_INBOUND", undefined, &
"KILLSTREAK_REMOTE_MISSILE_HACKED" );
57 killstreaks::register_dialog(
"remote_missile",
"mpl_killstreak_cruisemissile",
"remoteMissileDialogBundle",
"remoteMissilePilotDialogBundle",
"friendlyRemoteMissile",
"enemyRemoteMissile",
"enemyRemoteMissileMultiple",
"friendlyRemoteMissileHacked",
"enemyRemoteMissileHacked",
"requestRemoteMissile" );
64 level.missilesForSightTraces = [];
66 level.missileRemoteDeployFX =
"killstreaks/fx_predator_trigger";
67 level.missileRemoteLaunchVert = 18000;
68 level.missileRemoteLaunchHorz = 7000;
69 level.missileRemoteLaunchTargetDist = 1500;
76 self endon(
"Remotemissle_killstreak_done" );
78 level waittill(
"game_ended" );
82 self notify(
"Remotemissle_killstreak_done" );
87 waterDepth =
self depthofplayerinwater();
91 self iPrintLnBold( &
"KILLSTREAK_REMOTE_MISSILE_NOT_USABLE" );
97 if ( killstreak_id == -1 )
104 returnVar =
_fire( lifeId,
self, team, killstreak_id );
114 foreach ( spawnPoint
in remoteMissileSpawnPoints )
116 spawnPoint.validPlayers = [];
117 spawnPoint.spawnScore = 0;
120 foreach ( player
in level.players )
122 if ( !isAlive( player ) )
125 if ( player.team ==
self.team )
128 if ( player.team ==
"spectator" )
131 bestDistance = 999999999;
132 bestSpawnPoint = undefined;
134 foreach ( spawnPoint
in remoteMissileSpawnPoints )
137 spawnPoint.validPlayers[spawnPoint.validPlayers.size] = player;
139 potentialBestDistance = Distance2DSquared( spawnPoint.targetent.origin, player.origin );
141 if ( potentialBestDistance <= bestDistance )
143 bestDistance = potentialBestDistance;
144 bestSpawnpoint = spawnPoint;
148 bestSpawnPoint.spawnScore += 2;
151 bestSpawn = remoteMissileSpawnPoints[0];
152 foreach ( spawnPoint
in remoteMissileSpawnPoints )
154 foreach ( player
in spawnPoint.validPlayers )
156 spawnPoint.spawnScore += 1;
158 if ( bulletTracePassed( player.origin + (0,0,32), spawnPoint.origin,
false, player ) )
159 spawnPoint.spawnScore += 3;
161 if ( spawnPoint.spawnScore > bestSpawn.spawnScore )
163 bestSpawn = spawnPoint;
165 else if ( spawnPoint.spawnScore == bestSpawn.spawnScore )
168 bestSpawn = spawnPoint;
173 return ( bestSpawn );
179 drawTime = int(timeSlice * 20);
180 for( time = 0; time < drawTime; time++ )
182 line( start,
end, color,
false, 1 );
188 function _fire( lifeId, player, team, killstreak_id )
190 remoteMissileSpawnArray = getEntArray(
"remoteMissileSpawn" ,
"targetname" );
192 foreach (
spawn in remoteMissileSpawnArray )
194 if ( isdefined(
spawn.target ) )
195 spawn.targetEnt = getEnt(
spawn.target,
"targetname" );
198 if ( remoteMissileSpawnArray.size > 0 )
201 remoteMissileSpawn = undefined;
203 if ( isdefined( remoteMissileSpawn ) )
205 startPos = remoteMissileSpawn.origin;
206 targetPos = remoteMissileSpawn.targetEnt.origin;
208 vector = vectorNormalize( startPos - targetPos );
209 startPos = ( vector * level.missileRemoteLaunchVert ) + targetPos;
213 upVector = (0, 0, level.missileRemoteLaunchVert );
214 backDist = level.missileRemoteLaunchHorz;
215 targetDist = level.missileRemoteLaunchTargetDist;
217 forward = AnglesToForward( player.angles );
218 startpos = player.origin + upVector + forward * backDist * -1;
219 targetPos = player.origin + forward * targetDist;
224 player DisableWeaponCycling();
228 if (
result !=
"success" || level.gameended )
234 player EnableWeaponCycling();
241 rocket = MagicBullet( GetWeapon(
"remote_missile_missile" ), startpos, targetPos, player );
242 rocket.forceOneMissile =
true;
243 forceAngleVector = vectorNormalize( targetPos - startPos );
244 rocket.angles = VectorToAngles( forceAngleVector );
245 rocket.targetname =
"remote_missile";
255 player LinkToMissile( rocket,
true,
true );
256 rocket.owner = player;
257 rocket.killcament = player;
258 player thread
cleanupWaiter( rocket, player.team, killstreak_id );
261 player SetModelLodBias(
VAL( level.remotemissile_lod_bias, 12 ) );
266 self AddWeaponStat( GetWeapon(
"remote_missile" ),
"used", 1 );
283 player waittill(
"Remotemissle_killstreak_done" );
308 if ( !isdefined( level.remotemissile_kill_z ) )
312 kill_z = level.remotemissile_kill_z;
314 rocket endon(
"Remotemissle_killstreak_done" );
315 rocket endon(
"death" );
317 while ( rocket.origin[2] > kill_z )
327 self endon(
"Remotemissle_killstreak_done" );
329 rocket waittill(
"death" );
335 self notify(
"Remotemissle_killstreak_done" );
341 self notify(
"player_missile_end_singleton" );
342 self endon (
"player_missile_end_singleton" );
344 if( isalive( rocket ) )
351 self notify(
"snd1stPersonExplo" );
353 if( isdefined(
self ) )
358 if(
IS_TRUE( performPlayerKillstreakEnd ) )
360 self PlayRumbleOnEntity(
"grenade_rumble" );
362 if ( level.gameended ==
false )
364 self SendKillstreakDamageEvent( 600 );
368 if( isdefined ( rocket ) )
377 self SetModelLodBias( 0 );
380 self UnlinkFromMissile();
382 self notify(
"remotemissile_done" );
385 self EnableWeaponCycling();
394 player = rocket.owner;
396 self endon(
"death" );
398 self waittill(
"missile_brake" );
400 rocket PlaySound(
"wpn_remote_missile_brake_npc" );
401 player playlocalsound(
"wpn_remote_missile_brake_plr" );
405 if( isdefined(
self ) )
407 self SetMissileBrake(
false );
413 self waittill(
"death" );
414 if( isdefined( snd ) )
420 self endon(
"Remotemissle_killstreak_done" );
426 self notify(
"Remotemissle_killstreak_done" );
431 self endon (
"death" );
432 self endon (
"deleted" );
434 self setCanDamage(
true );
438 self waittill(
"damage",
damage, attacker, direction_vec, point, meansOfDeath, tagName, modelName, partName, weapon );
440 if ( isdefined ( attacker ) && isdefined(
self.owner ) )
447 attacker AddWeaponStat( weapon,
"destroyed_controlled_killstreak", 1 );
453 self.owner SendKillstreakDamageEvent(
int(
damage) );
462 self endon (
"disconnect" );
464 staticBG = newClientHudElem(
self );
465 staticBG.horzAlign =
"fullscreen";
466 staticBG.vertAlign =
"fullscreen";
467 staticBG setShader(
"white", 640, 480 );
468 staticBG.archive =
true;
470 staticBG.immunetodemogamehudsettings =
true;
472 static = newClientHudElem(
self );
473 static.horzAlign =
"fullscreen";
474 static.vertAlign =
"fullscreen";
476 static.archive =
true;
478 static.immunetodemogamehudsettings =
true;
491 entityNumber =
self getEntityNumber();
492 level.rockets[ entityNumber ] =
self;
493 self waittill(
"death" );
495 level.rockets[ entityNumber ] = undefined;
500 self.snd_first =
spawn(
"script_model",
self.origin );
501 self.snd_first SetModel(
"tag_origin" );
502 self.snd_first LinkTo(
self );
503 self.snd_first SetInvisibleToAll();
504 self.snd_first SetVisibleToPlayer( player );
505 self.snd_first PlayLoopSound(
"wpn_remote_missile_loop_plr", .5 );
509 self.snd_third =
spawn(
"script_model",
self.origin );
510 self.snd_third SetModel(
"tag_origin" );
511 self.snd_third LinkTo(
self );
512 self.snd_third SetVisibleToAll();
513 self.snd_third SetInvisibleToPlayer( player );
514 self.snd_third PlayLoopSound(
"wpn_remote_missile_loop_npc", .2 );
521 self endon(
"remotemissile_done" );
522 self endon(
"joined_team" );
523 self endon(
"joined_spectators" );
524 self endon(
"disconnect" );
526 self waittill(
"missile_boost" );
527 rocket PlaySound(
"wpn_remote_missile_fire_boost_npc" );
528 rocket.snd_third PlayLoopSound(
"wpn_remote_missile_boost_npc" );
530 self playlocalsound(
"wpn_remote_missile_fire_boost_plr" );
531 rocket.snd_first PlayLoopSound(
"wpn_remote_missile_boost_plr" );
532 self PlayRumbleOnEntity(
"sniper_fire" );
534 if ( rocket.origin[2] -
self.origin[2] > 4000 )
536 rocket notify(
"stop_impact_sound" );
543 self endon(
"death" );
544 self endon(
"stop_impact_sound" );
545 player endon(
"disconnect" );
546 player endon(
"remotemissile_done" );
547 player endon(
"joined_team" );
548 player endon(
"joined_spectators" );
552 if (
self.origin[2] - player.origin[2] < distance )
554 self PlaySound(
"wpn_remote_missile_inc" );
563 self endon(
"Remotemissle_killstreak_done" );
564 self endon(
"remotemissile_done" );
565 self endon(
"joined_team" );
566 self endon(
"joined_spectators" );
567 self endon(
"disconnect" );
568 self endon(
"bomblets_deployed" );
570 self waittill(
"snd1stPersonExplo" );
571 self playlocalsound(
"wpn_remote_missile_explode_plr" );
576 self.snd_first PlayLoopSound(
"wpn_remote_missile_loop_plr", .5 );
581 pixbeginevent(
"remotemissile_getVTs_header");
585 forward = AnglesToForward ( rocket.angles );
587 rocketZ = rocket.origin[2];
588 mapCenterZ = level.mapCenter[2];
589 diff = mapCenterZ - rocketZ;
591 ratio = diff / forward[2];
593 aimTarget = rocket.origin + forward * ratio;
594 rocket.aimTarget = aimTarget;
602 pixbeginevent(
"remotemissile_getVTs_enemies");
604 enemies =
self GetEnemies();
606 foreach( player
in enemies )
608 if( !IsPlayer( player ) )
613 if ( player.ignoreme ===
true )
622 if ( BulletTracePassed( player.origin + (0,0,60), player.origin + (0,0,180),
false, player) )
624 targets[targets.size] = player;
629 targets[targets.size] = player;
631 if( targets.size >= max_targets )
636 dogs = GetEntArray(
"attack_dog",
"targetname" );
638 foreach( dog
in dogs )
644 if ( BulletTracePassed( dog.origin + (0,0,60), dog.origin + (0,0,180),
false, dog) )
646 targets[targets.size] = dog;
651 targets[targets.size] = dog;
653 if( targets.size >= max_targets )
658 tanks = GetEntArray(
"talon",
"targetname" );
660 foreach( tank
in tanks )
666 if ( BulletTracePassed( tank.origin + (0,0,60), tank.origin + (0,0,180),
false, tank) )
668 targets[targets.size] = tank;
673 targets[targets.size] = tank;
675 if( targets.size >= max_targets )
680 turrets = GetEntArray(
"auto_turret",
"classname" );
681 foreach( turret
in turrets )
687 if ( BulletTracePassed( turret.origin + (0,0,60), turret.origin + (0,0,180),
false, turret) )
689 targets[targets.size] = turret;
694 targets[targets.size] = turret;
696 if( targets.size >= max_targets )
708 self.missile_target_icons = [];
710 foreach (player
in level.players)
715 if (level.teamBased && player.team ==
self.team)
718 index = player.clientId;
719 self.missile_target_icons[index] = newClientHudElem(
self );
720 self.missile_target_icons[index].x = 0;
721 self.missile_target_icons[index].y = 0;
722 self.missile_target_icons[index].z = 0;
723 self.missile_target_icons[index].alpha = 0;
724 self.missile_target_icons[index].archived =
true;
726 self.missile_target_icons[index] setWaypoint(
false );
727 self.missile_target_icons[index].hidewheninmenu =
true;
728 self.missile_target_icons[index].immunetodemogamehudsettings =
true;
733 self.missile_target_other[i] = newClientHudElem(
self );
734 self.missile_target_other[i].x = 0;
735 self.missile_target_other[i].y = 0;
736 self.missile_target_other[i].z = 0;
737 self.missile_target_other[i].alpha = 0;
738 self.missile_target_other[i].archived =
true;
740 self.missile_target_other[i] setWaypoint(
false );
741 self.missile_target_other[i].hidewheninmenu =
true;
742 self.missile_target_other[i].immunetodemogamehudsettings =
true;
744 rocket.iconIndexOther = 0;
751 if (isdefined(
self.missile_target_icons) )
753 foreach (player
in level.players)
760 index = player.clientId;
761 if (isdefined(
self.missile_target_icons[index]))
763 self.missile_target_icons[index] Destroy();
767 if (isdefined(
self.missile_target_other) )
771 if( isdefined(
self.missile_target_other[i] ) )
772 self.missile_target_other[i] Destroy();
779 self endon(
"disconnect" );
780 self endon(
"remotemissile_done");
781 rocket endon(
"death");
782 level endon (
"game_ended" );
785 framesSinceTargetScan = 0;
789 foreach (icon
in self.missile_target_icons)
794 framesSinceTargetScan++;
799 framesSinceTargetScan = 0;
802 if (targets.size > 0)
804 foreach (target
in targets)
806 if ( isdefined( target ) ==
false )
809 if ( IsPlayer( target ) )
811 if ( isalive( target ) )
813 index = target.clientId;
814 assert( isdefined( index ) );
816 self.missile_target_icons[index].x = target.origin[0];
817 self.missile_target_icons[index].y = target.origin[1];
818 self.missile_target_icons[index].z = target.origin[2] + 47;
819 self.missile_target_icons[index].alpha = 1;
824 if( !isdefined(target.missileIconIndex))
826 target.missileIconIndex = rocket.iconIndexOther;
829 index = target.missileIconIndex;
830 self.missile_target_other[index].x = target.origin[0];
831 self.missile_target_other[index].y = target.origin[1];
832 self.missile_target_other[index].z = target.origin[2];
833 self.missile_target_other[index].alpha = 1;
844 self endon(
"disconnect" );
845 self endon(
"remotemissile_done");
846 rocket endon(
"remotemissile_bomblets_launched");
847 rocket endon(
"death");
848 level endon (
"game_ended" );
856 if (
self attackbuttonpressed() )
869 rocket notify (
"remotemissile_bomblets_launched");
873 if( targets.size > 0 )
875 foreach( target
in targets )
877 self thread
fire_bomblet( rocket, explosionRadius, target, waitFrames );
885 if( rocket.origin[2] -
self.origin[2] > 4000 )
888 rocket notify(
"stop_impact_sound" );
893 self notify(
"remotemissile_done");
903 playfx( level.missileRemoteDeployFX, rocket.origin, anglestoForward( rocket.angles ) );
904 self playLocalSound(
"mpl_rc_exp");
905 self PlayRumbleOnEntity(
"sniper_fire" );
906 Earthquake( 0.2, 0.2, rocket.origin, 200 );
910 rocket setMissileCoasting(
true );
911 if ( hacked ==
false )
918 self notify(
"bomblets_deployed" );
920 if ( hacked ==
true )
922 rocket notify(
"death" );
930 self endon(
"disconnect" );
931 self endon(
"remotemissile_done");
932 rocket endon(
"death");
933 level endon (
"game_ended" );
935 delay = GetDvarFloat(
"scr_rmbomblet_camera_delaytime", 1.0 );
937 self waittill(
"bomblet_exploded" );
941 rocket notify(
"death" );
942 self notify(
"remotemissile_done");
955 bomb.team =
self.team;
957 bomb setTeam(
self.team );
962 bomb.killcamEnt =
self;
969 origin = rocket.origin;
971 targetOrigin = target.origin + (0,0,50);
973 wait( waitFrames * 0.05 );
975 if( isdefined( rocket ) )
976 origin = rocket.origin;
978 bomb = MagicBullet( GetWeapon(
"remote_missile_bomblet" ), origin, targetOrigin,
self, target, (0,0,30) );
985 origin = rocket.origin;
986 angles = rocket.angles;
987 owner = rocket.owner;
988 aimTarget = rocket.aimtarget;
990 wait ( waitFrames * 0.05 );
992 angle = randomIntRange( 10 + ( 60 * quadrant), 50 + ( 60 * quadrant ) );
997 bomb = MagicBullet( GetWeapon(
"remote_missile_bomblet" ), origin, aimtarget + ( x, y, 0 ),
self);
1005 bomb endon(
"death" );
1009 if( isdefined( bomb ) )
1020 player endon(
"disconnect" );
1021 player endon(
"remotemissile_done" );
1022 player endon(
"death" );
1023 level endon (
"game_ended" );
1025 self waittill(
"death" );
1027 player notify(
"bomblet_exploded" );
1032 if ( isdefined(
self.remotemissileBda ) )
1034 if (
self.remotemissileBda === 1)
1036 bdaDialog =
"kill1";
1038 else if (
self.remotemissileBda === 2)
1040 bdaDialog =
"kill2";
1042 else if (
self.remotemissileBda === 3)
1044 bdaDialog =
"kill3";
1046 else if (isdefined(
self.remotemissileBda ) &&
self.remotemissileBda > 3)
1048 bdaDialog =
"killMultiple";
1062 self.remotemissileBda = undefined;