‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_helicopter_guard.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\hostmigration_shared;
5 #using scripts\shared\killstreaks_shared;
6 #using scripts\shared\util_shared;
7 #using scripts\shared\weapons\_heatseekingmissile;
8 
9 #using scripts\mp\_util;
10 #using scripts\mp\gametypes\_hostmigration;
11 #using scripts\mp\gametypes\_spawning;
12 #using scripts\mp\killstreaks\_airsupport;
13 #using scripts\mp\killstreaks\_helicopter;
14 #using scripts\mp\killstreaks\_killstreak_detect;
15 #using scripts\mp\killstreaks\_killstreak_hacking;
16 #using scripts\mp\killstreaks\_killstreakrules;
17 #using scripts\mp\killstreaks\_killstreaks;
18 
19 #insert scripts\mp\_hacker_tool.gsh;
20 #insert scripts\shared\shared.gsh;
21 #insert scripts\shared\version.gsh;
22 
23 #precache( "string", "MP_CIVILIAN_AIR_TRAFFIC" );
24 #precache( "string", "MP_AIR_SPACE_TOO_CROWDED" );
25 #precache( "string", "KILLSTREAK_EARNED_HELICOPTER_GUARD" );
26 #precache( "string", "KILLSTREAK_HELICOPTER_GUARD_NOT_AVAILABLE" );
27 #precache( "string", "KILLSTREAK_HELICOPTER_GUARD_INBOUND" );
28 #precache( "string", "KILLSTREAK_HELICOPTER_GUARD_HACKED" );
29 #precache( "eventstring", "mpl_killstreak_lbguard_strt" );
30 #precache( "fx", "killstreaks/fx_ed_lights_green" );
31 #precache( "fx", "killstreaks/fx_ed_lights_red" );
32 #namespace helicopter_guard;
33 
34 function ‪init()
35 {
36  ‪killstreaks::register("helicopter_guard", "helicopter_guard", "killstreak_helicopter_guard", "helicopter_used",&‪tryUseheliGuardSupport, true);
37  ‪killstreaks::register_alt_weapon( "helicopter_guard", "littlebird_guard_minigun" );
38  ‪killstreaks::register_strings("helicopter_guard", &"KILLSTREAK_EARNED_HELICOPTER_GUARD", &"KILLSTREAK_HELICOPTER_GUARD_NOT_AVAILABLE", &"KILLSTREAK_HELICOPTER_GUARD_INBOUND", undefined, &"KILLSTREAK_HELICOPTER_GUARD_HACKED");
39  ‪killstreaks::register_dialog("helicopter_guard", "mpl_killstreak_lbguard_strt", "kls_littlebird_used", "","kls_littlebird_enemy", "", "kls_littlebird_ready");
40  ‪killstreaks::set_team_kill_penalty_scale( "helicopter_guard", 0.0 );
41 
42  level._effect["heli_guard_light"]["friendly"] = "killstreaks/fx_ed_lights_green";
43  level._effect["heli_guard_light"]["enemy"] = "killstreaks/fx_ed_lights_red";
44 
45  level.heliGuardFlyOverNFZ = false;
46  if ( level.script == "mp_hydro" )
47  {
48  level.heliGuardFlyOverNFZ = true;
49  }
50 
51  thread register();
52 }
53 
54 #define PLAYER_HEIGHT_INCREASE (0,0,50)
55 #define HELI_GUARD_FIRE_TIME 0.15
56 #define HELI_GUARD_MIN_SHOTS 10
57 #define HELI_GUARD_MAX_SHOTS 20
58 #define HELI_GUARD_MIN_PAUSE 1.0
59 #define HELI_GUARD_MAX_PAUSE 2.0
60 #define HELI_GUARD_GUNNER 0
61 #define HELI_GUARD_SPINUP 0.2
62 
63 function register()
64 {
65  ‪clientfield::register( "helicopter", "vehicle_is_firing", ‪VERSION_SHIP, 1, "int");
66  ‪clientfield::register( "vehicle", "vehicle_is_firing", ‪VERSION_SHIP, 1, "int");
67 }
68 
69 function ‪tryUseheliGuardSupport( lifeId ) // self == player
70 {
71  if ( isdefined( level.civilianJetFlyBy ) )
72  {
73  self iPrintLnBold( &"MP_CIVILIAN_AIR_TRAFFIC" );
74  return false;
75  }
76 
77  if ( self IsRemoteControlling() )
78  {
79  return false;
80  }
81 
82  if ( !isdefined( level.heli_paths ) || level.heli_paths.size <= 0 )
83  {
84  self iPrintLnBold( &"MP_UNAVAILABLE_IN_LEVEL" );
85  return false;
86  }
87 
88  killstreak_id = self ‪killstreakrules::killstreakStart( "helicopter_guard", self.team, false, true );
89  if ( killstreak_id == -1 )
90  {
91  return false;
92  }
93 
94  heliGuard = ‪createHeliGuardSupport( lifeId, killstreak_id );
95  if ( !isdefined( heliGuard ) )
96  return false;
97 
98  self thread ‪startHeliGuardSupport( heliGuard, lifeId );
99 
100  return true;
101 }
102 
104 {
105  heliGuard = self;
106  heliGuard thread ‪heliGuardSupport_watchForEarlyLeave();
107  heliGuard thread ‪heliGuardSupport_watchOwnerDamage();
108 }
109 
110 function ‪createHeliGuardSupport( lifeId, killstreak_id )
111 {
112  owner = self;
113  hardpointType = "helicopter_guard";
114  closestStartNode = ‪heliGuardSupport_getClosestStartNode( owner.origin );
115  if( isdefined( closestStartNode.angles ) )
116  startAng = closestStartNode.angles;
117  else
118  startAng = ( 0, 0, 0);
119 
120  closestNode = ‪heliGuardSupport_getClosestNode( owner.origin );
121  flyHeight = max( owner.origin[2] + 1600, ‪airsupport::getNoFlyZoneHeight( owner.origin ) );
122  forward = anglesToForward( owner.angles );
123  targetPos = ( owner.origin*(1,1,0) ) + ( (0,0,1)*flyHeight ) + ( forward * -100 );
124 
125  startPos = closestStartNode.origin;
126 
127  heliGuard = spawnHelicopter( owner, startPos, startAng, "heli_guard_mp", "veh_t6_drone_overwatch_light" );
128  if ( !isdefined( heliGuard ) )
129  return;
130 
131  heliGuard.harpointType = hardpointType;
132 
133  heliGuard ‪killstreaks::configure_team( hardpointType, killstreak_id, owner, "helicopter", undefined, &‪ConfigureTeamPost );
134  heliGuard ‪killstreak_hacking::enable_hacking( hardpointType );
135 
136  Target_Set( heliGuard, (0,0,-50) );
137 
138  heliguard setEnemyModel("veh_t6_drone_overwatch_dark");
139  heliGuard.speed = 150;
140  heliGuard.followSpeed = 40;
141  heliGuard setCanDamage( true );
142  heliGuard SetMaxPitchRoll( 45, 45 );
143  heliGuard SetSpeed( heliGuard.speed, 100, 40 );
144  heliGuard SetYawSpeed( 120, 60 );
145  heliGuard setneargoalnotifydist( 512 );
146  heliGuard ‪clientfield::set( "enemyvehicle", ‪ENEMY_VEHICLE_ACTIVE );
147 
148  heliGuard thread ‪heliGuardSupport_attackTargets();
149 
150  heliGuard.killCount = 0;
151  heliGuard.streakName = "littlebird_support";
152  heliGuard.heliType = "littlebird";
153  heliGuard.targettingRadius = 2000; // matches the maxRange on the turret gdt setting
154 
155  heliGuard.targetPos = targetPos;
156  heliGuard.currentNode = closestNode;
157 
158  heliGuard.attract_strength = 10000;
159  heliGuard.attract_range = 150;
160  heliGuard.attractor = Missile_CreateAttractorEnt( heliGuard, heliGuard.attract_strength, heliGuard.attract_range );
161  heliGuard.health = 999999; // keep it from dying anywhere in code
162  heliGuard.maxHealth = level.heli_maxhealth; // this is the health we'll check
163  heliGuard.rocketDamageOneShot = heliGuard.maxhealth + 1;
164  heliGuard.crashType = "explode";// just explode
165  heliGuard.destroyFunc =&‪lbExplode;
166  heliGuard.targeting_delay = level.heli_targeting_delay;
167  heliGuard.hasDodged = false;
168  heliGuard SetDrawInfrared( true );
169 
170  owner thread ‪helicopter::announceHelicopterInbound( hardpointType );
171 
172  heliGuard thread ‪helicopter::heli_targeting( false, hardpointType );
173  heliGuard thread ‪helicopter::wait_for_killed(); // monitors player kills
174  heliGuard thread ‪helicopter::heli_health(hardpointtype, undefined );
175 
176  killstreakTimeout = 60.0;
177 
178  heliGuard thread ‪killstreaks::WaitForTimeout( hardpointType, killstreakTimeout, &‪heliGuardSupport_leave, "leaving", "death" );
179  heliGuard thread ‪heliGuardSupport_watchRoundEnd();
180 
181  heliGuard.numFlares = 1;
182  heliGuard.flareOffset = (0,0,0);
183  heliGuard thread ‪heatseekingmissile::MissileTarget_ProximityDetonateIncomingMissile("explode", "death"); // fires chaff if needed
184  heliGuard thread ‪helicopter::create_flare_ent( (0,0,-50) );
185 
186  heliGuard.killstreak_id = killstreak_id;
187 
188  level.littlebirdGuard = heliGuard;
189 
190  return heliGuard;
191 }
192 
193 function ‪getMeshHeight( littleBird, owner )
194 {
195  if ( !(owner isInsideHeightLock()) )
196  {
198  }
199 
200  maxMeshHeight = littleBird GetHeliHeightLockHeight( owner.origin );
201  return max( maxMeshHeight, owner.origin[2] );
202 }
203 
204 function ‪startHeliGuardSupport( littleBird, lifeId ) // self == player
205 {
206  level endon( "game_ended" );
207  littleBird endon( "death" );
208 
209  // look at the player
210  littleBird SetLookAtEnt( self );
211 
212  // go to pos
213  maxMeshHeight = ‪getMeshHeight( littleBird, self );
214  height = ‪airsupport::getNoFlyZoneHeight((self.origin[0], self.origin[1], maxMeshHeight ));
215  playerMeshOrigin = (self.origin[0], self.origin[1], height);
216  vecToStart = VectorNormalize(littleBird.origin - littleBird.targetPos);
217  dist = 1500;
218  target = littleBird.targetPos + vecToStart * dist;
219  collide = ‪airsupport::crossesNoFlyZone(target, playerMeshOrigin);
220  while ( isdefined(collide) && dist > 0)
221  {
222  dist = dist - 500;
223  target = littleBird.targetPos + vecToStart * dist;
224  collide = ‪airsupport::crossesNoFlyZone(target, playerMeshOrigin);
225  }
226 
227  littleBird setVehGoalPos( target, 1 );
228  Target_SetTurretAquire( littleBird, false );
229 
230  littleBird waittill( "near_goal" );
231  Target_SetTurretAquire( littleBird, true );
232  littleBird SetVehGoalPos( playerMeshOrigin, 1);
233  littleBird waittill( "near_goal" );
234  littleBird SetSpeed( littleBird.speed, 80, 30 );
235  littleBird waittill ( "goal" );
236 
237  // begin following player
238  littleBird thread ‪heliGuardSupport_followPlayer();
239 
240  // dodge the first sam attack
241  //littleBird thread helicopter::handleIncomingSAM(&heliGuardSupport_watchSAMProximity );
242 }
243 
244 
245 function ‪heliGuardSupport_followPlayer() // self == heliGuard
246 {
247  level endon( "game_ended" );
248  self endon( "death" );
249  self endon( "leaving" );
250 
251  if( !isdefined( self.owner ) )
252  {
253  self thread ‪heliGuardSupport_leave();
254  return;
255  }
256 
257  self SetSpeed( self.followSpeed, 20, 20 );
258  while( true )
259  {
260  if( isdefined( self.owner ) && IsAlive( self.owner ) )
261  {
263  }
264  wait( 3 );
265  }
266 }
267 
268 
269 function ‪heliGuardSupport_moveToPlayer() // self == heliGuard
270 {
271  self notify( "heliGuardSupport_moveToPlayer" );
272  self endon( "heliGuardSupport_moveToPlayer" );
273 
274  level endon( "game_ended" );
275  self endon( "death" );
276  self endon( "leaving" );
277  self.owner endon( "death" );
278  self.owner endon( "disconnect" );
279  self.owner endon( "joined_team" );
280  self.owner endon( "joined_spectators" );
281 
282  maxMeshHeight = ‪getMeshHeight( self, self.owner );
283 
284  hoverGoal = ( self.owner.origin[0], self.owner.origin[1], maxMeshHeight );
285 
286  zoneIndex = ‪airsupport::crossesNoFlyZone( self.origin, hoverGoal );
287  if ( isdefined( zoneIndex ) && level.heliGuardFlyOverNFZ )
288  {
289  self.inTransit = true;
290 
291  noFlyZoneHeight = ‪airsupport::getNoFlyZoneHeightCrossed( hoverGoal, self.origin, maxMeshHeight );
292  self setVehGoalPos(( hoverGoal[0], hoverGoal[1], noFlyZoneHeight ), true );
293  self waittill ( "goal" );
294  return;
295  }
296 
297  if ( isdefined( zoneIndex ) )
298  {
299  dist = Distance2D( self.owner.origin, level.noFlyZones[zoneIndex].origin );
300 
301  zoneOrgToPlayer2D = self.owner.origin - level.noFlyZones[zoneIndex].origin;
302  zoneOrgToPlayer2D *= (1,1,0);
303 
304  zoneOrgToChopper2D = self.origin - level.noFlyZones[zoneIndex].origin;
305  zoneOrgToChopper2D *= (1,1,0);
306 
307  zoneOrgAtMeshHeight = ( level.noFlyZones[zoneIndex].origin[0], level.noFlyZones[zoneIndex].origin[1], maxMeshHeight );
308 
309  // adjacent to the no fly zone closest to the player
310  zoneOrgToAdjPos = VectorScale( VectorNormalize( zoneOrgToPlayer2D ), level.noFlyZones[ zoneIndex ].radius + 150.0 );
311 
312  adjacentGoalPos = zoneOrgToAdjPos + level.noFlyZones[zoneIndex].origin;
313  adjacentGoalPos = ( adjacentGoalPos[0], adjacentGoalPos[1], maxMeshHeight );
314 
315  zoneOrgToPerpendicular = ( zoneOrgToAdjPos[1], -zoneOrgToAdjPos[0], 0 );
316  zoneOrgToOppositePerpendicular = ( -zoneOrgToAdjPos[1], zoneOrgToAdjPos[0], 0 );
317 
318  perpendicularGoalPos = zoneOrgToPerpendicular + zoneOrgAtMeshHeight;
319  oppositePerpendicularGoalPos = zoneOrgToOppositePerpendicular + zoneOrgAtMeshHeight;
320 
321  if ( dist < level.noFlyZones[zoneIndex].radius )
322  {
323  zoneIndex = undefined;
324  zoneIndex = ‪airsupport::crossesNoFlyZone( self.origin, adjacentGoalPos );
325 
326  if ( isdefined( zoneIndex ))
327  {
328  hoverGoal = perpendicularGoalPos;
329  }
330  else
331  {
332  hoverGoal = adjacentGoalPos;
333  }
334  }
335  else
336  {
337  // player is outside the radius, but a no fly zone is in the way
338  // try to set new goal tangent to the offending no fly zone in the direction of the player
339  hoverGoal = perpendicularGoalPos;
340  }
341  }
342 
343  zoneIndex = undefined;
344  zoneIndex = ‪airsupport::crossesNoFlyZone( self.origin, hoverGoal );
345  if ( isdefined( zoneIndex ))
346  {
347  hoverGoal = oppositePerpendicularGoalPos;
348  }
349 
350  self.inTransit = true;
351 
352  self setVehGoalPos(( hoverGoal[0], hoverGoal[1], maxMeshHeight ), true );
353  self waittill ( "goal" );
354 }
355 
356 function ‪heliGuardSupport_moveToPlayerVertical ( maxMeshHeight ) // self == heli
357 {
358  height = ‪airsupport::getNoFlyZoneHeightCrossed( self.origin, self.owner.origin, maxMeshHeight );
359  upperHeight = max( self.origin[2], height );
360 
361  acquireUpperHeight = ( self.origin[0], self.origin[1], upperHeight );
362  hoverOverPlayer = ( self.owner.origin[0], self.owner.origin[1], upperHeight );
363  hoverCorrectHeight = ( self.owner.origin[0], self.owner.origin[1], height );
364 
365  self.inTransit = true; // needed?
366  self setVehGoalPos( acquireUpperHeight, true );
367  self waittill ( "goal" );
368 
369  self setVehGoalPos( hoverOverPlayer, true );
370  self waittill ( "goal" );
371 
372  self setVehGoalPos( hoverCorrectHeight, true );
373  self waittill ( "goal" );
374 
375  self.inTransit = false;
376 }
377 
378 //
379 // state trackers
380 //
381 
383 {
384  self notify( "heliGuardSupport_watchForEarlyLeave" );
385  self endon( "heliGuardSupport_watchForEarlyLeave" );
386  level endon ( "game_ended" );
387  self endon( "death" );
388  self endon( "leaving" );
389 
390  self.owner ‪util::waittill_any( "disconnect", "joined_team", "joined_spectators" );
391 
392  // leave
393  self thread ‪heliGuardSupport_leave();
394 }
395 
396 function ‪heliGuardSupport_watchOwnerDamage() // self == heliGuard
397 {
398  self notify( "heliGuardSupport_watchOwnerDamage" );
399  self endon( "heliGuardSupport_watchOwnerDamage" );
400  level endon ( "game_ended" );
401  self endon( "death" );
402  self endon( "leaving" );
403  self.owner endon( "disconnect" );
404  self.owner endon( "joined_team" );
405  self.owner endon( "joined_spectators" );
406 
407  while( true )
408  {
409  // if someone is attacking the owner, attack them
410  self.owner waittill( "damage", ‪damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, weapon, iDFlags );
411 
412  if( isPlayer( attacker ) )
413  {
414  if( attacker != self.owner && Distance2D( attacker.origin, self.origin ) <= self.targettingRadius && attacker ‪airsupport::canTargetPlayerWithSpecialty() )
415  {
416  self SetLookAtEnt( attacker );
417  self setGunnerTargetEnt( attacker, ‪PLAYER_HEIGHT_INCREASE, ‪HELI_GUARD_GUNNER );
418  self setturrettargetent( attacker, ‪PLAYER_HEIGHT_INCREASE );
419  }
420  }
421  }
422 }
423 
425 {
426  level endon ( "game_ended" );
427  self endon( "death" );
428  self endon( "leaving" );
429  self.owner endon( "disconnect" );
430  self.owner endon( "joined_team" );
431  self.owner endon( "joined_spectators" );
432 
433  level waittill ( "round_end_finished" );
434 
435  // leave
436  self thread ‪heliGuardSupport_leave();
437 }
438 
440 {
441  self endon( "death" );
442  self notify( "leaving" );
443  level.littlebirdGuard = undefined;
444 
445  self cleargunnertarget(‪HELI_GUARD_GUNNER);
446  self clearturrettarget();
447 
448  // rise
449  self ClearLookAtEnt();
450  flyHeight = ‪airsupport::getNoFlyZoneHeight( self.origin );
451  targetPos = self.origin + anglesToForward( self.angles ) * 1500 + (0,0,flyHeight);
452  collide = ‪airsupport::crossesNoFlyZone(self.origin, targetPos);
453  tries = 5;
454  while ( isdefined( collide ) && tries > 0 )
455  {
456  yaw = RandomInt(360);
457  targetPos = self.origin + anglesToForward( (self.angles[0], yaw, self.angles[2]) ) * 1500 + (0,0,flyHeight);
458  collide = ‪airsupport::crossesNoFlyZone(self.origin, targetPos);
459  tries--;
460  }
461  if ( tries == 0 )
462  {
463  targetPos = self.origin + (0,0,flyHeight);
464  }
465  self SetSpeed( self.speed, 80 );
466  self SetMaxPitchRoll( 45, 180 );
467  self setVehGoalPos( targetPos );
468  self waittill ( "goal" );
469 
470  // leave
471  targetPos = targetPos + anglesToForward( (0,self.angles[1],self.angles[2]) ) * 14000;
472  self setVehGoalPos( targetPos );
473  self waittill ( "goal" );
474 
475  // remove
476  self notify( "gone" );
477  self ‪removeLittlebird();
478 }
479 
481 {
482  level.littlebirdGuard = undefined;
483 
484  if (! isdefined(self) )
485  return;
486 
487  self SetSpeed( 25, 5 );
488  self thread ‪lbSpin( RandomIntRange(180, 220) );
489 
490  wait( RandomFloatRange( .5, 1.5 ) );
491 
492  ‪lbExplode();
493 }
494 
495 function ‪lbExplode()
496 {
497  self notify ( "explode" );
498 
499  self ‪removeLittlebird();
500 }
501 
502 function ‪lbSpin( speed )
503 {
504  self endon( "explode" );
505 
506  // tail explosion that caused the spinning
507  playfxontag( level.chopper_fx["explode"]["large"], self, "tail_rotor_jnt" );
508  self thread ‪trail_fx( level.chopper_fx["smoke"]["trail"], "tail_rotor_jnt", "stop tail smoke" );
509 
510  self setyawspeed( speed, speed, speed );
511  while ( isdefined( self ) )
512  {
513  self settargetyaw( self.angles[1]+(speed*0.9) );
514  wait ( 1 );
515  }
516 }
517 
518 function ‪trail_fx( ‪trail_fx, trail_tag, stop_notify )
519 {
520  // only one instance allowed
521  self notify( stop_notify );
522  self endon( stop_notify );
523  self endon( "death" );
524 
525  for ( ;; )
526  {
527  playfxontag( ‪trail_fx, self, trail_tag );
529  }
530 }
531 
533 {
534  level.lbStrike = 0;
535  ‪killstreakrules::killstreakStop( "helicopter_guard", self.originalteam, self.killstreak_id );
536 
538 
539  if( isdefined( self.marker ) )
540  self.marker delete();
541 
542  self delete();
543 }
544 
545 // this is different from the flares monitoring that the other helicopters do
546 // we want this to dodge the missiles if at all possible, making for a cool evasive manuever
547 function ‪heliGuardSupport_watchSAMProximity( player, missileTeam, missileTarget, missileGroup ) // self == level
548 {
549  level endon ( "game_ended" );
550  missileTarget endon( "death" );
551 
552  for( i = 0; i < missileGroup.size; i++ )
553  {
554  if( isdefined( missileGroup[ i ] ) && !missileTarget.hasDodged )
555  {
556  missileTarget.hasDodged = true;
557 
558  newTarget = ‪spawn( "script_origin", missileTarget.origin );
559  newTarget.angles = missileTarget.angles;
560  newTarget MoveGravity( AnglesToRight( missileGroup[ i ].angles ) * -1000, 0.05 );
561  //newTarget thread helicopter::deleteAfterTime( 5.0 );
562 
563  for( j = 0; j < missileGroup.size; j++ )
564  {
565  if( isdefined( missileGroup[ j ] ) )
566  {
567  missileGroup[ j ] SetTargetEntity( newTarget );
568  }
569  }
570 
571  // dodge the incoming missiles
572  dodgePoint = missileTarget.origin + ( AnglesToRight( missileGroup[ i ].angles ) * 200 );
573  missileTarget SetSpeed( missileTarget.speed, 100, 40 );
574  missileTarget SetVehGoalPos( dodgePoint, true );
575 
576  wait( 2.0 );
577  missileTarget SetSpeed( missileTarget.followSpeed, 20, 20 );
578  break;
579  }
580  }
581 }
582 
583 //
584 // node funcs
585 //
586 
588 {
589  // gets the start node that is closest to the position passed in
590  closestNode = undefined;
591  closestDistance = 999999;
592 
593  foreach( path in level.heli_paths )
594  {
595  foreach( loc in path )
596  {
597  nodeDistance = distance( loc.origin, pos );
598  if ( nodeDistance < closestDistance )
599  {
600  closestNode = loc;
601  closestDistance = nodeDistance;
602  }
603  }
604  }
605 
606  return closestNode;
607 }
608 
610 {
611  // gets the closest node to the position passed in, regardless of link
612  closestNode = undefined;
613  closestDistance = 999999;
614 
615  foreach( loc in level.heli_loop_paths )
616  {
617  nodeDistance = distance( loc.origin, pos );
618  if ( nodeDistance < closestDistance )
619  {
620  closestNode = loc;
621  closestDistance = nodeDistance;
622  }
623  }
624 
625  return closestNode;
626 }
627 
628 function ‪heliGuardSupport_getClosestLinkedNode( pos ) // self == heliGuard
629 {
630  // gets the linked node that is closest to the current position and moving towards the position passed in
631  closestNode = undefined;
632  totalDistance = Distance2D( self.currentNode.origin, pos );
633  closestDistance = totalDistance;
634 
635  target = self.currentNode.target;
636 
637  while( isdefined( target ) )
638  {
639  nextNode = GetEnt( target, "targetname" );
640 
641  if ( nextNode == self.currentNode )
642  {
643  break;
644  }
645 
646  nodeDistance = Distance2D( nextNode.origin, pos );
647  if ( nodeDistance < totalDistance && nodeDistance < closestDistance )
648  {
649  closestNode = nextNode;
650  closestDistance = nodeDistance;
651  }
652 
653  target = nextNode.target;
654  }
655 
656  return closestNode;
657 }
658 
660 {
661  if ( ‪array.size <= 0 )
662  return false;
663 
664  foreach ( member in ‪array )
665  {
666  if ( member == compare )
667  return true;
668  }
669 
670  return false;
671 }
672 
673 
675 {
676  ‪array = [];
677  return ‪array;
678 }
679 
681 {
682  level.air_start_nodes = ‪struct::get_array( "chopper_boss_path_start", "targetname" );
683 
684  foreach( loc in level.air_start_nodes )
685  {
686  // Grab array of path loc refs that this loc links to
687  loc.neighbors = loc ‪heliGuardSupport_getLinkedStructs();
688  }
689 }
690 
692 {
693  level.air_node_mesh = ‪struct::get_array( "so_chopper_boss_path_struct", "script_noteworthy" );
694 
695  foreach( loc in level.air_node_mesh )
696  {
697  // Grab array of path loc refs that this loc links to
698  loc.neighbors = loc ‪heliGuardSupport_getLinkedStructs();
699 
700  // Step through each loc in the map and if it
701  // links to this loc, add it
702  foreach( other_loc in level.air_node_mesh )
703  {
704  if ( loc == other_loc )
705  continue;
706 
707  if ( !‪heliGuardSupport_arrayContains( loc.neighbors, other_loc ) && ‪heliGuardSupport_arrayContains( other_loc ‪heliGuardSupport_getLinkedStructs(), loc ) )
708  loc.neighbors[ loc.neighbors.size ] = other_loc;
709  }
710  }
711 }
712 
713 /* ============================
714 Turret Logic Functions
715 ============================ */
716 
717 function ‪heliGuardSupport_attackTargets() // self == turret
718 {
719  self endon( "death" );
720  level endon( "game_ended" );
721  self endon( "leaving" );
722 
723  for (;;)
724  {
726  }
727 }
728 
729 function ‪heliGuardSupport_fireStart() // self == turret
730 {
731  self endon( "death" );
732  self endon( "leaving" );
733  self endon( "stop_shooting" );
734  level endon( "game_ended" );
735 
736  for ( ;; )
737  {
738  numShots = RandomIntRange( ‪HELI_GUARD_MIN_SHOTS, ‪HELI_GUARD_MAX_SHOTS + 1 );
739 
740  if ( !isdefined( self.primaryTarget ) )
741  {
742  self waittill( "primary acquired");
743  }
744 
745  if ( isdefined( self.primaryTarget ) )
746  {
747  targetEnt = self.primaryTarget;
748  self thread ‪heliGuardSupport_fireStop( targetEnt );
749 
750  self SetLookAtEnt( targetEnt );
751 
752  self setGunnerTargetEnt( targetEnt, ‪PLAYER_HEIGHT_INCREASE, ‪HELI_GUARD_GUNNER );
753  self setturrettargetent( targetEnt, ‪PLAYER_HEIGHT_INCREASE );
754  self waittill( "turret_on_target" );
755 
756  wait( ‪HELI_GUARD_SPINUP );
757 
758  self ‪clientfield::set("vehicle_is_firing", 1);
759 
760  for ( i = 0; i < numShots; i++ )
761  {
762  self ‪fireWeapon( ‪HELI_GUARD_GUNNER + 1, undefined, undefined, self );
763  self fireweapon();
764  wait ( ‪HELI_GUARD_FIRE_TIME );
765  }
766  }
767 
768  self ‪clientfield::set("vehicle_is_firing", 0);
769  //level util::clientNotify("nofir");
770 
771  self clearturrettarget();
772  self cleargunnertarget(‪HELI_GUARD_GUNNER);
773  wait ( RandomFloatRange( ‪HELI_GUARD_MIN_PAUSE, ‪HELI_GUARD_MAX_PAUSE ) );
774  }
775 }
776 
777 function ‪heliGuardSupport_fireStop( targetEnt ) // self == turret
778 {
779  self endon( "death" );
780  self endon( "leaving" );
781  self notify( "heli_guard_target_death_watcher" );
782  self endon( "heli_guard_target_death_watcher" );
783 
784  targetEnt ‪util::waittill_any( "death", "disconnect" );
785 
786  self ‪clientfield::set("vehicle_is_firing", 0);
787 
788  self notify( "stop_shooting" );
789  self.primaryTarget = undefined;
790  self SetLookAtEnt( self.owner );
791  self cleargunnertarget(‪HELI_GUARD_GUNNER);
792  self clearturrettarget();
793 }
794 
795 /* ============================
796 END Turret Logic Functions
797 ============================ */
‪heliGuardSupport_followPlayer
‪function heliGuardSupport_followPlayer()
Definition: _helicopter_guard.gsc:245
‪startHeliGuardSupport
‪function startHeliGuardSupport(littleBird, lifeId)
Definition: _helicopter_guard.gsc:204
‪register
‪function register()
Definition: _helicopter_guard.gsc:63
‪heliGuardSupport_watchForEarlyLeave
‪function heliGuardSupport_watchForEarlyLeave()
Definition: _helicopter_guard.gsc:382
‪heliGuardSupport_fireStart
‪function heliGuardSupport_fireStart()
Definition: _helicopter_guard.gsc:729
‪WaitForTimeout
‪function WaitForTimeout(killstreak, duration, callback, endCondition1, endCondition2, endCondition3)
Definition: _killstreaks.gsc:2913
‪HELI_GUARD_MAX_SHOTS
‪#define HELI_GUARD_MAX_SHOTS
Definition: _helicopter_guard.gsc:57
‪heliGuardSupport_attackTargets
‪function heliGuardSupport_attackTargets()
Definition: _helicopter_guard.gsc:717
‪MissileTarget_ProximityDetonateIncomingMissile
‪function MissileTarget_ProximityDetonateIncomingMissile(endon1, endon2, allowDirectDamage)
Definition: _heatseekingmissile.gsc:1085
‪getMinimumFlyHeight
‪function getMinimumFlyHeight()
Definition: _airsupport.gsc:167
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪getNoFlyZoneHeight
‪function getNoFlyZoneHeight(point)
Definition: _airsupport.gsc:352
‪heliGuardSupport_arrayContains
‪function heliGuardSupport_arrayContains(array, compare)
Definition: _helicopter_guard.gsc:659
‪ENEMY_VEHICLE_ACTIVE
‪#define ENEMY_VEHICLE_ACTIVE
Definition: _hacker_tool.gsh:2
‪heliGuardSupport_fireStop
‪function heliGuardSupport_fireStop(targetEnt)
Definition: _helicopter_guard.gsc:777
‪ConfigureTeamPost
‪function ConfigureTeamPost(owner, isHacked)
Definition: _helicopter_guard.gsc:103
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪tryUseheliGuardSupport
‪function tryUseheliGuardSupport(lifeId)
Definition: _helicopter_guard.gsc:69
‪heliGuardSupport_watchRoundEnd
‪function heliGuardSupport_watchRoundEnd()
Definition: _helicopter_guard.gsc:424
‪trail_fx
‪function trail_fx(trail_fx, trail_tag, stop_notify)
Definition: _helicopter_guard.gsc:518
‪HELI_GUARD_SPINUP
‪#define HELI_GUARD_SPINUP
Definition: _helicopter_guard.gsc:61
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪wait_for_killed
‪function wait_for_killed()
Definition: _helicopter.gsc:1183
‪canTargetPlayerWithSpecialty
‪function canTargetPlayerWithSpecialty()
Definition: _airsupport.gsc:1228
‪heli_health
‪function heli_health(hardpointType, playerNotify)
Definition: _helicopter.gsc:1685
‪set_team_kill_penalty_scale
‪function set_team_kill_penalty_scale(killstreakType, scale, isInventory)
Definition: _killstreaks.gsc:404
‪getNoFlyZoneHeightCrossed
‪function getNoFlyZoneHeightCrossed(start, end, minHeight)
Definition: _airsupport.gsc:430
‪heliGuardSupport_leave
‪function heliGuardSupport_leave()
Definition: _helicopter_guard.gsc:439
‪HELI_GUARD_FIRE_TIME
‪#define HELI_GUARD_FIRE_TIME
Definition: _helicopter_guard.gsc:55
‪heliGuardSupport_moveToPlayer
‪function heliGuardSupport_moveToPlayer()
Definition: _helicopter_guard.gsc:269
‪heliGuardSupport_getLinkedStructs
‪function heliGuardSupport_getLinkedStructs()
Definition: _helicopter_guard.gsc:674
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪PLAYER_HEIGHT_INCREASE
‪#define PLAYER_HEIGHT_INCREASE
Definition: _helicopter_guard.gsc:54
‪HELI_GUARD_GUNNER
‪#define HELI_GUARD_GUNNER
Definition: _helicopter_guard.gsc:60
‪heliGuardSupport_watchSAMProximity
‪function heliGuardSupport_watchSAMProximity(player, missileTeam, missileTarget, missileGroup)
Definition: _helicopter_guard.gsc:547
‪remove_influencers
‪function remove_influencers()
Definition: _spawning.gsc:405
‪createHeliGuardSupport
‪function createHeliGuardSupport(lifeId, killstreak_id)
Definition: _helicopter_guard.gsc:110
‪register_dialog
‪function register_dialog(killstreakType, informDialog, taacomDialogBundleKey, pilotDialogArrayKey, startDialogKey, enemyStartDialogKey, enemyStartMultipleDialogKey, hackedDialogKey, hackedStartDialogKey, requestDialogKey, threatDialogKey, isInventory)
Definition: _killstreaks.gsc:239
‪lbSpin
‪function lbSpin(speed)
Definition: _helicopter_guard.gsc:502
‪heliDestroyed
‪function heliDestroyed()
Definition: _helicopter_guard.gsc:480
‪array
‪function filter array
Definition: array_shared.csc:16
‪heli_targeting
‪function heli_targeting(missilesEnabled, hardpointType)
Definition: _helicopter.gsc:678
‪HELI_GUARD_MIN_SHOTS
‪#define HELI_GUARD_MIN_SHOTS
Definition: _helicopter_guard.gsc:56
‪heliGuardSupport_setAirNodeMesh
‪function heliGuardSupport_setAirNodeMesh()
Definition: _helicopter_guard.gsc:691
‪register_strings
‪function register_strings(killstreakType, receivedText, notUsableText, inboundText, inboundNearPlayerText, hackedText, utilizesAirspace=true, isInventory=false)
Definition: _killstreaks.gsc:223
‪killstreakStop
‪function killstreakStop(hardpointType, team, id)
Definition: _killstreakrules.gsc:293
‪getMeshHeight
‪function getMeshHeight(littleBird, owner)
Definition: _helicopter_guard.gsc:193
‪heliGuardSupport_watchOwnerDamage
‪function heliGuardSupport_watchOwnerDamage()
Definition: _helicopter_guard.gsc:396
‪init
‪function init()
Definition: _helicopter_guard.gsc:34
‪killstreakStart
‪function killstreakStart(hardpointType, team, hacked, displayTeamMessage)
Definition: _killstreakrules.gsc:184
‪crossesNoFlyZone
‪function crossesNoFlyZone(start, end)
Definition: _airsupport.gsc:391
‪lbExplode
‪function lbExplode()
Definition: _helicopter_guard.gsc:495
‪heliGuardSupport_moveToPlayerVertical
‪function heliGuardSupport_moveToPlayerVertical(maxMeshHeight)
Definition: _helicopter_guard.gsc:356
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪configure_team
‪function configure_team(killstreakType, killstreakId, owner, influencerType, configureTeamPreFunction, configureTeamPostFunction, isHacked=false)
Definition: _killstreaks.gsc:2806
‪HELI_GUARD_MIN_PAUSE
‪#define HELI_GUARD_MIN_PAUSE
Definition: _helicopter_guard.gsc:58
‪heliGuardSupport_getClosestNode
‪function heliGuardSupport_getClosestNode(pos)
Definition: _helicopter_guard.gsc:609
‪register_alt_weapon
‪function register_alt_weapon(killstreakType, weaponName, isInventory)
Definition: _killstreaks.gsc:318
‪create_flare_ent
‪function create_flare_ent(offset)
Definition: _helicopter.gsc:645
‪heliGuardSupport_getClosestLinkedNode
‪function heliGuardSupport_getClosestLinkedNode(pos)
Definition: _helicopter_guard.gsc:628
‪enable_hacking
‪function enable_hacking(killstreakName, preHackFunction, postHackFunction)
Definition: _killstreak_hacking.gsc:22
‪removeLittlebird
‪function removeLittlebird()
Definition: _helicopter_guard.gsc:532
‪announceHelicopterInbound
‪function announceHelicopterInbound(hardpointType)
Definition: _helicopter.gsc:140
‪heliGuardSupport_getClosestStartNode
‪function heliGuardSupport_getClosestStartNode(pos)
Definition: _helicopter_guard.gsc:587
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪HELI_GUARD_MAX_PAUSE
‪#define HELI_GUARD_MAX_PAUSE
Definition: _helicopter_guard.gsc:59
‪heliGuardSupport_setAirStartNodes
‪function heliGuardSupport_setAirStartNodes()
Definition: _helicopter_guard.gsc:680
‪fireWeapon
‪function fireWeapon(weaponName)
Definition: end_game_taunts.csc:1118
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265