‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_raps.gsc
Go to the documentation of this file.
1 #using scripts\shared\callbacks_shared;
2 #using scripts\shared\challenges_shared;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\system_shared;
5 #using scripts\shared\array_shared;
6 #using scripts\shared\util_shared;
7 #using scripts\shared\scoreevents_shared;
8 #using scripts\shared\killstreaks_shared;
9 #using scripts\shared\vehicle_ai_shared;
10 #using scripts\shared\vehicle_shared;
11 #using scripts\shared\vehicles\_raps;
12 #using scripts\shared\weapons\_smokegrenade;
13 
14 #using scripts\mp\gametypes\_battlechatter;
15 #using scripts\mp\gametypes\_globallogic_audio;
16 #using scripts\mp\gametypes\_spawning;
17 #using scripts\mp\gametypes\_spawnlogic;
18 #using scripts\mp\teams\_teams;
19 #using scripts\mp\killstreaks\_helicopter;
20 #using scripts\mp\killstreaks\_killstreak_bundles;
21 #using scripts\mp\killstreaks\_killstreak_detect;
22 #using scripts\mp\killstreaks\_killstreak_hacking;
23 #using scripts\mp\killstreaks\_killstreakrules;
24 #using scripts\mp\killstreaks\_killstreaks;
25 #using scripts\mp\killstreaks\_airsupport;
26 
27 #insert scripts\mp\_hacker_tool.gsh;
28 #insert scripts\mp\killstreaks\_killstreaks.gsh;
29 #insert scripts\shared\clientfields.gsh;
30 #insert scripts\shared\shared.gsh;
31 #insert scripts\shared\version.gsh;
32 
33 #namespace raps_mp;
34 
35 #define RAPS_HURT_TRIGGER_IMMUNE_DURATION_MS 5000
36 #define RAPS_HELI_POST_DEATH_FX_GHOST_DELAY 0.1
37 
38 #precache( "string", "KILLSTREAK_DESTROYED_RAPS_DEPLOY_SHIP");
39 #precache( "string", "KILLSTREAK_EARNED_RAPS" );
40 #precache( "string", "KILLSTREAK_RAPS_NOT_AVAILABLE" );
41 #precache( "string", "KILLSTREAK_RAPS_NOT_PLACEABLE" );
42 #precache( "string", "KILLSTREAK_RAPS_INBOUND" );
43 #precache( "string", "KILLSTREAK_RAPS_HACKED" );
44 #precache( "eventstring", "mpl_killstreak_raps" );
45 #precache( "fx", RAPS_HELI_FIRST_EXPLO_FX );
46 #precache( "fx", RAPS_HELI_DEATH_TRAIL_FX );
47 #precache( "fx", RAPS_HELI_DEATH_FX );
48 
49 function ‪init()
50 {
51  level.raps_settings = level.scriptbundles[ "vehiclecustomsettings" ][ "rapssettings_mp" ];
52  assert( isdefined( level.raps_settings ) );
53 
54  level.raps = [];
55  level.raps_helicopters = [];
56 
57  level.raps_force_get_enemies = &‪ForceGetEnemies;
58 
59  ‪killstreaks::register( ‪RAPS_NAME, ‪RAPS_NAME, "killstreak_raps", "raps_used", &‪ActivateRapsKillstreak, true );
60  ‪killstreaks::register_strings( ‪RAPS_NAME, &"KILLSTREAK_EARNED_RAPS", &"KILLSTREAK_RAPS_NOT_AVAILABLE", &"KILLSTREAK_RAPS_INBOUND", undefined, &"KILLSTREAK_RAPS_HACKED" );
61  ‪killstreaks::register_dialog( ‪RAPS_NAME, "mpl_killstreak_raps", "rapsHelicopterDialogBundle", "rapsHelicopterPilotDialogBundle", "friendlyRaps", "enemyRaps", "enemyRapsMultiple", "friendlyRapsHacked", "enemyRapsHacked", "requestRaps", "threatRaps" );
63 
65 
67 
69 
70  ‪clientfield::register( "vehicle", "monitor_raps_drop_landing", ‪VERSION_SHIP, 1, "int" );
71  ‪clientfield::register( "vehicle", "raps_heli_low_health", ‪VERSION_SHIP, 1, "int" );
72  ‪clientfield::register( "vehicle", "raps_heli_extra_low_health", ‪VERSION_SHIP, 1, "int" );
73 
74  // level thread RapsHelicopterDynamicAvoidance(); // aku: disabling avoidance for now because it's avoidance technique does not "look right", going for different z heights for now
75 
76  level.raps_helicopter_drop_tag_names = [];
77  level.raps_helicopter_drop_tag_names[0] = "tag_raps_drop_left";
78  level.raps_helicopter_drop_tag_names[1] = "tag_raps_drop_right";
79 }
80 
82 {
83  self.entNum = self getEntityNumber();
84  level.raps[ self.entNum ] = spawnstruct();
85  level.raps[ self.entNum ].killstreak_id = ‪INVALID_KILLSTREAK_ID;
86  level.raps[ self.entNum ].raps = [];
87  level.raps[ self.entNum ].helicopter = undefined;
88 }
89 
90 /* RapsHelicopterDynamicAvoidance
91  *
92  * This method supports a simple avoidance system for the RAPS Helicopter (RAPS deploy ship).
93  *
94  * The RAPS helicopters are required to fly at the same hight. To prevent overlapping, this system checks
95  * the helicopters relative to each other and changes driving behavior based on different distances.
96  * The system will choose another deploy point based on distance, last pick time, and other factors.
97  *
98  * Note: tuning vars in _killstreaks.gsh using RAPS_HELAV where HELAV is short for Helicopter Avoidance
99  *
100  * The RAPS helicopter avoidance has been designed to function with at most two RAPS helicopters for now.
101  *
102  * Key concepts in use:
103  * a. Forward Reference Point -- distances are measured relative to this forward reference point ( RAPS_HELAV_FORWARD_OFFSET )
104  * b. Other Forward Ref Point -- this is the reference point used when testing distances from another helicopter ( RAPS_HELAV_OTHER_FORWARD_OFFSET )
105  * c. Stop Distance -- the helicopter stops when another helicopter is within this distance
106  * d. Slow Down Distance -- the helicopter slows down when another helicopter is within this distance
107  * e. Pick New Goal Distance -- the helicopter selects a new drop point when the other helicopter is within this distance
108  * f. Backing Off -- if a helicopter stops and the other helicopter is in front of it, it will pick a random point opposite
109  * the direction behind it and can pick a new goal (drop point) to go to after it backs off
110  * g. Drive Mode -- there are four different drive modes: expedient, cautious, more cautious, and stop.
111  * Each has different speed, acceleration, and deceleration.
112  *
113  */
115 {
116  level endon( "game_ended" );
117 
118  index_to_update = 0;
119 
120  while( true )
121  {
122  ‪RapsHelicopterDynamicAvoidanceUpdate( index_to_update );
123 
124  index_to_update++;
125  if ( index_to_update >= level.raps_helicopters.size )
126  index_to_update = 0;
127 
129  }
130 }
131 
132 function ‪RapsHelicopterDynamicAvoidanceUpdate( index_to_update )
133 {
134  helicopterRefOrigin = ( 0, 0, 0 );
135  otherHelicopterRefOrigin = ( 0, 0, 0 );
136 
137  ArrayRemoveValue( level.raps_helicopters, undefined );
138 
139  if ( index_to_update >= level.raps_helicopters.size )
140  index_to_update = 0;
141 
142  if( level.raps_helicopters.size >= 2 )
143  {
144  helicopter = level.raps_helicopters[index_to_update];
145  /# helicopter.__action_just_made = false; #/
146 
147  for( i = 0; i < level.raps_helicopters.size; i++ )
148  {
149  if ( i == index_to_update )
150  continue;
151 
152  if ( helicopter.droppingRaps )
153  continue;
154 
155  if ( !isdefined( helicopter.lastNewGoalTime ) )
156  helicopter.lastNewGoalTime = GetTime();
157 
158  helicopterForward = AnglesToForward( helicopter GetAngles() );
159  helicopterRefOrigin = helicopter.origin + ( helicopterForward * ‪RAPS_HELAV_FORWARD_OFFSET );
160  otherHelicopterForward = AnglesToForward( level.raps_helicopters[i] GetAngles() );
161  otherHelicopterRefOrigin = level.raps_helicopters[i].origin + ( otherHelicopterForward * ‪RAPS_HELAV_OTHER_FORWARD_OFFSET );
162  deltaToOther = otherHelicopterRefOrigin - helicopterRefOrigin;
163  otherInFront = ( VectorDot( helicopterForward, VectorNormalize( deltaToOther ) ) > ‪RAPS_HELAV_IN_FRONT_DOT );
164  distanceSqr = Distance2DSquared( helicopterRefOrigin, otherHelicopterRefOrigin);
165 
166  if ( (distanceSqr < ‪RAPS_HELAV_NEED_NEW_GOAL_DISTANCE_SQR || helicopter GetSpeed() == 0 )
167  && (GetTime() - helicopter.lastNewGoalTime) > ‪RAPS_HELAV_MIN_PICK_NEW_GOAL_TIME_MS )
168  {
169  //
170  // pick a new goal based on distance, speed, and the last time picked
171  //
172  /# helicopter.__last_dynamic_avoidance_action = 20; /* new goal */ #/
173  /# helicopter.__action_just_made = true; #/
174 
175  helicopter ‪UpdateHelicopterSpeed();
176  if ( helicopter.isLeaving )
177  {
178  self.leaveLocation = ‪GetRandomHelicopterLeaveOrigin( /*self.assigned_fly_height*/ 0, self.origin );
179  helicopter setVehGoalPos( self.leaveLocation, 0 );
180  }
181  else
182  {
183  self.targetDropLocation = ‪GetRandomHelicopterPosition( self.lastDropLocation );
184  helicopter setVehGoalPos( self.targetDropLocation, 1 );
185  }
186  helicopter.lastNewGoalTime = GetTime();
187  }
188  else if ( distanceSqr < ‪RAPS_HELAV_FULL_STOP_DISTANCE_SQR
189  && otherInFront
190  && (GetTime() - helicopter.lastStopTime) > ‪RAPS_HELAV_MIN_TIME_BETWEEN_FULL_STOPS_MS
191  )
192  {
193  //
194  // do a full stop if the other helicopter is in front and is too close
195  //
196  /# helicopter.__last_dynamic_avoidance_action = 10; /* stop */ #/
197  /# helicopter.__action_just_made = true; #/
198 
199  helicopter ‪StopHelicopter();
200  }
201  else if ( helicopter GetSpeed() == 0 && otherInFront && distanceSqr < ‪RAPS_HELAV_FULL_STOP_DISTANCE_SQR )
202  {
203  //
204  // after a full stop, have the helicopter back off if the other helicopter is in front and too close
205  // and a new drop location may be picked based on the tuning vars
206  //
207  /# helicopter.__last_dynamic_avoidance_action = 50; /* back off */ #/
208  /# helicopter.__action_just_made = true; #/
209 
210  delta = otherHelicopterRefOrigin - helicopterRefOrigin;
211  newGoalPosition = helicopter.origin -
212  ( deltaToOther[0] * RandomFloatRange( ‪RAPS_HELAV_BACK_OFF_FACTOR_MIN, ‪RAPS_HELAV_BACK_OFF_FACTOR_MAX ),
213  deltaToOther[1] * RandomFloatRange( ‪RAPS_HELAV_BACK_OFF_FACTOR_MIN, ‪RAPS_HELAV_BACK_OFF_FACTOR_MAX), 0 );
214  helicopter ‪UpdateHelicopterSpeed();
215  helicopter setVehGoalPos( newGoalPosition, 0 );
216 
217  // pick a new drop location for use after the "back off" goal is reached
218  if ( ‪RAPS_HELAV_ALWAYS_PICK_NEW_GOAL_POST_BACK_OFF || (GetTime() - helicopter.lastNewGoalTime) > ‪RAPS_HELAV_MIN_PICK_NEW_GOAL_TIME_MS )
219  {
220  /# helicopter.__last_dynamic_avoidance_action = 51; /* back off + new goal */ #/
221  helicopter.targetDropLocation = ‪GetClosestRandomHelicopterPosition( newGoalPosition, 8 );
222  helicopter.lastNewGoalTime = GetTime();
223  }
224  }
225  else if ( distanceSqr < ‪RAPS_HELAV_SLOW_DOWN_DISTANCE_SQR && helicopter.driveModeSpeedScale == 1.0 )
226  {
227  //
228  // slow down the helicopter if within the configured distances and at full speed
229  // there is a cautious and a more cautious speed based on if the other helicopter is in front
230  //
231  /# helicopter.__last_dynamic_avoidance_action = (( otherInFront ) ? 31 : 30); /* cautious */ #/
232  /# helicopter.__action_just_made = true; #/
233 
235  }
236  else if ( distanceSqr >= ‪RAPS_HELAV_SLOW_DOWN_DISTANCE_SQR && helicopter.driveModeSpeedScale < 1.0 )
237  {
238  //
239  // speed the helicopter back up if we are beyond the slow down distance and set to drive at full speed
240  //
241  /# helicopter.__last_dynamic_avoidance_action = 40; /* expedient */ #/
242  /# helicopter.__action_just_made = true; #/
243 
245  }
246  else if ( helicopter GetSpeed() == 0 && (GetTime() - helicopter.lastStopTime) > ‪RAPS_HELAV_MIN_TIME_BETWEEN_FULL_STOPS_MS )
247  {
248  //
249  // resume moving -- start mmoving again if we have stopped for too long
250  //
251  // devblock to report last action made intentionally left out.
252 
253  helicopter ‪UpdateHelicopterSpeed();
254  }
255  }
256 
257  /#
258  //================================================================================================
259  //
260  // this code section is meant for visual debuggingof the RAPS Helicopter dynamic avoidance system
261  //
262  //------------------------------------------------------------------------------------------------
263  //
264  if ( ‪RAPS_HELAV_DEBUG )
265  {
266  if ( isdefined( helicopter ) )
267  {
268  server_frames_to_persist = INT( (‪RAPS_HELAV_TIME_BETWEEN_UPDATES * 2) / ‪SERVER_FRAME );
269 
270  Sphere( helicopterRefOrigin, 10, ( 0, 0, 1 ), 1, false, 10, server_frames_to_persist );
271  Sphere( otherHelicopterRefOrigin, 10, ( 1, 0, 0 ), 1, false, 10, server_frames_to_persist );
272 
273  circle( helicopterRefOrigin, ‪RAPS_HELAV_SLOW_DOWN_DISTANCE, ( 1, 1, 0 ), true, true, server_frames_to_persist );
274  circle( helicopterRefOrigin, ‪RAPS_HELAV_NEED_NEW_GOAL_DISTANCE, ( 0, 0, 0 ), true, true, server_frames_to_persist );
275  circle( helicopterRefOrigin, ‪RAPS_HELAV_FULL_STOP_DISTANCE, ( 1, 0, 0 ), true, true, server_frames_to_persist );
276 
277  Print3d( helicopter.origin, "Speed: " + INT( helicopter GetSpeedMPH() ), (1,1,1), 1, 2.5, server_frames_to_persist );
278 
279  action_debug_color = ( 0.8, 0.8, 0.8 );
280  debug_action_string = "";
281  if ( helicopter.__action_just_made )
282  action_debug_color = ( 0, 1, 0 );
283 
284  switch ( helicopter.__last_dynamic_avoidance_action )
285  {
286  case 0: break; // do nothing
287  case 10: debug_action_string = "stop"; break;
288  case 20: debug_action_string = "new goal"; break;
289  case 30: debug_action_string = "cautious"; break;
290  case 31: debug_action_string = "more cautious"; break;
291  case 40: debug_action_string = "expedient"; break;
292  case 50: debug_action_string = "back off"; break;
293  case 51: debug_action_string = "back off + new goal"; break;
294  default: debug_action_string = "unknown action"; break;
295  }
296 
297  // display last action taken
298  Print3d( helicopter.origin + ( 0, 0, -50 ), debug_action_string, action_debug_color, 1, 2.5, server_frames_to_persist );
299 
300  }
301  }
302  //
303  //------------------------------------------------------------------------------------------------
304  //
305  // end of visual debug section
306  //
307  //================================================================================================
308  #/
309  }
310 }
311 
312 function ‪ActivateRapsKillstreak( hardpointType )
313 {
314  player = self;
315 
316  if ( !player ‪killstreakrules::isKillstreakAllowed( ‪RAPS_NAME, player.team ) )
317  {
318  return false;
319  }
320 
321  if( game["raps_helicopter_positions"].size <= 0 )
322  {
323  /# IPrintLnBold( "RAPS helicopter position error, check NavMesh." ); #/
324  self iPrintLnBold( &"KILLSTREAK_RAPS_NOT_AVAILABLE" );
325  return false;
326  }
327 
328  killstreakId = player ‪killstreakrules::killstreakStart( ‪RAPS_NAME, player.team );
329  if( killstreakId == ‪INVALID_KILLSTREAK_ID )
330  {
331  player iPrintLnBold( &"KILLSTREAK_RAPS_NOT_AVAILABLE" );
332  return false;
333  }
334 
335  player thread ‪teams::WaitUntilTeamChange( player, &‪OnTeamChanged, player.entNum, "raps_complete" );
336 
337  level thread ‪WatchRapsKillstreakEnd( killstreakId, player.entNum, player.team );
338 
339  helicopter = player ‪SpawnRapsHelicopter( killstreakId );
340  helicopter.killstreakId = killstreakId;
341 
342  player ‪killstreaks::play_killstreak_start_dialog( ‪RAPS_NAME, player.team, killstreakId );
343  player AddWeaponStat( GetWeapon( ‪RAPS_NAME ), "used", 1 );
344 
345  helicopter ‪killstreaks::play_pilot_dialog_on_owner( "arrive", ‪RAPS_NAME, killstreakId );
346 
347  level.raps[ player.entNum ].helicopter = helicopter;
348  ‪ARRAY_ADD( level.raps_helicopters, level.raps[ player.entNum ].helicopter );
349  level thread ‪UpdateKillstreakOnHelicopterDeath( level.raps[ player.entNum ].helicopter, player.entNum );
350 
351 /#
353  {
354  level thread ‪AutoReactivateRapsKillstreak( player.entNum, player, hardpointType );
355  }
356 #/
357 
358  return true;
359 }
360 
361 /#
362 function ‪AutoReactivateRapsKillstreak( ownerEntNum, player, hardpointType )
363 {
364  while( true )
365  {
366  level waittill( "raps_updated_" + ownerEntNum );
367 
368  if( isdefined( level.raps[ ownerEntNum ].helicopter ) )
369  continue;
370 
371  wait ( RandomFloatRange( 2.0, 5.0 ) );
372  player thread ‪ActivateRapsKillstreak( hardpointType );
373 
374  return;
375  }
376 }
377 #/
378 
379 function ‪WatchRapsKillstreakEnd( killstreakId, ownerEntNum, team )
380 {
381  while( true )
382  {
383  level waittill( "raps_updated_" + ownerEntNum );
384 
385  if( isdefined( level.raps[ ownerEntNum ].helicopter ) )
386  {
387  continue;
388  }
389 
390  ‪killstreakrules::killstreakStop( ‪RAPS_NAME, team, killstreakId );
391  return;
392  }
393 }
394 
395 function ‪UpdateKillstreakOnHelicopterDeath( helicopter, ownerEntEnum )
396 {
397  helicopter waittill( "death" );
398 
399  level notify( "raps_updated_" + ownerEntEnum );
400 }
401 
402 function ‪OnTeamChanged( entNum, event )
403 {
404  abandoned = true;
405  ‪DestroyAllRaps( entNum, abandoned );
406 }
407 
408 function ‪OnEMP( attacker, ownerEntNum )
409 {
410  ‪DestroyAllRaps( ownerEntNum );
411 }
412 
413 function ‪NoVehicleFaceThread( mapCenter, radius )
414 {
415  level endon ("game_ended");
416  wait 3; // wait arbitrary time so moving platform can be initialized
417  MarkNoVehicleNavMeshFaces( mapCenter, radius, 21 );
418 }
419 
421 //HELICOPTER
424 {
425 
426  // - - - - -
427  //
428  // -- try to find a reasonable center point on the nav mesh as a starting point to start querying for more points
429  //
430  startSearchPoint = ‪airsupport::GetMapCenter();
431  mapCenter = GetClosestPointOnNavMesh( startSearchPoint, ‪RAPS_HELICOPTER_NAV_MAP_CENTER_MAX_OFFSET );
432 
433  if ( !isdefined( mapCenter ) )
434  {
435  startSearchPoint = ( startSearchPoint[0], startSearchPoint[1], 0 );
436  }
437 
438  remaining_attempts = 10;
439  while ( !isdefined( mapCenter ) && remaining_attempts > 0 )
440  {
441  startSearchPoint += ( 100, 100, 0 );
442  mapCenter = GetClosestPointOnNavMesh( startSearchPoint, ‪RAPS_HELICOPTER_NAV_MAP_CENTER_MAX_OFFSET );
443  remaining_attempts -= 1;
444  }
445 
446  if( !isdefined( mapCenter ) )
447  {
448  mapCenter = ‪airsupport::GetMapCenter();
449  }
450 
451  // - - - - -
452  //
453  // -- now query the nav mesh for some random, reasonably-spaced-out points
454  //
456  if ( radius < 1 )
457  radius = 1;
458 
459  // don't re-generate the points if they are already there
460  if ( IsDefined( game["raps_helicopter_positions"] ) )
461  return;
462 
463  lots_of_height = 1024;
464  randomNavMeshPoints = ‪util::PositionQuery_PointArray( mapCenter, ‪RAPS_HELICOPTER_NAV_RADIUS_MIN, radius * 3, lots_of_height, ‪RAPS_HELICOPTER_NAV_POINT_SPACING );
465  // Hack fix for when the mapCenter cannot be found (mp_veiled / mp_sentosa)
466  if ( randomNavMeshPoints.size == 0 )
467  {
468  mapCenter = ( 0, 0, 39 );
470  }
471 
472  /# position_query_drop_location_count = randomNavMeshPoints.size; #/
473 
474  // add level specific raps drop locations
475  if ( isdefined( level.add_raps_drop_locations ) )
476  {
477  [[ level.add_raps_drop_locations ]]( randomNavMeshPoints );
478  }
479 
480 /#
481  // debug draw level specific points
483  {
484  boxHalfWidth = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.25; // draw a smaller box
485 
486  for( i = position_query_drop_location_count; i < randomNavMeshPoints.size; i++ )
487  {
488  // shows a short orange box
489  Box( randomNavMeshPoints[ i ], (-boxHalfWidth, -boxHalfWidth, 0), (boxHalfWidth, boxHalfWidth, 8.88 ), 0, ( 1.0, 0.53, 0.0 ), 0.9, false, 9999999 );
490  }
491  }
492 #/
493 
494  // get any level specific omit points
495  ‪omit_locations = [];
496  if ( isdefined( level.add_raps_omit_locations ) )
497  {
498  [[ level.add_raps_omit_locations ]]( ‪omit_locations ); // don't add too many of these.
499  }
500 
501 /#
502  // debug draw level specific omit points
504  {
505  debug_radius = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5; // draw a smaller box
506 
507  foreach( omit_location in ‪omit_locations )
508  {
509  // shows a few dark grey circles
510  Circle( omit_location, debug_radius, ( 0.05, 0.05, 0.05 ), false, true, 9999999 );
511  Circle( omit_location + ( 0, 0, 4 ), debug_radius, ( 0.05, 0.05, 0.05 ), false, true, 9999999 );
512  Circle( omit_location + ( 0, 0, 8 ), debug_radius, ( 0.05, 0.05, 0.05 ), false, true, 9999999 );
513  }
514  }
515 #/
516 
517  // - - - - -
518  //
519  // -- collect the random points that can be used to drop raps (test points using box traces, etc.)
520  //
521  game["raps_helicopter_positions"] = [];
522  minFlyHeight = ‪RAPS_HELICOPTER_FLY_HEIGHT;
523  test_point_radius = 12;
524  fit_radius = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5;
525  fit_radius_corner = fit_radius * 0.7071;
526  omit_radius = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5;
527 
528  foreach( point in randomNavMeshPoints )
529  {
530  // skip points in water
531  start_water_trace = point + ( 0, 0, 6 );
532  stop_water_trace = point + ( 0, 0, 8 );
533  ‪trace = physicstrace( start_water_trace, stop_water_trace, ( -2, -2, -2 ), ( 2, 2, 2 ) , undefined, ‪PHYSICS_TRACE_MASK_WATER );
534  if( ‪trace["fraction"] < 1.0 )
535  {
536  /#
538  {
539  DebugBoxWidth = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5;
540  DebugBoxHeight = 10;
541 
542  // draw a blue box where water was found
543  Box( start_water_trace, ( -DebugBoxWidth, -DebugBoxWidth, 0 ), ( DebugBoxWidth, DebugBoxWidth, DebugBoxHeight ), 0, ( 0.0, 0, 1.0 ), 0.9, false, 9999999 );
544  Box( start_water_trace, ( -2, -2, -2 ), ( 2, 2, 2 ), 0, ( 0.0, 0, 1.0 ), 0.9, false, 9999999 );
545  }
546  #/
547  continue;
548  }
549 
550  // skip avoid points
551  should_omit = false;
552 
553  foreach( omit_location in ‪omit_locations )
554  {
555  if ( DistanceSquared( omit_location, point ) < ( omit_radius * omit_radius ) )
556  {
557  should_omit = true;
558 
559  /#
561  {
562  DebugBoxWidth = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5;
563  DebugBoxHeight = 10;
564 
565  // draw a dark grey box for omitted boxes
566  Box( point, ( -DebugBoxWidth, -DebugBoxWidth, 0 ), ( DebugBoxWidth, DebugBoxWidth, DebugBoxHeight ), 0, ( 0.05, 0.05, 0.05 ), 1.0, false, 9999999 );
567  }
568  #/
569 
570  break;
571  }
572  }
573 
574  if (should_omit)
575  continue;
576 
577  // for each random nav mesh point, test a few points near it to see if it works as a drop point
578  randomTestPoints = ‪util::PositionQuery_PointArray( point, 0, ‪RAPS_HELICOPTER_NAV_SPACIOUS_POINT_BOUNDARY, lots_of_height, test_point_radius );
579  max_attempts = 12;
580  point_added = false;
581  for ( i = 0; !point_added && i < max_attempts && i < randomTestPoints.size; i++ )
582  {
583  test_point = randomTestPoints[ i ];
584 
585  //can_fit_on_nav_mesh = IsPointOnNavMesh( test_point, RAPS_HELICOPTER_NAV_SPACIOUS_POINT_BOUNDARY ); // this line should "work", but it doesn't, so we test some points individually
586  can_fit_on_nav_mesh = ( IsPointOnNavMesh( test_point + ( 0, fit_radius, 0 ), 0 )
587  && IsPointOnNavMesh( test_point + ( 0, -fit_radius, 0 ), 0 )
588  && IsPointOnNavMesh( test_point + ( fit_radius, 0, 0 ), 0 )
589  && IsPointOnNavMesh( test_point + ( -fit_radius, 0, 0 ), 0 )
590  && IsPointOnNavMesh( test_point + ( fit_radius_corner, fit_radius_corner, 0 ), 0 ) // also include corners as there are cases where the above four are not sufficient for raps drones
591  && IsPointOnNavMesh( test_point + ( fit_radius_corner, -fit_radius_corner, 0 ), 0 )
592  && IsPointOnNavMesh( test_point + ( -fit_radius_corner, fit_radius_corner, 0 ), 0 )
593  && IsPointOnNavMesh( test_point + ( -fit_radius_corner, -fit_radius_corner, 0 ), 0 )
594  );
595 
596  if ( can_fit_on_nav_mesh )
597  {
598  point_added = ‪TryAddPointForHelicopterPosition( test_point, minFlyHeight );
599  }
600  }
601  }
602 
603  if( game["raps_helicopter_positions"].size == 0 )
604  {
605  /# IPrintLnBold( "Error Finding Valid RAPS Helicopter Positions, Using Default Random NavMesh Points" ); #/
606  game["raps_helicopter_positions"] = randomNavMeshPoints;
607  }
608 
609  // find helicopter position closest to mapCenter to use as flood fill start point
610  flood_fill_start_point = undefined;
611  flood_fill_start_point_distance_squared = 9999999;
612  foreach( point in game["raps_helicopter_positions"] )
613  {
614  if ( !isdefined( point ) )
615  continue;
616 
617  distance_squared = DistanceSquared( point, mapCenter );
618  if ( distance_squared < flood_fill_start_point_distance_squared )
619  {
620  flood_fill_start_point_distance_squared = distance_squared;
621  flood_fill_start_point = point;
622  }
623  }
624 
625  if ( !isdefined( flood_fill_start_point ) )
626  flood_fill_start_point = mapCenter;
627 
628  level thread ‪NoVehicleFaceThread( flood_fill_start_point, radius * 2 );
629 }
630 
631 function ‪TryAddPointForHelicopterPosition( spaciousPoint, minFlyHeight )
632 {
633  traceHeight = minFlyHeight + ‪RAPS_HELICOPTER_NAV_ADDITIONAL_TRACE_HEIGHT;
634  traceBoxHalfWidth = ‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH * 0.5;
635 
636  if ( ‪IsTraceSafeForRapsDroneDropFromHelicopter( spaciousPoint, traceHeight, traceBoxHalfWidth ) )
637  {
638  ‪ARRAY_ADD( game["raps_helicopter_positions"], spaciousPoint );
639  return true;
640  }
641 
642  return false;
643 }
644 
645 function ‪IsTraceSafeForRapsDroneDropFromHelicopter( spaciousPoint, traceHeight, traceBoxHalfWidth )
646 {
647  start = ( spaciousPoint[0], spaciouspoint[1], traceHeight );
648  ‪end = ( spaciousPoint[0], spaciouspoint[1], spaciouspoint[2] + ‪RAPS_HELICOPTER_NAV_END_POINT_TRACE_OFFSET );
649 
650  ‪trace = PhysicsTrace( start, ‪end, ( -traceBoxHalfWidth, -traceBoxHalfWidth, 0 ), ( traceBoxHalfWidth, traceBoxHalfWidth, traceBoxHalfWidth * 2.0 ), undefined, ‪PHYSICS_TRACE_MASK_PHYSICS );
651 
652 
653 /#
655  {
656  if (‪trace["fraction"] < 1.0 )
657  {
658  // shows the first trace hit, but from the end
659  Box( ‪end, (-traceBoxHalfWidth, -traceBoxHalfWidth, 0), (traceBoxHalfWidth, traceBoxHalfWidth, (start[2] - ‪end[2]) * (1.0 - ‪trace["fraction"])), 0, ( 1.0, 0, 0.0 ), 0.6, false, 9999999 );
660  }
661  else
662  {
663  // shows a small green box
664  Box( ‪end, (-traceBoxHalfWidth, -traceBoxHalfWidth, 0), (traceBoxHalfWidth, traceBoxHalfWidth, 8.88), 0, ( 0.0, 1.0, 0.0 ), 0.6, false, 9999999 );
665  }
666  }
667 #/
668 
669  return ( ‪trace["fraction"] == 1.0 && ‪trace["surfacetype"] == "none" );
670 }
671 
672 function ‪GetRandomHelicopterStartOrigin( fly_height, firstDropLocation )
673 {
674  best_node = ‪helicopter::getValidRandomStartNode( firstDropLocation );
675  return best_node.origin + ( 0, 0, fly_height );
676 }
677 
678 function ‪GetRandomHelicopterLeaveOrigin( fly_height, startLocationToLeaveFrom )
679 {
680  best_node = ‪helicopter::getValidRandomLeaveNode( startLocationToLeaveFrom );
681  return best_node.origin + ( 0, 0, fly_height );
682 }
683 
685 {
686  // Note A: call this only once for each helicopter when spawned
687  // Note B: this technique only works for two RAPS helicopters in play at any give time
688  // Note C: this works regardless of team based or not
689 
690  ArrayRemoveValue( level.raps_helicopters, undefined ); // clean up array first
691 
692  minimum_fly_height = ‪airsupport::getMinimumFlyHeight();
693 
694  if ( level.raps_helicopters.size > 0 )
695  {
696  already_assigned_height = level.raps_helicopters[0].assigned_fly_height;
697 
698  if ( already_assigned_height == ( minimum_fly_height + ‪RAPS_HELICOPTER_FLY_HEIGHT ) )
700  }
701 
702  return minimum_fly_height + ‪RAPS_HELICOPTER_FLY_HEIGHT;
703 }
704 
706 {
707  helicopter = self;
708  helicopter thread ‪WatchOwnerDisconnect( owner );
709  helicopter thread ‪CreateRapsHelicopterInfluencer();
710 }
711 
712 function ‪SpawnRapsHelicopter( killstreakId )
713 {
714  player = self;
715 
716  assigned_fly_height = ‪GetInitialHelicopterFlyHeight();
717  prePickedDropLocation = ‪PickNextDropLocation( undefined, 0, player.origin, assigned_fly_height );
718  spawnOrigin = ‪GetRandomHelicopterStartOrigin( /*fly_height*/ 0, prePickedDropLocation ); // update this
719 
720  helicopter = SpawnHelicopter( player, spawnOrigin, ( 0, 0, 0 ), ‪RAPS_HELICOPTER_INFO, ‪RAPS_HELICOPTER_MODEL );
721  helicopter.prePickedDropLocation = prePickedDropLocation;
722  helicopter.assigned_fly_height = assigned_fly_height;
723 
724  helicopter ‪killstreaks::configure_team( ‪RAPS_NAME, killstreakId, player, undefined, undefined, &‪ConfigureChopperTeamPost );
726 
727  helicopter.droppingRaps = false;
728  helicopter.isLeaving = false;
729  helicopter.droppedRaps = false;
730  helicopter.driveModeSpeedScale = 3.0;
731  helicopter.driveModeAccel = ‪RAPS_HELAV_EXPEDIENT_MODE_ACCEL * 5;
732  helicopter.driveModeDecel = ‪RAPS_HELAV_EXPEDIENT_MODE_DECEL * 5;
733  helicopter.lastStopTime = 0;
734  helicopter.targetDropLocation = ‪RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT;
735  helicopter.lastDropLocation = ‪RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT;
736  helicopter.firstDropReferencePoint = ( player.origin[0], player.origin[1], ‪RAPS_HELICOPTER_FLY_HEIGHT);
737  /# helicopter.__last_dynamic_avoidance_action = 0; #/
738 
739  helicopter ‪clientfield::set( "enemyvehicle", ‪ENEMY_VEHICLE_ACTIVE );
740 
741  helicopter.health = 99999999;
742  helicopter.maxhealth = ‪killstreak_bundles::get_max_health( ‪RAPS_NAME );
743  helicopter.lowhealth = ‪killstreak_bundles::get_low_health( ‪RAPS_NAME );
744  helicopter.extra_low_health = helicopter.lowhealth * 0.5; // hand craft for ship (no need to be tunable now per design, it's locked in)
745  helicopter.extra_low_health_callback = &‪OnExtraLowHealth;
746 
747  helicopter SetCanDamage( true );
748  helicopter thread ‪killstreaks::MonitorDamage( ‪RAPS_NAME, helicopter.maxhealth, &‪OnDeath, helicopter.lowhealth, &‪OnLowHealth, 0, undefined, true );
749 
750  helicopter.rocketDamage = helicopter.maxhealth / ‪RAPS_HELICOPTER_MISSILES_TO_DESTROY + 1;
751  helicopter.remoteMissileDamage = helicopter.maxhealth / ‪RAPS_HELICOPTER_REMOTE_MISSILES_TO_DESTROY + 1;
752  helicopter.hackerToolDamage = helicopter.maxhealth / ‪RAPS_HELICOPTER_HACKS_TO_DESTROY + 1;
753  helicopter.DetonateViaEMP = &‪raps::detonate_damage_monitored;
754 
755  Target_Set( helicopter, ( 0, 0, 100 ) );
756  helicopter SetDrawInfrared( true );
757  helicopter thread ‪WaitForHelicopterShutdown();
758  helicopter thread ‪HelicopterThink();
759  helicopter thread ‪WatchGameEnded();
760 /# helicopter thread ‪HelicopterThinkDebugVisitAll(); #/
761 
762  return helicopter;
763 }
764 
766 {
767  helicopter = self;
768  helicopter waittill( "raps_helicopter_shutdown", killed );
769 
770  level notify( "raps_updated_" + helicopter.ownerEntNum );
771 
772  if ( Target_IsTarget( helicopter ) )
773  {
774  Target_Remove( helicopter );
775  }
776 
777  if( killed )
778  {
779  wait( RandomFloatRange( 0.1, 0.2 ) );
780 
781  helicopter ‪FirstHeliExplo();
782  helicopter ‪HeliDeathTrails();
783 
784  helicopter thread ‪Spin();
785  GoalX = RandomFloatRange( 650, 700 );
786  GoalY = RandomFloatRange( 650, 700 );
787 
788  if ( RandomIntRange ( 0, 2 ) > 0 )
789  GoalX = -GoalX;
790 
791  if ( RandomIntRange ( 0, 2 ) > 0 )
792  GoalY = -GoalY;
793 
794  helicopter setVehGoalPos( helicopter.origin + ( GoalX, GoalY, -RandomFloatRange( 285, 300 ) ), false );
795  wait( RandomFloatRange( 3.0, 4.0 ) );
796 
797  helicopter ‪FinalHeliDeathExplode();
798 
799  // fx will not work if we delete too soon
800  wait ‪RAPS_HELI_POST_DEATH_FX_GHOST_DELAY; // ghost only after fx has covered up the drop ship
801  helicopter ghost();
802  self notify( "stop_death_spin" );
803  wait 0.5;
804  }
805  else
806  {
807  helicopter ‪HelicopterLeave();
808  }
809 
810  helicopter delete();
811 }
812 
813 function ‪WatchOwnerDisconnect( owner )
814 {
815  self notify( "WatchOwnerDisconnect_singleton" );
816  self endon ( "WatchOwnerDisconnect_singleton" );
817 
818  helicopter = self;
819  helicopter endon( "raps_helicopter_shutdown" );
820  owner ‪util::waittill_any( "joined_team", "disconnect", "joined_spectators" );
821  helicopter notify( "raps_helicopter_shutdown", false );
822 }
823 
824 function ‪WatchGameEnded( )
825 {
826  helicopter = self;
827  helicopter endon( "raps_helicopter_shutdown" );
828  helicopter endon( "death" );
829  level waittill("game_ended");
830  helicopter notify( "raps_helicopter_shutdown", false );
831 }
832 
833 function ‪OnDeath( attacker, weapon )
834 {
835  helicopter = self;
836 
837  if ( isdefined( attacker ) && ( !isdefined( helicopter.owner ) || helicopter.owner ‪util::IsEnemyPlayer( attacker ) ) )
838  {
839  ‪challenges::destroyedAircraft( attacker, weapon, false );
840  attacker ‪challenges::addFlySwatterStat( weapon, self );
841  scoreevents::processscoreevent( "destroyed_raps_deployship", attacker, helicopter.owner, weapon );
842  if ( isdefined( helicopter.droppedRaps ) && helicopter.droppedRaps == false )
843  {
844  attacker addplayerstat( "destroy_raps_before_drop", 1 );
845  }
846  LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_RAPS_DEPLOY_SHIP", attacker.entnum );
847  helicopter notify( "raps_helicopter_shutdown", true );
848  }
849 
850  if ( helicopter.isleaving !== true )
851  {
852  helicopter ‪killstreaks::play_pilot_dialog_on_owner( "destroyed", ‪RAPS_NAME );
853  helicopter ‪killstreaks::play_destroyed_dialog_on_owner( ‪RAPS_NAME, self.killstreakId );
854  }
855 }
856 
857 function ‪OnLowHealth( attacker, weapon )
858 {
859  helicopter = self;
860 
861  helicopter ‪killstreaks::play_pilot_dialog_on_owner( "damaged", ‪RAPS_NAME, helicopter.killstreakId );
862 
863  helicopter ‪HeliLowHealthFx();
864 }
865 
866 function ‪OnExtraLowHealth( attacker, weapon )
867 {
868  helicopter = self;
869  helicopter ‪HeliExtraLowHealthFx();
870 }
871 
873 {
874  flyHeight = ‪RAPS_HELICOPTER_FLY_HEIGHT;
875  found = false;
876  tries = 0;
877 
878  // try picking a location outside the avoid circle, if not possible, reduce the circle size and try again
879  for( i = 0; i <= ‪RAPS_HEDEPS_REDUCE_RADIUS_RETRIES; i++ ) // intentionally using "<=" to get N+1 attemmpts
880  {
881  // for the very last attempt, make radius negative to make any point valid as a fail safe
883  avoidRadiusSqr = -1.0;
884 
885 /# if ( ‪RAPS_HEDEPS_DEBUG > 0 )
886  {
887  server_frames_to_persist = INT( 3.0 / ‪SERVER_FRAME );
888  circle( avoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS, ( 1, 0, 0 ), true, true, server_frames_to_persist );
889  circle( avoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS - 1, ( 1, 0, 0 ), true, true, server_frames_to_persist );
890  circle( avoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS - 2, ( 1, 0, 0 ), true, true, server_frames_to_persist );
891 
892  circle( otherAvoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS, ( 1, 0, 0 ), true, true, server_frames_to_persist );
893  circle( otherAvoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS - 1, ( 1, 0, 0 ), true, true, server_frames_to_persist );
894  circle( otherAvoidPoint, ‪RAPS_HEDEPS_AVOID_RADIUS - 2, ( 1, 0, 0 ), true, true, server_frames_to_persist );
895  }
896 #/
897 
898  while( !found && tries < game["raps_helicopter_positions"].size )
899  {
900  index = RandomIntRange( 0, game["raps_helicopter_positions"].size );
901  randomPoint = ( game["raps_helicopter_positions"][ index ][0], game["raps_helicopter_positions"][ index ][1], flyHeight );
902  found = ( ( Distance2DSquared( randomPoint, avoidPoint ) > avoidRadiusSqr ) && ( Distance2DSquared( randomPoint, otherAvoidPoint ) > avoidRadiusSqr ) );
903  tries++;
904  }
905 
906  if (!found)
907  {
908  avoidRadiusSqr *= 0.25;
909  tries = 0;
910  }
911  }
912 
913  // note: the -1 avoid radius should force the selection of a point
914  Assert( found, "Failed to find a RAPS deploy point!" );
915 
916  return randomPoint;
917 }
918 
920 {
921  bestPosition = ‪GetRandomHelicopterPosition( avoidPoint, otherAvoidPoint );
922  bestDistanceSqr = Distance2DSquared( bestPosition, refPoint );
923 
924  for ( i = 1; i < pickCount; i++ )
925  {
926  candidatePosition = ‪GetRandomHelicopterPosition( avoidPoint, otherAvoidPoint );
927  candidateDistanceSqr = Distance2DSquared( candidatePosition, refPoint );
928 
929  if ( candidateDistanceSqr < bestDistanceSqr )
930  {
931  bestPosition = candidatePosition;
932  bestDistanceSqr = candidateDistanceSqr;
933  }
934  }
935 
936  return bestPosition;
937 }
938 
940 {
941  elapsedTimeStopping = GetTime() - self.lastStopTime;
942  if ( elapsedTimeStopping < ‪RAPS_HELAV_STOP_WAIT_BEFORE_NEXT_DROP_POINT_MS )
943  {
944  wait ( (‪RAPS_HELAV_STOP_WAIT_BEFORE_NEXT_DROP_POINT_MS - elapsedTimeStopping) * 0.001 );
945  }
946 }
947 
948 function ‪GetOtherHelicopterPointToAvoid() //self == raps helicopter
949 {
950  avoid_point = undefined;
951 
952  ArrayRemoveValue( level.raps_helicopters, undefined ); // clean up array first
953 
954  foreach( heli in level.raps_helicopters )
955  {
956  if ( heli != self )
957  {
958  avoid_point = heli.targetDropLocation;
959  break;
960  }
961  }
962 
963  return avoid_point;
964 }
965 
966 function ‪PickNextDropLocation( heli, drop_index, firstDropReferencePoint, assigned_fly_height, lastDropLocation )
967 {
968  avoid_point = self ‪GetOtherHelicopterPointToAvoid();
969 
970  // if we have a pre-picked drop location, use that first and reset it
971  if ( isdefined( heli ) && isdefined( heli.prePickedDropLocation ) )
972  {
973  targetDropLocation = heli.prePickedDropLocation;
974  heli.prePickedDropLocation = undefined;
975  return targetDropLocation;
976  }
977 
978  targetDropLocation = ( ( drop_index == 0 ) ? ‪GetClosestRandomHelicopterPosition(
979  firstDropReferencePoint,
980  INT(game["raps_helicopter_positions"].size * (‪RAPS_HEDEPS_FIRST_POINT_PERCENT_OF_TOTAL / 100.0) + 1),
981  avoid_point )
982  : ‪GetRandomHelicopterPosition( lastDropLocation, avoid_point ) );
983 
984  targetDropLocation = ( targetDropLocation[0], targetDropLocation[1], assigned_fly_height );
985 
986  return targetDropLocation;
987 }
988 
990 {
991 /#
993  return;
994 #/
995 
996  self endon( "raps_helicopter_shutdown" );
997 
998  for( i = 0; i < ‪RAPS_HELICOPTER_DROP_LOCATION_COUNT; i++ )
999  {
1000  self.targetDropLocation = ‪PickNextDropLocation( self, i, self.firstDropReferencePoint, self.assigned_fly_height, self.lastDropLocation );
1001 
1002  while ( Distance2DSquared( self.origin, self.targetDropLocation ) > ‪RAPS_HELICOPTER_DROP_LOCATION_TOLERANCE_SQR )
1003  {
1005  self ‪UpdateHelicopterSpeed();
1006  self setVehGoalPos( self.targetDropLocation, 1 );
1007  self waittill( "goal" );
1008  }
1009 
1010  if ( isdefined( self.owner ) )
1011  {
1012  if ( ( i + 1 ) < ‪RAPS_HELICOPTER_DROP_LOCATION_COUNT )
1013  {
1014  self ‪killstreaks::play_pilot_dialog_on_owner( "waveStart", ‪RAPS_NAME, self.killstreakId );
1015  }
1016  else
1017  {
1018  self ‪killstreaks::play_pilot_dialog_on_owner( "waveStartFinal", ‪RAPS_NAME, self.killstreakId );
1019  }
1020  }
1021 
1022  enemy = self.owner ‪battlechatter::get_closest_player_enemy( self.origin, true );
1023  enemyRadius = ‪battlechatter::mpdialog_value( "rapsDropRadius", 0 );
1024 
1025  if ( isdefined( enemy ) && Distance2DSquared( self.origin, enemy.origin ) < enemyRadius * enemyRadius )
1026  {
1028  }
1029 
1030  self ‪DropRaps();
1031 
1032  wait( ( i + 1 >= ‪RAPS_HELICOPTER_DROP_LOCATION_COUNT )
1035  }
1036 
1037  self notify( "raps_helicopter_shutdown", false );
1038 }
1039 
1040 /#
1042 {
1043  self endon( "death" );
1044 
1046  return;
1047 
1048  for( i = 0; i < 100; i++ )
1049  {
1050  for( j = 0; j < game["raps_helicopter_positions"].size; j++ )
1051  {
1052  self.targetDropLocation = ( game["raps_helicopter_positions"][ j ][0], game["raps_helicopter_positions"][ j ][1], self.assigned_fly_height );
1053 
1054  while ( Distance2DSquared( self.origin, self.targetDropLocation ) > ‪RAPS_HELICOPTER_DROP_LOCATION_TOLERANCE_SQR )
1055  {
1057  self ‪UpdateHelicopterSpeed();
1058  self setVehGoalPos( self.targetDropLocation, 1 );
1059  self waittill( "goal" );
1060  }
1061 
1062  self ‪DropRaps();
1063 
1064  wait( 1.0 );
1065 
1067  {
1068  if ( (j+1) % 3 == 0 )
1069  {
1070 
1071  // fake a leave and then return
1072  self.targetDropLocation = ‪GetRandomHelicopterStartOrigin( self.assigned_fly_height, self.origin ); //TODO: make this debug function work at some point, not now, too close to ship
1073  while ( Distance2DSquared( self.origin, self.targetDropLocation ) > ‪RAPS_HELICOPTER_DROP_LOCATION_TOLERANCE_SQR )
1074  {
1076  self ‪UpdateHelicopterSpeed();
1077  self setVehGoalPos( self.targetDropLocation, 1 );
1078  self waittill( "goal" );
1079  }
1080  }
1081  }
1082  }
1083  }
1084 
1085  self notify( "raps_helicopter_shutdown", false );
1086 }
1087 #/
1088 
1089 function ‪DropRaps()
1090 {
1091  level endon( "game_ended" );
1092  self endon( "death" );
1093 
1094  self.droppingRaps = true;
1095  self.lastDropLocation = self.origin;
1096 
1097  // reposition raps to a more precise drap location
1098  preciseDropLocation = 0.5 * ( self GetTagOrigin( level.raps_helicopter_drop_tag_names[0] ) + self GetTagOrigin( level.raps_helicopter_drop_tag_names[1] ) );
1099  preciseGoalLocation = self.targetDropLocation + (self.targetDropLocation - preciseDropLocation);
1100  preciseGoalLocation = ( preciseGoalLocation[0], preciseGoalLocation[1], self.targetDropLocation[2] );
1101  self setVehGoalPos( preciseGoalLocation, 1 );
1102  self waittill( "goal" );
1103  self.droppedRaps = true;
1104  for( i = 0; i < level.raps_settings.spawn_count; i++ )
1105  {
1106  spawn_tag = level.raps_helicopter_drop_tag_names[ i % level.raps_helicopter_drop_tag_names.size ];
1107 
1108  origin = self GetTagOrigin( spawn_tag );
1109  angles = self GetTagAngles( spawn_tag );
1110 
1111  if ( !isdefined( origin ) || !isdefined( angles ) )
1112  {
1113  origin = self.origin;
1114  angles = self.angles;
1115  }
1116 
1117  self.owner thread ‪SpawnRaps( origin, angles );
1118  self playsound( "veh_raps_launch" );
1120  }
1121 
1122  self.droppingRaps = false;
1123 }
1124 
1125 function ‪Spin()
1126 {
1127  self endon( "stop_death_spin" );
1128 
1129  speed = RandomIntRange( 180, 220 );
1130  self setyawspeed( speed, speed * 0.25, speed );
1131 
1132  if ( RandomIntRange ( 0, 2 ) > 0 )
1133  speed = -speed;
1134 
1135  while ( isdefined( self ) )
1136  {
1137  self settargetyaw( self.angles[1]+(speed*0.4) );
1138  wait ( 1 );
1139  }
1140 }
1141 
1143 {
1145  self PlaySound( level.heli_sound["crash"] );
1146 }
1147 
1149 {
1150  self ‪clientfield::set( "raps_heli_low_health", 1 );
1151 }
1152 
1154 {
1155  self ‪clientfield::set( "raps_heli_extra_low_health", 1 );
1156 }
1157 
1159 {
1161 }
1162 
1164 {
1165  PlayFxOnTag( ‪RAPS_HELI_DEATH_FX, self, ‪RAPS_HELI_DEATH_FX_TAG );
1166  self PlaySound( level.heli_sound["crash"] );
1167 }
1168 
1170 {
1171  self.isLeaving = true;
1172 
1175 
1176  self.leaveLocation = ‪GetRandomHelicopterLeaveOrigin( /* self.assigned_fly_height */ 0, self.origin );
1177  while ( Distance2DSquared( self.origin, self.leaveLocation ) > ‪RAPS_HELICOPTER_LEAVE_LOCATION_REACHED_SQR )
1178  {
1179  self ‪UpdateHelicopterSpeed();
1180  self setVehGoalPos( self.leaveLocation, 0 );
1181  self waittill( "goal" );
1182  }
1183 }
1184 
1185 function ‪UpdateHelicopterSpeed( driveMode )
1186 {
1187  if ( isdefined( driveMode ) )
1188  {
1189  switch ( driveMode )
1190  {
1192  self.driveModeSpeedScale = 1.0;
1193  self.driveModeAccel = ‪RAPS_HELAV_EXPEDIENT_MODE_ACCEL;
1194  self.driveModeDecel = ‪RAPS_HELAV_EXPEDIENT_MODE_DECEL;
1195  break;
1196 
1200  self.driveModeAccel = ‪RAPS_HELAV_CAUTIOUS_MODE_ACCEL;
1201  self.driveModeDecel = ‪RAPS_HELAV_CAUTIOUS_MODE_DECEL;
1202  break;
1203  }
1204  }
1205 
1206  desiredSpeed = (self GetMaxSpeed() / ‪MPH_TO_INCHES_PER_SEC) * self.driveModeSpeedScale;
1207 
1208  // use Decel as Accel when the desired speed is less than the current speed; (it's a side effect of the system)
1209  if ( desiredspeed < self GetSpeedMPH() )
1210  {
1211  self SetSpeed( desiredSpeed, self.driveModeDecel, self.driveModeDecel );
1212  }
1213  else
1214  {
1215  self SetSpeed( desiredSpeed, self.driveModeAccel, self.driveModeDecel );
1216  }
1217 }
1218 
1220 {
1221  //self SetSpeed( 0, RAPS_HELAV_FULL_STOP_MODE_ACCEL, RAPS_HELAV_FULL_STOP_MODE_DECEL );
1222  self SetSpeed( 0, ‪RAPS_HELAV_FULL_STOP_MODE_DECEL, ‪RAPS_HELAV_FULL_STOP_MODE_DECEL ); // using DECEL as accel due to way the current system works
1223  self.lastStopTime = GetTime();
1224 }
1225 
1227 // RAPS
1229 function ‪SpawnRaps( origin, angles )
1230 {
1231  originalOwner = self;
1232  originalOwnerEntNum = originalOwner.entNum;
1233 
1234  raps = SpawnVehicle( ‪RAPS_VEHICLE, origin, angles, "dynamic_spawn_ai" );
1235 
1236  if ( !isdefined( raps ) )
1237  return;
1238 
1239  raps.forceOneMissile = true;
1240  raps.drop_deploying = true;
1241  raps.hurt_trigger_immune_end_time = GetTime() + ‪VAL( level.raps_hurt_trigger_immune_duration_ms, ‪RAPS_HURT_TRIGGER_IMMUNE_DURATION_MS );
1242 
1243  ‪ARRAY_ADD( level.raps[ originalOwnerEntNum ].raps, raps );
1244 
1245  raps ‪killstreaks::configure_team( ‪RAPS_NAME, ‪RAPS_NAME, originalOwner, undefined, undefined, &‪ConfigureTeamPost );
1247  raps ‪clientfield::set( "enemyvehicle", ‪ENEMY_VEHICLE_ACTIVE );
1248  raps.soundmod = "raps";
1249  raps.ignore_vehicle_underneath_splash_scalar = true;
1250  raps.detonate_sides_disabled = true;
1251  raps.treat_owner_damage_as_friendly_fire = true;
1252  raps.ignore_team_kills = true;
1253 
1254  raps SetInvisibleToAll();
1255  raps thread ‪AutoSetVisibleToAll();
1256 
1257  raps ‪vehicle::toggle_sounds( 0 );
1258  //raps thread sndAndRumbleWaitUntilLanding( originalOwner ); // now in client script as monitor_drop_landing
1259 
1260  raps thread ‪WatchRapsKills( originalOwner );
1261  raps thread ‪WatchRapsDeath( originalOwner );
1262  raps thread ‪killstreaks::WaitForTimeout( ‪RAPS_NAME, raps.settings.max_duration * 1000, &‪OnRapsTimeout, "death" );
1263 }
1264 
1265 
1267 {
1268  raps = self;
1269  raps thread ‪CreateRapsInfluencer();
1270  raps thread ‪InitEnemySelection( owner );
1271  raps thread ‪WatchRapsTippedOver( owner );
1272 }
1273 
1274 
1275 
1277 {
1278  self endon( "death" );
1279 
1280  // intent: hide the visual glitches when first spawning raps mid air
1281 
1284 
1285  self SetVisibleToAll();
1286 }
1287 
1289 {
1290  self ‪SelfDestruct( self.owner );
1291 }
1292 
1293 function ‪SelfDestruct( attacker ) // self == raps
1294 {
1295  self.selfDestruct = true;
1296  self ‪raps::detonate( attacker );
1297 }
1298 
1299 function ‪WatchRapsKills( originalOwner )
1300 {
1301  originalOwner endon( "raps_complete" );
1302  self endon( "death" );
1303 
1304  if( self.settings.max_kill_count == 0 )
1305  {
1306  return;
1307  }
1308 
1309  while( true )
1310  {
1311  self waittill( "killed", victim );
1312 
1313  if( isdefined( victim ) && IsPlayer( victim ) )
1314  {
1315  if( !isdefined( self.killCount ) )
1316  {
1317  self.killCount = 0;
1318  }
1319 
1320  self.killCount++;
1321  if( self.killCount >= self.settings.max_kill_count )
1322  {
1323  self ‪raps::detonate( self.owner );
1324  }
1325  }
1326  }
1327 }
1328 
1329 function ‪WatchRapsTippedOver( owner )
1330 {
1331  owner endon( "disconnect" );
1332  self endon( "death" );
1333 
1334  // if the raps manage to tip over and get stuck, it should detonate
1335  while( true )
1336  {
1337  wait 3.5;
1338 
1339  if ( Abs( self.angles[2] ) > 75 )
1340  {
1341  self ‪raps::detonate( owner );
1342  }
1343  }
1344 }
1345 
1346 function ‪WatchRapsDeath( originalOwner )
1347 {
1348  originalOwnerEntNum = originalOwner.entnum;
1349  self waittill( "death", attacker, damageFromUnderneath, weapon );
1350 
1351  attacker = self [[ level.figure_out_attacker ]]( attacker );
1352 
1353  if( isdefined( attacker ) && isPlayer( attacker ) )
1354  {
1355  if( isdefined( self.owner ) && self.owner != attacker && ( self.owner.team != attacker.team ) )
1356  {
1357  ‪scoreevents::processScoreEvent( "killed_raps", attacker );
1358  attacker ‪challenges::destroyScoreStreak( weapon, true );
1360 
1361  if( isdefined( self.attackers ) )
1362  {
1363  foreach( player in self.attackers )
1364  {
1365  if( isPlayer( player ) && ( player != attacker ) && ( player != self.owner ) )
1366  {
1367  ‪scoreevents::processScoreEvent( "killed_raps_assist", player );
1368  }
1369  }
1370  }
1371  }
1372  }
1373 
1374  ArrayRemoveValue( level.raps[ originalOwnerEntNum ].raps, self );
1375 }
1376 
1377 function ‪InitEnemySelection( owner ) //self == raps
1378 {
1379  owner endon( "disconnect" );
1380  self endon( "death" );
1381  self endon( "hacked" );
1382 
1383  self ‪vehicle_ai::set_state( "off" );
1384  ‪util::wait_network_frame(); // wait needed to get drop deploy mode to work
1385  ‪util::wait_network_frame(); // need two to make sure fast forward works
1386  self SetVehicleForDropDeploy();
1387  self ‪clientfield::set( "monitor_raps_drop_landing", 1 );
1388  wait( ‪RAPS_SLEEP_DURATION );
1389  if ( self ‪InitialWaitUntilSettled() )
1390  {
1391  self ResetVehicleFromDropDeploy();
1392  self SetGoal( self.origin );
1393  self ‪vehicle_ai::set_state( "combat" );
1394  self ‪vehicle::toggle_sounds( 1 );
1395 
1396  self.drop_deploying = undefined;
1397  self.hurt_trigger_immune_end_time = undefined;
1398  Target_Set( self );
1399 
1400  // try not to target the same enemy
1401  for( i = 0; i < level.raps[ owner.entNum ].raps.size; i++ )
1402  {
1403  raps = level.raps[ owner.entNum ].raps[ i ];
1404  if( isdefined( raps ) && isdefined( raps.enemy ) && isdefined( self ) && isdefined( self.enemy ) && ( raps != self ) && ( raps.enemy == self.enemy ) )
1405  {
1406  self SetPersonalThreatBias( self.enemy, -2000, 5.0 );
1407  }
1408  }
1409  }
1410  else
1411  {
1412  // could not settle, then self destruct
1413  self ‪SelfDestruct( self.owner );
1414  }
1415 }
1416 
1417 #define RAPS_IWUS_WAIT_INTERVAL ( 0.2 )
1418 #define RAPS_IWUS_Z_SPEED_THRESHOLD ( 0.1 )
1419 #define RAPS_IWUS_Z_SETTLE_TIMEOUT ( 5.0 )
1420 #define RAPS_IWUS_SETTLE_ON_MESH_TIMEOUT ( RAPS_IWUS_Z_SETTLE_TIMEOUT + 5.0 )
1421 #define RAPS_IWUS_FORCE_TIMEOUT_TEST ( false )
1422 #define RAPS_IWUS_RAPS_RADIUS ( 36 )
1423 
1425 {
1426  // settle z speed first
1427  waitTime = 0;
1428  while ( Abs( self.velocity[2] ) > ‪RAPS_IWUS_Z_SPEED_THRESHOLD && waitTime < ‪RAPS_IWUS_Z_SETTLE_TIMEOUT )
1429  {
1431  waitTime += ‪RAPS_IWUS_WAIT_INTERVAL;
1432  }
1433 
1434  // wait until settled on nav mesh
1435  while( ( !IsPointOnNavMesh( self.origin, ‪RAPS_IWUS_RAPS_RADIUS ) || ( Abs( self.velocity[2] ) > ‪RAPS_IWUS_Z_SPEED_THRESHOLD ) ) && waitTime < ‪RAPS_IWUS_SETTLE_ON_MESH_TIMEOUT )
1436  {
1438  waitTime += ‪RAPS_IWUS_WAIT_INTERVAL;
1439  }
1440 
1441 /#
1444 #/
1445 
1446  // return true if raps settled without timing out
1447  return ( waitTime < ‪RAPS_IWUS_SETTLE_ON_MESH_TIMEOUT );
1448 }
1449 
1450 
1451 function ‪DestroyAllRaps( entNum, abandoned = false )
1452 {
1453  foreach( raps in level.raps[ entNum ].raps )
1454  {
1455  if( IsAlive( raps ) )
1456  {
1457  raps.owner = undefined;
1458  raps.abandoned = abandoned; // note: abandoned vehicles do not cause damage radius damage
1459  raps ‪raps::detonate( raps );
1460  }
1461  }
1462 }
1463 
1464 //Override for scripts/shared/vehicles/_raps.gsc:force_get_enemies()
1466 {
1467  foreach( player in level.players )
1468  {
1469  if( isdefined( self.owner ) && self.owner ‪util::IsEnemyPlayer( player ) && ( !player ‪smokegrenade::IsInSmokeGrenade() ) && !player hasPerk( "specialty_nottargetedbyraps" ) )
1470  {
1471  self GetPerfectInfo( player );
1472  return;
1473  }
1474  }
1475 }
1476 
1478 {
1479  level endon( "game_ended" );
1480 
1481  helicopter = self;
1482 
1483  if ( isdefined( helicopter.influencerEnt ) )
1484  {
1485  helicopter.influencerEnt Delete();
1486  }
1487 
1488  influencerEnt = ‪spawn( "script_model", helicopter.origin - ( 0, 0, self.assigned_fly_height ) );
1489  helicopter.influencerEnt = influencerEnt;
1490  helicopter.influencerEnt.angles = ( 0, 0, 0 );
1491  helicopter.influencerEnt LinkTo( helicopter );
1492 
1493  preset = GetInfluencerPreset( "helicopter" );
1494  if( !IsDefined( preset ) )
1495  {
1496  return;
1497  }
1498 
1499  enemy_team_mask = helicopter ‪spawning::get_enemy_team_mask( helicopter.team );
1500  helicopter.influencerEnt ‪spawning::create_entity_influencer( "helicopter", enemy_team_mask );
1501 
1502  helicopter waittill( "death" );
1503  if ( isdefined( influencerEnt ) )
1504  {
1505  influencerEnt delete();
1506  }
1507 }
1508 
1510 {
1511  raps = self;
1512 
1513  preset = GetInfluencerPreset( ‪RAPS_NAME );
1514  if( !IsDefined( preset ) )
1515  {
1516  return;
1517  }
1518 
1519  enemy_team_mask = raps ‪spawning::get_enemy_team_mask( raps.team );
1520  raps ‪spawning::create_entity_influencer( ‪RAPS_NAME, enemy_team_mask );
1521 }
‪ConfigureTeamPost
‪function ConfigureTeamPost(owner, isHacked)
Definition: _raps.gsc:1266
‪HeliLowHealthFx
‪function HeliLowHealthFx()
Definition: _raps.gsc:1148
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪DestroyAllRaps
‪function DestroyAllRaps(entNum, abandoned=false)
Definition: _raps.gsc:1451
‪getValidRandomLeaveNode
‪function getValidRandomLeaveNode(start)
Definition: _helicopter.gsc:426
‪WatchRapsTippedOver
‪function WatchRapsTippedOver(owner)
Definition: _raps.gsc:1329
‪RAPS_HELAV_SLOW_DOWN_SPEED_SCALE_FACTOR
‪#define RAPS_HELAV_SLOW_DOWN_SPEED_SCALE_FACTOR
Definition: _killstreaks.gsh:167
‪OnExtraLowHealth
‪function OnExtraLowHealth(attacker, weapon)
Definition: _raps.gsc:866
‪RAPS_HELI_FIRST_EXPLO_FX
‪#define RAPS_HELI_FIRST_EXPLO_FX
Definition: _killstreaks.gsh:186
‪RAPS_IWUS_FORCE_TIMEOUT_TEST
‪#define RAPS_IWUS_FORCE_TIMEOUT_TEST
Definition: _raps.gsc:1421
‪set_state
‪function set_state(name, state_params)
Definition: statemachine_shared.gsc:133
‪RAPS_HELICOPTER_INFO
‪#define RAPS_HELICOPTER_INFO
Definition: _killstreaks.gsh:112
‪RAPS_HELAV_NEED_NEW_GOAL_DISTANCE
‪#define RAPS_HELAV_NEED_NEW_GOAL_DISTANCE
Definition: _killstreaks.gsh:165
‪RAPS_HELI_DEATH_FX_TAG
‪#define RAPS_HELI_DEATH_FX_TAG
Definition: _killstreaks.gsh:193
‪getValidRandomStartNode
‪function getValidRandomStartNode(dest)
Definition: _helicopter.gsc:455
‪mpdialog_value
‪function mpdialog_value(mpdialogKey, defaultValue)
Definition: _battlechatter.gsc:253
‪RAPS_HELICOPTER_DROP_INTERVAL
‪#define RAPS_HELICOPTER_DROP_INTERVAL
Definition: _killstreaks.gsh:141
‪RAPS_HELAV_OTHER_FORWARD_OFFSET
‪#define RAPS_HELAV_OTHER_FORWARD_OFFSET
Definition: _killstreaks.gsh:162
‪WaitForTimeout
‪function WaitForTimeout(killstreak, duration, callback, endCondition1, endCondition2, endCondition3)
Definition: _killstreaks.gsc:2913
‪RAPS_HELICOPTER_MISSILES_TO_DESTROY
‪#define RAPS_HELICOPTER_MISSILES_TO_DESTROY
Definition: _killstreaks.gsh:114
‪allow_assists
‪function allow_assists(killstreakType, allow)
Definition: _killstreaks.gsc:399
‪OnEMP
‪function OnEMP(attacker, ownerEntNum)
Definition: _raps.gsc:408
‪RAPS_HELAV_FULL_STOP_DISTANCE
‪#define RAPS_HELAV_FULL_STOP_DISTANCE
Definition: _killstreaks.gsh:164
‪detonate_damage_monitored
‪function detonate_damage_monitored(enemy, weapon)
Definition: _raps.gsc:523
‪RAPS_HELAV_CAUTIOUS_MODE_ACCEL
‪#define RAPS_HELAV_CAUTIOUS_MODE_ACCEL
Definition: _killstreaks.gsh:180
‪RAPS_HELAV_ALWAYS_PICK_NEW_GOAL_POST_BACK_OFF
‪#define RAPS_HELAV_ALWAYS_PICK_NEW_GOAL_POST_BACK_OFF
Definition: _killstreaks.gsh:175
‪RAPS_HELAV_DRIVE_MODE_MORE_CAUTIOUS
‪#define RAPS_HELAV_DRIVE_MODE_MORE_CAUTIOUS
Definition: _killstreaks.gsh:174
‪GetInitialHelicopterFlyHeight
‪function GetInitialHelicopterFlyHeight()
Definition: _raps.gsc:684
‪register_killstreak_bundle
‪function register_killstreak_bundle(killstreakType)
Definition: _killstreak_bundles.gsc:20
‪RAPS_HELICOPTER_DROP_DURATION_LAST_DELTA
‪#define RAPS_HELICOPTER_DROP_DURATION_LAST_DELTA
Definition: _killstreaks.gsh:140
‪PickNextDropLocation
‪function PickNextDropLocation(heli, drop_index, firstDropReferencePoint, assigned_fly_height, lastDropLocation)
Definition: _raps.gsc:966
‪FirstHeliExplo
‪function FirstHeliExplo()
Definition: _raps.gsc:1142
‪HelicopterThink
‪function HelicopterThink()
Definition: _raps.gsc:989
‪OnPlayerConnect
‪function OnPlayerConnect()
Definition: _raps.gsc:81
‪getMinimumFlyHeight
‪function getMinimumFlyHeight()
Definition: _airsupport.gsc:167
‪RAPS_HELAV_FORWARD_OFFSET
‪#define RAPS_HELAV_FORWARD_OFFSET
Definition: _killstreaks.gsh:161
‪GetRandomHelicopterLeaveOrigin
‪function GetRandomHelicopterLeaveOrigin(fly_height, startLocationToLeaveFrom)
Definition: _raps.gsc:678
‪RAPS_HEDEPS_AVOID_RADIUS_SQR
‪#define RAPS_HEDEPS_AVOID_RADIUS_SQR
Definition: _killstreaks.gsh:153
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪RAPS_HELICOPTER_NAV_ADDITIONAL_TRACE_HEIGHT
‪#define RAPS_HELICOPTER_NAV_ADDITIONAL_TRACE_HEIGHT
Definition: _killstreaks.gsh:127
‪play_killstreak_start_dialog
‪function play_killstreak_start_dialog(killstreakType, team, killstreakId)
Definition: _killstreaks.gsc:1905
‪RAPS_HELI_DEATH_TRAIL_FX
‪#define RAPS_HELI_DEATH_TRAIL_FX
Definition: _killstreaks.gsh:188
‪destroyScoreStreak
‪function destroyScoreStreak(weapon, playerControlled, groundBased, countAsKillstreakVehicle=true)
Definition: challenges_shared.gsc:784
‪PHYSICS_TRACE_MASK_WATER
‪#define PHYSICS_TRACE_MASK_WATER
Definition: shared.gsh:132
‪NoVehicleFaceThread
‪function NoVehicleFaceThread(mapCenter, radius)
Definition: _raps.gsc:413
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪RAPS_HELICOPTER_DROP_DURATION
‪#define RAPS_HELICOPTER_DROP_DURATION
Definition: _killstreaks.gsh:137
‪RAPS_HEDEPS_AVOID_RADIUS
‪#define RAPS_HEDEPS_AVOID_RADIUS
Definition: _killstreaks.gsh:152
‪RAPS_HELI_POST_DEATH_FX_GHOST_DELAY
‪#define RAPS_HELI_POST_DEATH_FX_GHOST_DELAY
Definition: _raps.gsc:36
‪RAPS_HURT_TRIGGER_IMMUNE_DURATION_MS
‪#define RAPS_HURT_TRIGGER_IMMUNE_DURATION_MS
Definition: _raps.gsc:35
‪play_pilot_dialog_on_owner
‪function play_pilot_dialog_on_owner(dialogKey, killstreakType, killstreakId)
Definition: _killstreaks.gsc:2010
‪RAPS_HELAV_FULL_STOP_DISTANCE_SQR
‪#define RAPS_HELAV_FULL_STOP_DISTANCE_SQR
Definition: _killstreaks.gsh:171
‪RAPS_HELICOPTER_REMOTE_MISSILES_TO_DESTROY
‪#define RAPS_HELICOPTER_REMOTE_MISSILES_TO_DESTROY
Definition: _killstreaks.gsh:116
‪RAPS_HELICOPTER_Z_OFFSET_PER_HELI
‪#define RAPS_HELICOPTER_Z_OFFSET_PER_HELI
Definition: _killstreaks.gsh:134
‪GetOtherHelicopterPointToAvoid
‪function GetOtherHelicopterPointToAvoid()
Definition: _raps.gsc:948
‪PositionQuery_PointArray
‪function PositionQuery_PointArray(origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing, reachableBy_Ent)
Definition: util_shared.gsc:3462
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪addFlySwatterStat
‪function addFlySwatterStat(weapon, aircraft)
Definition: challenges_shared.gsc:86
‪get_closest_player_enemy
‪function get_closest_player_enemy(origin, teamOnly)
Definition: _battlechatter.gsc:1517
‪ENEMY_VEHICLE_ACTIVE
‪#define ENEMY_VEHICLE_ACTIVE
Definition: _hacker_tool.gsh:2
‪DropRaps
‪function DropRaps()
Definition: _raps.gsc:1089
‪RAPS_HELAV_EXPEDIENT_MODE_DECEL
‪#define RAPS_HELAV_EXPEDIENT_MODE_DECEL
Definition: _killstreaks.gsh:179
‪OnLowHealth
‪function OnLowHealth(attacker, weapon)
Definition: _raps.gsc:857
‪AutoReactivateRapsKillstreak
‪function AutoReactivateRapsKillstreak(ownerEntNum, player, hardpointType)
Definition: _raps.gsc:362
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪RAPS_HELICOPTER_FLY_HEIGHT
‪#define RAPS_HELICOPTER_FLY_HEIGHT
Definition: _killstreaks.gsh:135
‪WatchRapsKills
‪function WatchRapsKills(originalOwner)
Definition: _raps.gsc:1299
‪MPH_TO_INCHES_PER_SEC
‪#define MPH_TO_INCHES_PER_SEC
Definition: shared.gsh:268
‪GetMaxMapWidth
‪function GetMaxMapWidth()
Definition: _airsupport.gsc:802
‪play_killstreak_threat
‪function play_killstreak_threat(killstreakType)
Definition: _battlechatter.gsc:892
‪CreateRapsInfluencer
‪function CreateRapsInfluencer()
Definition: _raps.gsc:1509
‪RAPS_HELAV_SLOW_DOWN_DISTANCE
‪#define RAPS_HELAV_SLOW_DOWN_DISTANCE
Definition: _killstreaks.gsh:166
‪SelfDestruct
‪function SelfDestruct(attacker)
Definition: _raps.gsc:1293
‪WatchRapsDeath
‪function WatchRapsDeath(originalOwner)
Definition: _raps.gsc:1346
‪get_low_health
‪function get_low_health(killstreakType)
Definition: _killstreak_bundles.gsc:195
‪RAPS_IWUS_Z_SPEED_THRESHOLD
‪#define RAPS_IWUS_Z_SPEED_THRESHOLD
Definition: _raps.gsc:1418
‪RAPS_HEDEPS_FIRST_POINT_PERCENT_OF_TOTAL
‪#define RAPS_HEDEPS_FIRST_POINT_PERCENT_OF_TOTAL
Definition: _killstreaks.gsh:151
‪MonitorDamage
‪function MonitorDamage(killstreak_ref, max_health, destroyed_callback, low_health, low_health_callback, emp_damage, emp_callback, allow_bullet_damage)
Definition: _killstreaks.gsc:2499
‪GetMapCenter
‪function GetMapCenter()
Definition: _airsupport.gsc:766
‪RAPS_VEHICLE
‪#define RAPS_VEHICLE
Definition: _killstreaks.gsh:111
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪WatchOwnerDisconnect
‪function WatchOwnerDisconnect(owner)
Definition: _raps.gsc:813
‪RAPS_HELAV_MIN_TIME_BETWEEN_FULL_STOPS_MS
‪#define RAPS_HELAV_MIN_TIME_BETWEEN_FULL_STOPS_MS
Definition: _killstreaks.gsh:160
‪CreateRapsHelicopterInfluencer
‪function CreateRapsHelicopterInfluencer()
Definition: _raps.gsc:1477
‪RAPS_HELAV_BACK_OFF_FACTOR_MIN
‪#define RAPS_HELAV_BACK_OFF_FACTOR_MIN
Definition: _killstreaks.gsh:176
‪RAPS_HELICOPTER_NAV_DEBUG_VISIT_ALL
‪#define RAPS_HELICOPTER_NAV_DEBUG_VISIT_ALL
Definition: _killstreaks.gsh:130
‪RAPS_HELAV_SLOW_DOWN_DISTANCE_SQR
‪#define RAPS_HELAV_SLOW_DOWN_DISTANCE_SQR
Definition: _killstreaks.gsh:169
‪RAPS_HELAV_IN_FRONT_DOT
‪#define RAPS_HELAV_IN_FRONT_DOT
Definition: _killstreaks.gsh:163
‪HeliExtraLowHealthFx
‪function HeliExtraLowHealthFx()
Definition: _raps.gsc:1153
‪RAPS_IWUS_RAPS_RADIUS
‪#define RAPS_IWUS_RAPS_RADIUS
Definition: _raps.gsc:1422
‪destroyedAircraft
‪function destroyedAircraft(attacker, weapon, playerControlled)
Definition: challenges_shared.gsc:1405
‪UpdateKillstreakOnHelicopterDeath
‪function UpdateKillstreakOnHelicopterDeath(helicopter, ownerEntEnum)
Definition: _raps.gsc:395
‪RAPS_HELICOPTER_NAV_POINT_SPACING
‪#define RAPS_HELICOPTER_NAV_POINT_SPACING
Definition: _killstreaks.gsh:123
‪IsTraceSafeForRapsDroneDropFromHelicopter
‪function IsTraceSafeForRapsDroneDropFromHelicopter(spaciousPoint, traceHeight, traceBoxHalfWidth)
Definition: _raps.gsc:645
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪WaitForHelicopterShutdown
‪function WaitForHelicopterShutdown()
Definition: _raps.gsc:765
‪TryAddPointForHelicopterPosition
‪function TryAddPointForHelicopterPosition(spaciousPoint, minFlyHeight)
Definition: _raps.gsc:631
‪play_destroyed_dialog_on_owner
‪function play_destroyed_dialog_on_owner(killstreakType, killstreakId)
Definition: _killstreaks.gsc:1982
‪isKillstreakAllowed
‪function isKillstreakAllowed(hardpointType, team)
Definition: _killstreakrules.gsc:352
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪RAPS_HELAV_SLOW_DOWN_MORE_SCALE_FACTOR
‪#define RAPS_HELAV_SLOW_DOWN_MORE_SCALE_FACTOR
Definition: _killstreaks.gsh:168
‪RAPS_HELICOPTER_HACKS_TO_DESTROY
‪#define RAPS_HELICOPTER_HACKS_TO_DESTROY
Definition: _killstreaks.gsh:118
‪StopHelicopter
‪function StopHelicopter()
Definition: _raps.gsc:1219
‪RAPS_HELAV_MIN_PICK_NEW_GOAL_TIME_MS
‪#define RAPS_HELAV_MIN_PICK_NEW_GOAL_TIME_MS
Definition: _killstreaks.gsh:158
‪init
‪function init()
Definition: _raps.gsc:49
‪RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH
‪#define RAPS_HELICOPTER_NAV_TRACE_BOX_WIDTH
Definition: _killstreaks.gsh:126
‪OnTeamChanged
‪function OnTeamChanged(entNum, event)
Definition: _raps.gsc:402
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪ConfigureChopperTeamPost
‪function ConfigureChopperTeamPost(owner, isHacked)
Definition: _raps.gsc:705
‪ARRAY_ADD
‪#define ARRAY_ADD(__array, __item)
Definition: shared.gsh:304
‪Spin
‪function Spin()
Definition: _raps.gsc:1125
‪SERVER_FRAME
‪#define SERVER_FRAME
Definition: shared.gsh:264
‪RAPS_HELI_DEATH_FX
‪#define RAPS_HELI_DEATH_FX
Definition: _killstreaks.gsh:192
‪SpawnRapsHelicopter
‪function SpawnRapsHelicopter(killstreakId)
Definition: _raps.gsc:712
‪get_max_health
‪function get_max_health(killstreakType)
Definition: _killstreak_bundles.gsc:188
‪RAPS_SLEEP_DURATION
‪#define RAPS_SLEEP_DURATION
Definition: _killstreaks.gsh:145
‪ForceGetEnemies
‪function ForceGetEnemies()
Definition: _raps.gsc:1465
‪WaitForStoppingMoveToExpire
‪function WaitForStoppingMoveToExpire()
Definition: _raps.gsc:939
‪RAPS_HELAV_BACK_OFF_FACTOR_MAX
‪#define RAPS_HELAV_BACK_OFF_FACTOR_MAX
Definition: _killstreaks.gsh:177
‪register_dialog
‪function register_dialog(killstreakType, informDialog, taacomDialogBundleKey, pilotDialogArrayKey, startDialogKey, enemyStartDialogKey, enemyStartMultipleDialogKey, hackedDialogKey, hackedStartDialogKey, requestDialogKey, threatDialogKey, isInventory)
Definition: _killstreaks.gsc:239
‪INVALID_KILLSTREAK_ID
‪#define INVALID_KILLSTREAK_ID
Definition: _killstreaks.gsh:2
‪RAPS_HELICOPTER_NAV_END_POINT_TRACE_OFFSET
‪#define RAPS_HELICOPTER_NAV_END_POINT_TRACE_OFFSET
Definition: _killstreaks.gsh:128
‪RAPS_HELICOPTER_NAV_DEBUG_VISIT_ALL_FAKE_LEAVE
‪#define RAPS_HELICOPTER_NAV_DEBUG_VISIT_ALL_FAKE_LEAVE
Definition: _killstreaks.gsh:131
‪RAPS_HELAV_DRIVE_MODE_EXPEDIENT
‪#define RAPS_HELAV_DRIVE_MODE_EXPEDIENT
Definition: _killstreaks.gsh:172
‪PHYSICS_TRACE_MASK_PHYSICS
‪#define PHYSICS_TRACE_MASK_PHYSICS
Definition: shared.gsh:130
‪RAPS_HELAV_DRIVE_MODE_CAUTIOUS
‪#define RAPS_HELAV_DRIVE_MODE_CAUTIOUS
Definition: _killstreaks.gsh:173
‪ActivateRapsKillstreak
‪function ActivateRapsKillstreak(hardpointType)
Definition: _raps.gsc:312
‪RAPS_IWUS_WAIT_INTERVAL
‪#define RAPS_IWUS_WAIT_INTERVAL
Definition: _raps.gsc:1417
‪RapsHelicopterDynamicAvoidance
‪function RapsHelicopterDynamicAvoidance()
Definition: _raps.gsc:114
‪RAPS_HELI_DEATH_TRAIL_FX_TAG_A
‪#define RAPS_HELI_DEATH_TRAIL_FX_TAG_A
Definition: _killstreaks.gsh:189
‪RAPS_HELAV_CAUTIOUS_MODE_DECEL
‪#define RAPS_HELAV_CAUTIOUS_MODE_DECEL
Definition: _killstreaks.gsh:181
‪InitHelicopterPositions
‪function InitHelicopterPositions()
Definition: _raps.gsc:423
‪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
‪RAPS_HELAV_NEED_NEW_GOAL_DISTANCE_SQR
‪#define RAPS_HELAV_NEED_NEW_GOAL_DISTANCE_SQR
Definition: _killstreaks.gsh:170
‪RAPS_HELICOPTER_MODEL
‪#define RAPS_HELICOPTER_MODEL
Definition: _killstreaks.gsh:113
‪UpdateHelicopterSpeed
‪function UpdateHelicopterSpeed(driveMode)
Definition: _raps.gsc:1185
‪FinalHeliDeathExplode
‪function FinalHeliDeathExplode()
Definition: _raps.gsc:1163
‪killstreakStart
‪function killstreakStart(hardpointType, team, hacked, displayTeamMessage)
Definition: _killstreakrules.gsc:184
‪RAPS_IWUS_Z_SETTLE_TIMEOUT
‪#define RAPS_IWUS_Z_SETTLE_TIMEOUT
Definition: _raps.gsc:1419
‪RAPS_HELICOPTER_DEBUG_AUTO_REACTIVATE
‪#define RAPS_HELICOPTER_DEBUG_AUTO_REACTIVATE
Definition: _killstreaks.gsh:132
‪OnRapsTimeout
‪function OnRapsTimeout()
Definition: _raps.gsc:1288
‪AutoSetVisibleToAll
‪function AutoSetVisibleToAll()
Definition: _raps.gsc:1276
‪RapsHelicopterDynamicAvoidanceUpdate
‪function RapsHelicopterDynamicAvoidanceUpdate(index_to_update)
Definition: _raps.gsc:132
‪SpawnRaps
‪function SpawnRaps(origin, angles)
Definition: _raps.gsc:1229
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪InitEnemySelection
‪function InitEnemySelection(owner)
Definition: _raps.gsc:1377
‪omit_locations
‪function add_raps_omit_locations omit_locations
Definition: mp_combine.gsc:72
‪InitialWaitUntilSettled
‪function InitialWaitUntilSettled()
Definition: _raps.gsc:1424
‪RAPS_HELAV_DEBUG
‪#define RAPS_HELAV_DEBUG
Definition: _killstreaks.gsh:156
‪RAPS_HEDEPS_REDUCE_RADIUS_RETRIES
‪#define RAPS_HEDEPS_REDUCE_RADIUS_RETRIES
Definition: _killstreaks.gsh:150
‪RAPS_HELICOPTER_DROP_DURATION_LAST
‪#define RAPS_HELICOPTER_DROP_DURATION_LAST
Definition: _killstreaks.gsh:139
‪RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT
‪#define RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT
Definition: _killstreaks.gsh:149
‪RAPS_HELICOPTER_DROP_LOCATION_TOLERANCE_SQR
‪#define RAPS_HELICOPTER_DROP_LOCATION_TOLERANCE_SQR
Definition: _killstreaks.gsh:143
‪configure_team
‪function configure_team(killstreakType, killstreakId, owner, influencerType, configureTeamPreFunction, configureTeamPostFunction, isHacked=false)
Definition: _killstreaks.gsc:2806
‪play_taacom_dialog_response_on_owner
‪function play_taacom_dialog_response_on_owner(dialogKey, killstreakType, killstreakId)
Definition: _killstreaks.gsc:2036
‪RAPS_NAME
‪#define RAPS_NAME
Definition: _killstreaks.gsh:108
‪detonate
‪function detonate(attacker)
Definition: _raps.gsc:513
‪get_enemy_team_mask
‪function get_enemy_team_mask(team)
Definition: _spawning.gsc:253
‪RAPS_HEDEPS_DEBUG
‪#define RAPS_HEDEPS_DEBUG
Definition: _killstreaks.gsh:148
‪RAPS_HELICOPTER_LEAVE_LOCATION_REACHED_SQR
‪#define RAPS_HELICOPTER_LEAVE_LOCATION_REACHED_SQR
Definition: _killstreaks.gsh:144
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪RAPS_HELICOPTER_DROP_LOCATION_COUNT
‪#define RAPS_HELICOPTER_DROP_LOCATION_COUNT
Definition: _killstreaks.gsh:136
‪RAPS_HELAV_EXPEDIENT_MODE_ACCEL
‪#define RAPS_HELAV_EXPEDIENT_MODE_ACCEL
Definition: _killstreaks.gsh:178
‪WatchRapsKillstreakEnd
‪function WatchRapsKillstreakEnd(killstreakId, ownerEntNum, team)
Definition: _raps.gsc:379
‪RAPS_HELICOPTER_NAV_SPACIOUS_POINT_BOUNDARY
‪#define RAPS_HELICOPTER_NAV_SPACIOUS_POINT_BOUNDARY
Definition: _killstreaks.gsh:124
‪GetRandomHelicopterPosition
‪function GetRandomHelicopterPosition(avoidPoint=RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT, otherAvoidPoint=RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT, avoidRadiusSqr=RAPS_HEDEPS_AVOID_RADIUS_SQR)
Definition: _raps.gsc:872
‪HelicopterThinkDebugVisitAll
‪function HelicopterThinkDebugVisitAll()
Definition: _raps.gsc:1041
‪WaitUntilTeamChange
‪function WaitUntilTeamChange(player, callback, arg, end_condition1, end_condition2, end_condition3)
Definition: _teams.gsc:447
‪enable_hacking
‪function enable_hacking(killstreakName, preHackFunction, postHackFunction)
Definition: _killstreak_hacking.gsc:22
‪WatchGameEnded
‪function WatchGameEnded()
Definition: _raps.gsc:824
‪toggle_sounds
‪function toggle_sounds(on)
Definition: vehicle_shared.gsc:3379
‪on_connect
‪function on_connect()
Definition: _arena.gsc:20
‪RAPS_DRONE_NAME
‪#define RAPS_DRONE_NAME
Definition: _killstreaks.gsh:109
‪destroyNonAirScoreStreak_PostStatsLock
‪function destroyNonAirScoreStreak_PostStatsLock(weapon)
Definition: challenges_shared.gsc:126
‪RAPS_IWUS_SETTLE_ON_MESH_TIMEOUT
‪#define RAPS_IWUS_SETTLE_ON_MESH_TIMEOUT
Definition: _raps.gsc:1420
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪HeliDeathTrails
‪function HeliDeathTrails()
Definition: _raps.gsc:1158
‪RAPS_HELICOPTER_NAV_MAP_CENTER_MAX_OFFSET
‪#define RAPS_HELICOPTER_NAV_MAP_CENTER_MAX_OFFSET
Definition: _killstreaks.gsh:125
‪OnDeath
‪function OnDeath(attacker, weapon)
Definition: _raps.gsc:833
‪RAPS_HELI_FIRST_EXPLO_FX_TAG
‪#define RAPS_HELI_FIRST_EXPLO_FX_TAG
Definition: _killstreaks.gsh:187
‪RAPS_HELICOPTER_NAV_RADIUS_MIN
‪#define RAPS_HELICOPTER_NAV_RADIUS_MIN
Definition: _killstreaks.gsh:120
‪create_entity_influencer
‪function create_entity_influencer(name, team_mask)
Definition: _spawning.gsc:294
‪IsInSmokeGrenade
‪function IsInSmokeGrenade()
Definition: _smokegrenade.gsc:123
‪RAPS_HELICOPTER_DROP_DURATION_DELTA
‪#define RAPS_HELICOPTER_DROP_DURATION_DELTA
Definition: _killstreaks.gsh:138
‪RAPS_HELAV_TIME_BETWEEN_UPDATES
‪#define RAPS_HELAV_TIME_BETWEEN_UPDATES
Definition: _killstreaks.gsh:157
‪RAPS_HELAV_STOP_WAIT_BEFORE_NEXT_DROP_POINT_MS
‪#define RAPS_HELAV_STOP_WAIT_BEFORE_NEXT_DROP_POINT_MS
Definition: _killstreaks.gsh:159
‪GetRandomHelicopterStartOrigin
‪function GetRandomHelicopterStartOrigin(fly_height, firstDropLocation)
Definition: _raps.gsc:672
‪GetClosestRandomHelicopterPosition
‪function GetClosestRandomHelicopterPosition(refPoint, pickCount, avoidPoint=RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT, otherAvoidPoint=RAPS_HEDEPS_UNSPECIFIED_AVOID_POINT)
Definition: _raps.gsc:919
‪RAPS_HELICOPTER_NAV_POINT_TRACE_DEBUG
‪#define RAPS_HELICOPTER_NAV_POINT_TRACE_DEBUG
Definition: _killstreaks.gsh:129
‪HelicopterLeave
‪function HelicopterLeave()
Definition: _raps.gsc:1169
‪RAPS_HELAV_FULL_STOP_MODE_DECEL
‪#define RAPS_HELAV_FULL_STOP_MODE_DECEL
Definition: _killstreaks.gsh:183
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265