1 #using scripts\codescripts\struct;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\killstreaks_shared;
6 #using scripts\shared\popups_shared;
7 #using scripts\shared\scoreevents_shared;
8 #using scripts\shared\util_shared;
10 #insert scripts\shared\shared.gsh;
11 #insert scripts\shared\version.gsh;
13 #using scripts\mp\_challenges;
14 #using scripts\mp\_util;
15 #using scripts\mp\killstreaks\_airsupport;
16 #using scripts\mp\killstreaks\_dogs;
17 #using scripts\mp\killstreaks\_killstreakrules;
18 #using scripts\mp\killstreaks\_killstreaks;
19 #using scripts\mp\killstreaks\_missile_swarm;
21 #insert scripts\mp\killstreaks\_killstreaks.gsh;
23 #precache( "string", "KILLSTREAK_EARNED_MISSILE_DRONE" );
24 #precache( "string", "KILLSTREAK_MISSILE_DRONE_NOT_AVAILABLE" );
25 #precache( "string", "KILLSTREAK_MISSILE_DRONE_INBOUND" );
26 #precache( "string", "KILLSTREAK_MISSILE_DRONE_HACKED" );
27 #precache( "eventstring", "mpl_killstreak_missile_drone" );
29 #using_animtree ( "mp_missile_drone" );
31 #namespace missile_drone;
39 level.missile_drone_flyheight = 2400;
40 level.missile_drone_anim = %o_drone_hunter_launch;
52 assert( killstreakType ==
"missile_drone" || killstreakType ==
"inventory_missile_drone" );
54 level.missile_drone_origin = level.mapCenter + ( 0, 0, level.missile_drone_flyheight );
56 hardpointType =
"missile_drone";
75 missileWeapon = undefined;
76 currentWeapon =
self GetCurrentWeapon();
77 if ( currentWeapon.name ==
"missile_drone" || currentWeapon.name ==
"inventory_missile_drone" )
79 missileWeapon = currentWeapon;
83 assert( isdefined ( missileWeapon ) );
85 if ( !isdefined( missileWeapon ) )
90 if ( notifyString ==
"weapon_change" || notifyString ==
"death" )
95 if ( notifyString ==
"death" )
98 self TakeWeapon( missileWeapon );
102 if (
self HasWeapon( missileWeapon ) ||
self GetAmmoCount( missileWeapon ) )
111 self notify(
"missileDroneWatcher");
113 self endon(
"missileDroneWatcher" );
114 self endon(
"spawned_player" );
115 self endon(
"disconnect" );
116 self endon(
"weapon_change" );
117 self endon(
"death" );
122 if ( killstreak_id == -1 )
134 self waittill(
"grenade_fire", grenade, weapon );
135 origin = grenade.origin;
136 self notify(
"missile_drone_active" );
139 self AddWeaponStat( GetWeapon(
"missile_drone" ),
"used", 1 );
142 grenade.origin = grenade.origin + ( 0,0, 1000 );
144 self thread
doMissileDrone( origin, weapon, killstreak_id, hardpointType, team );
151 direction =
self getPlayerAngles();
152 forward = AnglesToForward( direction );
153 target = origin + VectorScale( forward, 10000 );
158 projectile Missile_DroneSetVisible(
true );
160 projectile.originalTarget = target;
167 projectile.targetname =
"remote_drone";
169 projectile PlaySound(
"wpn_hunter_ignite");
178 self endon(
"delete" );
179 self endon(
"death" );
188 self waittill(
"death" );
194 self endon(
"death" );
195 self notify(
"drone_target_acquired" );
203 self endon(
"death" );
205 if ( isdefined(
self.droneTarget ) )
208 self Missile_SetTarget(
self.goal );
213 searchDotProdMinimums = [];
214 searchDotProdMinimums[0] = 0.9;
215 searchDotProdMinimums[1] = 0.7071;
216 searchDotProdMinimums[2] = 0.5;
217 searchDotProdMinimums[3] = 0;
224 if ( !isdefined(
self ) )
226 self notify(
"death" );
230 if ( searchCounter < searchDotProdMinimums.size - 1 )
238 if ( level.missile_drone_origin[2] !=
self.goal.origin[2] )
241 currentAngles =
self.angles;
242 direction = VectorNormalize( AnglesToForward(
self.angles ) );
245 direction =
vecscale( direction, 1024 );
246 self.goal.origin = (
self.origin[0] + direction[0],
self.origin[1] + direction[1], level.missile_drone_origin[2] );
254 currentAngles =
self.angles;
255 direction = VectorNormalize( AnglesToForward(
self.angles ) );
257 direction =
vecscale( direction, 1024 );
258 self.goal.origin = ( level.missile_drone_origin[0] + direction[0], level.missile_drone_origin[1] + direction[1], level.missile_drone_origin[2] );
267 if ( isdefined( target ) )
270 self Missile_SetTarget(
self.goal );
280 return (vec[0]*scalar, vec[1]*scalar, vec[2]*scalar);
285 self endon(
"target_lost" );
287 self.swarm_target = target[
"entity" ];
288 target[
"entity" ].swarm =
self;
290 self Missile_SetTarget( target[
"entity" ], target[
"offset" ] );
292 self PlaySound(
"veh_harpy_drone_swarm_incomming" );
293 if ( !isdefined(target[
"entity" ].swarmSound) || target[
"entity" ].swarmSound ==
false)
296 target[
"entity" ] notify(
"stinger_fired_at_me",
self, hardpointType,
self.owner );
302 self Missile_SetTarget(
self.goal );
308 self endon(
"death" );
309 target[
"entity"] endon(
"death" );
310 target[
"entity"] endon(
"disconnect" );
311 target[
"entity"] endon(
"joined_team" );
321 if ( BulletTracePassed(
self.origin, target[
"entity"].origin + target[
"offset" ],
false, target[
"entity"] ) )
331 if ( failureCount >= failureLimit )
333 self notify(
"target_lost" );
346 if ( isdefined( ks ) && !isdefined( player ) )
350 else if ( !isdefined( ks ) && isdefined( player ) )
354 else if ( isdefined( ks ) && isdefined( player ) )
357 if ( player[
"dotprod" ] < ks[
"dotprod" ] )
371 ks[
"offset" ] = ( 0, 0, -10 );
373 targets = Target_GetArray();
374 rcbombs = GetEntArray(
"rcbomb",
"targetname" );
377 targets = ArrayCombine( targets, rcbombs,
true,
false );
378 targets = ArrayCombine( targets, dogs,
true,
false );
380 if ( targets.size <= 0 )
387 foreach( target
in targets )
389 if ( isdefined( target.owner ) && target.owner == owner )
394 if ( isdefined( target.script_owner ) && target.script_owner == owner )
399 if ( level.teambased && isdefined( target.team ) )
401 if ( target.team ==
self.team )
407 if ( isdefined( target.vehicletype ) && target.vehicletype ==
"heli_supplydrop_mp" )
413 if ( BulletTracePassed(
self.origin, target.origin,
false, target ) )
415 ks[
"entity" ] = target;
416 if ( isdefined( target.sortedDotProd ) )
418 ks[
"dotprod" ] = target.sortedDotProd;
422 ks[
"dotprod" ] = -1;
432 #define ORIGIN_SIGHT_CHECK_RATING 4
433 #define HEAD_SIGHT_CHECK_RATING 3
434 #define NOT_IN_BUILDING_RATING 2
435 #define MAX_TARGET_RATING ( ORIGIN_SIGHT_CHECK_RATING + NOT_IN_BUILDING_RATING + HEAD_SIGHT_CHECK_RATING )
436 #define MIN_TARGET_RATING 3
442 if ( isplayer(
self ) )
444 startOffset =
self GetPlayerViewHeight();
445 startOrigin = (
self.origin[0],
self.origin[1],
self.origin[2] + startOffset );
446 startAngles =
self GetPlayerAngles();
453 startOrigin =
self.origin;
454 startAngles =
self.angles;
458 bestPlayerRating = -1;
460 foreach( player
in players )
467 currentPlayerOffset = undefined;
468 currentPlayerDotProd = undefined;
469 currentPlayerRating = 0;
474 if ( BulletTracePassed( startOrigin, player.origin,
false, player ) )
479 if ( !isdefined ( currentPlayerOffset ) )
481 currentPlayerOffset = ( 0, 0, 0 );
487 verticalOffset = player GetPlayerViewHeight();
488 playerHeadOffset = ( 0, 0, verticalOffset );
493 if ( BulletTracePassed(startOrigin, player.origin + playerHeadOffset,
false, player ) )
499 if ( !isdefined ( currentPlayerOffset ) )
501 currentPlayerOffset = playerHeadOffset;
508 end = player.origin + playerHeadOffset + ( 0, 0, 96 );
512 if ( BulletTracePassed(player.origin + playerHeadOffset,
end,
false, player ) )
517 if ( !isdefined ( currentPlayerOffset ) )
519 currentPlayerOffset = ( 0, 0, 30 );
524 if ( currentPlayerRating > bestPlayerRating )
526 bestPlayerRating = currentPlayerRating;
527 target[
"entity" ] = player;
528 target[
"offset" ] = currentPlayerOffset;
529 if ( isdefined( player.sortedDotProd ) )
531 target[
"dotprod" ] = player.sortedDotProd;
535 target[
"dotprod" ] = -1;
554 self waittill(
"death" );
561 self endon(
"spawned_player" );
562 self endon(
"death" );
563 self endon(
"disconnect" );
564 self endon(
"grenade_fire" );
566 self waittill(
"weapon_change" );
574 self endon(
"spawned_player" );
575 self endon(
"disconnect" );
576 self endon(
"weapon_change" );
577 self endon(
"missile_drone_active" );
579 self waittill(
"death" );
586 self endon(
"spawned_player" );
587 self endon(
"disconnect" );
588 self endon(
"weapon_change" );
589 self endon(
"death" );
590 self endon(
"grenade_fire" );
592 self waittill(
"emp_jammed" );
600 self endon(
"death" );
601 self SetCanDamage(
true );
602 self.maxhealth = 100000;
603 self.health =
self.maxhealth;
607 self waittill(
"damage",
damage, attacker, direction, point, type, tagName, modelName, partname, weapon );
609 if( !isdefined( attacker ) || !isplayer( attacker ) )
612 if( isPlayer( attacker ) && level.teambased && isdefined( attacker.team ) &&
self.team == attacker.team && level.friendlyfire == 0 )
630 if ( isplayer(
self ) )
633 angles =
self GetPlayerAngles();
634 assert( isdefined ( angles ) );
639 assert( isdefined (
self.angles ) );
640 angles =
self.angles;
643 forwardVec = vectornormalize( AnglesToForward( angles ) );
649 for( i = 0;i <
array.size;i ++ )
651 assert( isdefined( forwardVec ) );
652 assert( isdefined(
array[ i ] ) );
653 assert( isdefined(
array[ i ].origin ) );
654 assert( isdefined( org ) );
656 cosA = vectorDot( forwardVec, vectornormalize(
array[ i ].origin - org ) );
658 assert( isdefined( cosA ) );
660 if ( isdefined( minCos ) && cosA < minCos )
665 array[ i ].sortedDotProd = cosA;
666 dotProd[ dotProd.size ] = cosA;
668 index[ index.size ] = i;
674 for( i = 0;i < dotProd.size - 1;i ++ )
676 if( dotProd[ i ] >= dotProd[ i + 1 ] )
680 dotProd[ i ] = dotProd[ i + 1 ];
681 dotProd[ i + 1 ] = temp;
683 index[ i ] = index[ i + 1 ];
684 index[ i + 1 ] = temp;
692 for( i = 0;i < dotProd.size;i ++ )
694 newArray[ i ] =
array[ index[ i ] ];
701 self endon(
"spawned_player" );
702 self endon(
"disconnect" );
703 self endon(
"weapon_change" );
704 self endon(
"death" );
705 self endon(
"grenade_fire" );
707 minCos = GetDvarFloat(
"scr_missile_drone_min_cos", 0.9 );
708 updateWait = GetDvarFloat(
"scr_missile_drone_update_wait", 0.5 );
713 if ( isdefined(
self.droneTarget ) )
732 self endon(
"death" );
733 self notify(
"clearInvalidDroneTarget" );
734 self endon(
"clearInvalidDroneTarget" );
735 self endon(
"drone_target_acquired" );
739 self.droneTarget = undefined;