‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_airsupport.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\damagefeedback_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\util_shared;
7 #using scripts\shared\weapons\_weaponobjects;
8 #using scripts\shared\weapons\_weapons;
9 
10 #insert scripts\shared\shared.gsh;
11 
12 #using scripts\mp\_util;
13 
14 #namespace airsupport;
15 
16 // some common functions between all the air kill streaks
17 
18 function ‪init()
19 {
20  if ( !isdefined( level.airsupportHeightScale ) )
21  level.airsupportHeightScale = 1;
22 
23  level.airsupportHeightScale = GetDvarInt( "scr_airsupportHeightScale", level.airsupportHeightScale );
24 
25  level.noFlyZones = [];
26  level.noFlyZones = GetEntArray("no_fly_zone","targetname");
27 
28  airsupport_heights = ‪struct::get_array("air_support_height","targetname");
29 
30  /#
31  if ( airsupport_heights.size > 1 )
32  {
33  ‪util::error( "Found more then one 'air_support_height' structs in the map" );
34  }
35  #/
36 
37  airsupport_heights = GetEntArray("air_support_height","targetname");
38 
39  /#
40  if ( airsupport_heights.size > 0 )
41  {
42  ‪util::error( "Found an entity in the map with an 'air_support_height' targetname. There should be only structs." );
43  }
44  #/
45 
46  heli_height_meshes = GetEntArray("heli_height_lock","classname");
47 
48  /#
49  if ( heli_height_meshes.size > 1 )
50  {
51  ‪util::error( "Found more then one 'heli_height_lock' classname in the map" );
52  }
53  #/
54 
56 }
57 
58 function ‪finishHardpointLocationUsage( location, usedCallback )
59 {
60  self notify( "used" );
62 
63  if( isdefined( usedCallback ) )
64  {
65  return self [[usedCallback]]( location );
66  }
67 
68  return true;
69 }
70 
71 function ‪finishDualHardpointLocationUsage( locationStart, locationEnd, usedCallback )
72 {
73  self notify( "used" );
75  return self [[usedCallback]]( locationStart, locationEnd );
76 }
77 
79 {
80  self endon( "death" );
81  self endon( "disconnect" );
82  self endon( "cancel_location" );
83  self endon( "used" );
84  self endon( "host_migration_begin" );
85 
86  level waittill( "game_ended" );
87  self notify( "game_ended" );
88 }
89 
91 {
92  self endon( "death" );
93  self endon( "disconnect" );
94  self endon( "cancel_location" );
95  self endon( "used" );
96  self endon( "game_ended" );
97 
98  level waittill( "host_migration_begin" );
99  self notify( "cancel_location" );
100 }
101 
103 {
104  assert( IsPlayer( self ) );
105  assert( IsAlive( self ) );
106  assert( isdefined( self.selectingLocation ) );
107  assert( self.selectingLocation == true );
108 
109  self thread ‪endSelectionOnGameEnd();
110  self thread ‪endSelectionOnHostMigration();
111 
112  event = self ‪util::waittill_any_return( "death", "disconnect", "cancel_location", "game_ended", "used", "weapon_change", "emp_jammed" );
113 
114  if ( event != "disconnect" )
115  {
116  self.selectingLocation = undefined;
117  self thread ‪clearUpLocationSelection();
118  }
119 
120  if ( event != "used" )
121  {
122  // wake threads waiting for locations
123  self notify( "confirm_location", undefined, undefined );
124  }
125 }
126 
128 {
129  event = self ‪util::waittill_any_return( "death", "disconnect", "game_ended", "used", "weapon_change", "emp_jammed", "weapon_change_complete" );
130 
131  if ( event != "disconnect" )
132  {
133  self endLocationSelection();
134  }
135 }
136 
138 {
139  self endon ( "death" );
140  wait ( time );
141 
142  self stoploopsound( 2 );
143 }
144 
145 function ‪calculateFallTime( flyHeight )
146 {
147  // this is the value that code uses
148  gravity = GetDvarint( "bg_gravity" );
149 
150  time = sqrt( (2 * flyHeight) / gravity );
151 
152  return time;
153 }
154 
155 function ‪calculateReleaseTime( flyTime, flyHeight, flySpeed, bombSpeedScale )
156 {
157  falltime = ‪calculateFallTime( flyHeight );
158 
159  // bomb horizontal velocity is not the same as the plane speed so we need to take this
160  // into account when calculating the bomb time
161  bomb_x = (flySpeed * bombSpeedScale) * falltime;
162  release_time = bomb_x / flySpeed;
163 
164  return ( (flyTime * 0.5) - release_time);
165 }
166 
168 {
169  airsupport_height = ‪struct::get( "air_support_height", "targetname");
170  if ( isdefined(airsupport_height) )
171  {
172  planeFlyHeight = airsupport_height.origin[2];
173  }
174  else
175  {
176 /#
177  PrintLn("WARNING: Missing air_support_height entity in the map. Using default height.");
178 #/
179  // original system
180  planeFlyHeight = 850;
181 
182  if ( isdefined( level.airsupportHeightScale ) )
183  {
184  level.airsupportHeightScale = GetDvarInt( "scr_airsupportHeightScale", level.airsupportHeightScale );
185  planeFlyHeight *= GetDvarInt( "scr_airsupportHeightScale", level.airsupportHeightScale );
186  }
187 
188  if ( isdefined( level.forceAirsupportMapHeight ) )
189  {
190  planeFlyHeight += level.forceAirsupportMapHeight;
191  }
192  }
193 
194  return planeFlyHeight;
195 }
196 
197 function ‪callStrike( flightPlan )
198 {
199  level.bomberDamagedEnts = [];
200  level.bomberDamagedEntsCount = 0;
201  level.bomberDamagedEntsIndex = 0;
202 
203  assert( flightPlan.distance != 0, "callStrike can not be passed a zero fly distance");
204 
205  planeHalfDistance = flightPlan.distance / 2;
206 
207  path = ‪getStrikePath( flightPlan.target, flightPlan.height, planeHalfDistance );
208  startPoint = path["start"];
209  endPoint = path["end"];
210  flightPlan.height = path["height"];
211  direction = path["direction"];
212 
213  // Make the plane fly by
214  d = length( startPoint - endPoint );
215  flyTime = ( d / flightPlan.speed );
216 
217  bombTime = ‪calculateReleaseTime( flyTime, flightPlan.height, flightPlan.speed, flightPlan.bombSpeedScale);
218 
219  if (bombTime < 0)
220  {
221  bombTime = 0;
222  }
223 
224  assert( flyTime > bombTime );
225 
226  flightPlan.owner endon("disconnect");
227 
228  requiredDeathCount = flightPlan.owner.deathCount;
229 
230  side = VectorCross( anglestoforward( direction ), (0,0,1) );
231  plane_seperation = 25;
232  side_offset = VectorScale( side, plane_seperation );
233 
234  level thread ‪planeStrike( flightPlan.owner, requiredDeathCount, startPoint, endPoint, bombTime, flyTime, flightPlan.speed, flightPlan.bombSpeedScale, direction, flightPlan.planeSpawnCallback );
235  wait( flightPlan.planeSpacing );
236  level thread ‪planeStrike( flightPlan.owner, requiredDeathCount, startPoint+side_offset, endPoint+side_offset, bombTime, flyTime, flightPlan.speed, flightPlan.bombSpeedScale, direction, flightPlan.planeSpawnCallback );
237  wait( flightPlan.planeSpacing );
238 
239  side_offset = VectorScale( side, -1 * plane_seperation );
240 
241  level thread ‪planeStrike( flightPlan.owner, requiredDeathCount, startPoint+side_offset, endPoint+side_offset, bombTime, flyTime, flightPlan.speed, flightPlan.bombSpeedScale, direction, flightPlan.planeSpawnCallback );
242 }
243 
244 
245 function ‪planeStrike( owner, requiredDeathCount, pathStart, pathEnd, bombTime, flyTime, flyspeed, bombSpeedScale, direction, planeSpawnedFunction )
246 {
247  // plane spawning randomness = up to 125 units, biased towards 0
248  // radius of bomb damage is 512
249 
250  if ( !isdefined( owner ) )
251  return;
252 
253 // bomb_x = (flySpeed * bombSpeedScale) * bombTime;
254 // origin = VectorScale(pathEnd - pathStart, 0.5) + pathStart;
255 // plane = spawnplane( owner, "script_model", origin );
256 
257  // Spawn the planes
258  plane = spawnplane( owner, "script_model", pathStart );
259  plane.angles = direction;
260 
261  plane moveTo( pathEnd, flyTime, 0, 0 );
262 
263  thread ‪debug_plane_line( flyTime, flyspeed, pathStart, pathEnd );
264 
265  if ( isdefined(planeSpawnedFunction) )
266  {
267  plane [[planeSpawnedFunction]]( owner, requiredDeathCount, pathStart, pathEnd, bombTime, bombSpeedScale, flyTime, flyspeed );
268  }
269 
270  // Delete the plane after its flyby
271  wait flyTime;
272  plane notify( "delete" );
273  plane delete();
274 }
275 
277 // TARGETING
278 
279 function ‪determineGroundPoint( player, position )
280 {
281  ground = (position[0], position[1], player.origin[2]);
282 
283  ‪trace = bullettrace(ground + (0,0,10000), ground, false, undefined );
284  return ‪trace["position"];
285 }
286 
287 function ‪determineTargetPoint( player, position )
288 {
289  point = ‪determineGroundPoint( player, position );
290 
291  return ‪clampTarget( point );
292 }
293 
295 {
296  return level.spawnMins[2] - 500;
297 }
298 
300 {
301  return level.spawnMaxs[2] + 500;
302 }
303 
304 function ‪clampTarget( target )
305 {
306  min = ‪getMinTargetHeight();
307  max = ‪getMaxTargetHeight();
308 
309  if ( target[2] < min )
310  target[2] = min;
311 
312  if ( target[2] > max )
313  target[2] = max;
314 
315  return target;
316 }
317 
318 
320 // NO FLY ZONE
321 
322 function ‪_insideCylinder( point, base, radius, height )
323 {
324  // only going to test if the point is above the height
325  // if the point is below the cylinder going to treat it
326  // as being inside
327  if ( isdefined( height ) )
328  {
329  if ( point[2] > base[2] + height )
330  return false;
331  }
332 
333  dist = Distance2D( point, base );
334 
335  if ( dist < radius )
336  return true;
337 
338  return false;
339 }
340 
341 function ‪_insideNoFlyZoneByIndex( point, index, disregardHeight )
342 {
343  height = level.noFlyZones[index].height;
344 
345  if ( isdefined(disregardHeight ) )
346  height = undefined;
347 
348  return ‪_insideCylinder( point, level.noFLyZones[index].origin, level.noFlyZones[index].radius, height );
349 }
350 
351 // if not in a no fly zone then it just returns the height of the point passed in
352 function ‪getNoFlyZoneHeight( point )
353 {
354  height = point[2];
355  origin = undefined;
356 
357  for ( i = 0; i < level.noFlyZones.size; i++ )
358  {
359  if ( ‪_insideNoFlyZoneByIndex( point, i ) )
360  {
361  if ( height < level.noFlyZones[i].height )
362  {
363  height = level.noFlyZones[i].height;
364  origin = level.noFlyZones[i].origin;
365  }
366  }
367  }
368 
369  if ( !isdefined( origin ) )
370  return point[2];
371 
372  return origin[2] + height;
373 }
374 
375 function ‪insideNoFlyZones( point, disregardHeight )
376 {
377  noFlyZones = [];
378 
379  for ( i = 0; i < level.noFlyZones.size; i++ )
380  {
381  if ( ‪_insideNoFlyZoneByIndex( point, i, disregardHeight ) )
382  {
383  noFlyZones[noFlyZones.size] = i;
384  }
385  }
386 
387  return noFlyZones;
388 }
389 
390 
391 function ‪crossesNoFlyZone( start, ‪end )
392 {
393  for ( i = 0; i < level.noFlyZones.size; i++ )
394  {
395  point = ‪math::closest_point_on_line( level.noFlyZones[i].origin + (0,0,(0.5 * level.noFlyZones[i].height)), start, ‪end );
396  dist = Distance2D( point, level.noFlyZones[i].origin );
397 
398  if ( point[2] > ( level.noFlyZones[i].origin[2] + level.noFlyZones[i].height ) )
399  continue;
400 
401  if ( dist < level.noFlyZones[i].radius )
402  {
403  return i;
404  }
405  }
406 
407  return undefined;
408 }
409 
410 function ‪crossesNoFlyZones( start, ‪end )
411 {
412  zones = [];
413  for ( i = 0; i < level.noFlyZones.size; i++ )
414  {
415  point = ‪math::closest_point_on_line( level.noFlyZones[i].origin, start, ‪end );
416  dist = Distance2D( point, level.noFlyZones[i].origin );
417 
418  if ( point[2] > ( level.noFlyZones[i].origin[2] + level.noFlyZones[i].height ) )
419  continue;
420 
421  if ( dist < level.noFlyZones[i].radius )
422  {
423  zones[zones.size] = i;
424  }
425  }
426 
427  return zones;
428 }
429 
430 function ‪getNoFlyZoneHeightCrossed( start, ‪end, minHeight )
431 {
432  height = minHeight;
433  for ( i = 0; i < level.noFlyZones.size; i++ )
434  {
435  point = ‪math::closest_point_on_line( level.noFlyZones[i].origin, start, ‪end );
436  dist = Distance2D( point, level.noFlyZones[i].origin );
437 
438  if ( dist < level.noFlyZones[i].radius )
439  {
440  if ( height < level.noFlyZones[i].height )
441  height = level.noFlyZones[i].height;
442  }
443  }
444 
445  return height;
446 }
447 
448 function ‪_shouldIgnoreNoFlyZone( noFlyZone, noFlyZones )
449 {
450  if ( !isdefined( noFlyZone ) )
451  return true;
452 
453  for ( i = 0; i < noFlyZones.size; i ++ )
454  {
455  if ( isdefined( noFlyZones[i] ) && noFlyZones[i] == noFlyZone )
456  return true;
457  }
458 
459  return false;
460 }
461 
462 function ‪_shouldIgnoreStartGoalNoFlyZone( noFlyZone, startNoFlyZones, goalNoFlyZones )
463 {
464  if ( !isdefined( noFlyZone ) )
465  return true;
466 
467  if ( ‪_shouldIgnoreNoFlyZone( noFlyZone, startNoFlyZones ) )
468  return true;
469 
470  if ( ‪_shouldIgnoreNoFlyZone( noFlyZone, goalNoFlyZones ) )
471  return true;
472 
473  return false;
474 }
475 
476 
477 function ‪getHeliPath( start, goal )
478 {
479  startNoFlyZones = ‪insideNoFlyZones( start, true );
480 
481  thread ‪debug_line( start, goal, (1,1,1) );
482 
483  goalNoFlyZones = ‪insideNoFlyZones( goal );
484 
485  // if the end point is in a no fly zone then raise the height to the top of the zone
486  if ( goalNoFlyZones.size )
487  {
488  goal = ( goal[0], goal[1], ‪getNoFlyZoneHeight( goal ) );
489  }
490 
491  goal_points = ‪calculatePath(start, goal, startNoFlyZones, goalNoFlyZones );
492 
493  if ( !isdefined( goal_points ) )
494  return undefined;
495 
496  Assert(goal_points.size >= 1 );
497 
498  return goal_points;
499 }
500 
501 function ‪followPath( path, doneNotify, stopAtGoal )
502 {
503  for ( i = 0; i < (path.size - 1); i++ )
504  {
505  self SetVehGoalPos( path[i], false );
506 
507  thread ‪debug_line( self.origin, path[i], (1,1,0) );
508  self waittill("goal" );
509  }
510 
511  self SetVehGoalPos( path[path.size - 1], stopAtGoal );
512  thread ‪debug_line( self.origin, path[i], (1,1,0) );
513 
514  self waittill("goal" );
515 
516  if ( isdefined( doneNotify ) )
517  {
518  self notify(doneNotify);
519  }
520 }
521 
522 function ‪setGoalPosition( goal, doneNotify, stopAtGoal )
523 {
524  if ( !isdefined( stopAtGoal ) )
525  stopAtGoal = true;
526 
527  // should test the start to see if it is inside of a no fly zone
528  // and try and make the vehicle leave the no fly zone in as short of
529  // a path possible while still moving intelligently
530  start = self.origin;
531 
532  goal_points = ‪getHeliPath(start, goal );
533 
534  if ( !isdefined(goal_points) )
535  {
536  goal_points = [];
537  goal_points[0] = goal;
538  }
539 
540  ‪followPath( goal_points, doneNotify, stopAtGoal );
541 }
542 
543 function ‪clearPath( start, ‪end, startNoFlyZone, goalNoFlyZone )
544 {
545  noFlyZones = ‪crossesNoFlyZones( start, ‪end );
546 
547  for ( i = 0 ; i < noFlyZones.size; i++ )
548  {
549  if ( !‪_shouldIgnoreStartGoalNoFlyZone( noFlyZones[i], startNoFlyZone, goalNoFlyZone) )
550  {
551  return false;
552  }
553  }
554 
555  return true;
556 }
557 
558 function ‪append_array( dst, src )
559 {
560  for ( i= 0; i < src.size; i++ )
561  {
562  dst[ dst.size ]= src[ i ];
563  }
564 }
565 
566 function ‪calculatePath_r( start, ‪end, points, startNoFlyZones, goalNoFlyZones, depth )
567 {
568  depth--;
569 
570  if ( depth <= 0 )
571  {
572  points[points.size] = ‪end;
573  return points;
574  }
575 
576  noFlyZones = ‪crossesNoFlyZones( start, ‪end );
577 
578  for ( i = 0; i < noFlyZones.size; i++ )
579  {
580  noFlyZone = noFlyZones[i];
581 
582  // simple path right now
583  // probably need to modify this so it tests the new lines found
584  if ( !‪_shouldIgnoreStartGoalNoFlyZone( noFlyZone, startNoFlyZones, goalNoFlyZones) )
585  {
586  return undefined;
587  }
588  }
589 
590  points[points.size] = ‪end;
591 
592  return points;
593 }
594 
595 function ‪calculatePath( start, ‪end, startNoFlyZones, goalNoFlyZones )
596 {
597  points = [];
598 
599 // PrintLn( "starting path calc: " + start + " " + end );
600 // points[0] = start;
601 
602  points = ‪calculatePath_r( start, ‪end, points, startNoFlyZones, goalNoFlyZones, 3 );
603 
604  if ( !isdefined(points) )
605  return undefined;
606 
607  Assert( points.size >= 1 );
608 
609 
610  ‪debug_sphere( points[points.size - 1], 10, (1,0,0), 1, 1000 );
611 
612  point = start;
613 
614 // PrintLn( "Path Calculated: " + points.size );
615  for ( i = 0 ; i < points.size; i++ )
616  {
617  thread ‪debug_line( point, points[i], (0,1,0) );
618  ‪debug_sphere( points[i], 10, (0,0,1), 1, 1000 );
619  point = points[i];
620  }
621  return points;
622 }
623 
624 function ‪_getStrikePathStartAndEnd( goal, yaw, halfDistance )
625 {
626  direction = (0,yaw,0);
627 
628  startPoint = goal + VectorScale( anglestoforward( direction ), -1 * halfDistance );
629  endPoint = goal + VectorScale( anglestoforward( direction ), halfDistance );
630 
631  noFlyZone = ‪crossesNoFlyZone( startPoint, endPoint );
632 
633  path = [];
634 
635  if ( isdefined( noFlyZone ) )
636  {
637  path["noFlyZone"] = noFlyZone;
638 
639  startPoint = ( startPoint[0], startPoint[1], level.noFlyZones[noFlyZone].origin[2] + level.noFlyZones[noFlyZone].height );
640  endPoint = ( endPoint[0], endPoint[1], startPoint[2] );
641  }
642  else
643  {
644  path["noFlyZone"] = undefined;
645  }
646 
647  path["start"] = startPoint;
648  path["end"] = endPoint;
649  path["direction"] = direction;
650 
651  return path;
652 }
653 
654 function ‪getStrikePath( target, height, halfDistance, yaw )
655 {
656  noFlyZoneHeight = ‪getNoFlyZoneHeight( target );
657 
658  worldHeight = target[2] + height;
659 
660  if ( noFlyZoneHeight > worldHeight )
661  {
662  worldHeight = noFlyZoneHeight;
663  }
664 
665  goal = ( target[0], target[1], worldHeight );
666 
667  path = [];
668 
669  if ( !isdefined( yaw ) || yaw != "random" )
670  {
671  // try a few times to find a path that is not through a no fly zone
672  for ( i = 0; i < 3; i++ )
673  {
674  path = ‪_getStrikePathStartAndEnd( goal, randomint( 360 ), halfDistance );
675 
676  if ( !isdefined( path["noFlyZone"] ) )
677  {
678  break;
679  }
680  }
681  }
682  else
683  {
684  path = ‪_getStrikePathStartAndEnd( goal, yaw, halfDistance );
685  }
686 
687  path["height"] = worldHeight - target[2];
688  return path;
689 }
690 
691 function ‪doGlassDamage(pos, radius, max, min, mod)
692 {
693  wait(RandomFloatRange(0.05, 0.15));
694  glassRadiusDamage( pos, radius, max, min, mod );
695 }
696 
697 function ‪entLOSRadiusDamage( ent, pos, radius, max, min, owner, eInflictor )
698 {
699  dist = distance(pos, ent.damageCenter);
700 
701  if ( ent.isPlayer || ent.isActor )
702  {
703  assumed_ceiling_height = 800; // check for very high ceilings
704  eye_position = ent.entity GetEye();
705  head_height = eye_position[2];
706  debug_display_time = 40 * 100;
707 
708  // check if there is a path to this entity above his feet. if not, they're probably indoors
709  ‪trace = ‪weapons::damage_trace( ent.entity.origin, ent.entity.origin + (0,0,assumed_ceiling_height), 0, undefined );
710  indoors = (‪trace["fraction"] != 1);
711 
712  if ( indoors )
713  {
714  // the follow check will still fail indoors if the bomb is detonated above the player
715  // and the ceiling is under 130 units. This second check will have line of site to
716  // the "ceiling height" point. I dont want to change it at this point.
717 
718  test_point = ‪trace["position"];
719  ‪debug_star(test_point, (0,1,0), debug_display_time);
720 
721  ‪trace = ‪weapons::damage_trace( (test_point[0],test_point[1],head_height) , (pos[0],pos[1], head_height), 0, undefined );
722  indoors = (‪trace["fraction"] != 1);
723 
724  if ( indoors )
725  {
726  ‪debug_star((pos[0],pos[1], head_height), (0,1,0), debug_display_time);
727  // give them a distance advantage for being indoors.
728  dist *= 4;
729  if ( dist > radius )
730  return false;
731  }
732  else
733  {
734  ‪debug_star((pos[0],pos[1], head_height), (1,0,0), debug_display_time);
735  ‪trace = ‪weapons::damage_trace( (pos[0],pos[1], head_height), pos, 0, undefined );
736  indoors = (‪trace["fraction"] != 1);
737  if ( indoors )
738  {
739  ‪debug_star(pos, (0,1,0), debug_display_time);
740  // give them a distance advantage for being indoors.
741  dist *= 4;
742  if ( dist > radius )
743  return false;
744  }
745  else
746  {
747  ‪debug_star(pos, (1,0,0), debug_display_time);
748  }
749  }
750  }
751  else
752  {
753  ‪debug_star(ent.entity.origin + (0,0,assumed_ceiling_height), (1,0,0), debug_display_time );
754  }
755  }
756 
757  ent.damage = int(max + (min-max)*dist/radius);
758  ent.pos = pos;
759  ent.damageOwner = owner;
760  ent.eInflictor = eInflictor;
761 
762  return true;
763 }
764 
766 function ‪GetMapCenter()
767 {
768  minimapOrigins = getEntArray( "minimap_corner", "targetname" );
769  if( miniMapOrigins.size )
770  {
771  return ‪math::find_box_center( miniMapOrigins[0].origin, miniMapOrigins[1].origin );
772  }
773 
774  return ( 0, 0, 0 );
775 }
776 
777 function ‪GetRandomMapPoint( x_offset, y_offset, map_x_percentage, map_y_percentage )
778 {
779  minimapOrigins = getEntArray( "minimap_corner", "targetname" );
780  if( miniMapOrigins.size )
781  {
782  rand_x = 0;
783  rand_y = 0;
784 
785  if( miniMapOrigins[0].origin[0] < miniMapOrigins[1].origin[0] )
786  {
787  rand_x = RandomFloatRange( miniMapOrigins[0].origin[0] * map_x_percentage, miniMapOrigins[1].origin[0] * map_x_percentage );
788  rand_y = RandomFloatRange( miniMapOrigins[0].origin[1] * map_y_percentage, miniMapOrigins[1].origin[1] * map_y_percentage );
789  }
790  else
791  {
792  rand_x = RandomFloatRange( miniMapOrigins[1].origin[0] * map_x_percentage, miniMapOrigins[0].origin[0] * map_x_percentage );
793  rand_y = RandomFloatRange( miniMapOrigins[1].origin[1] * map_y_percentage, miniMapOrigins[0].origin[1] * map_y_percentage );
794  }
795 
796  return ( x_offset + rand_x, y_offset + rand_y, 0 );
797  }
798 
799  return ( x_offset, y_offset, 0 );
800 }
801 
803 {
804  minimapOrigins = getEntArray( "minimap_corner", "targetname" );
805  if( miniMapOrigins.size )
806  {
807  x = abs( miniMapOrigins[0].origin[0] - miniMapOrigins[1].origin[0] );
808  y = abs( miniMapOrigins[0].origin[1] - miniMapOrigins[1].origin[1] );
809 
810  return max( x, y );
811  }
812 
813  return 0;
814 }
815 
817 {
818  level.airsupport_rotator = ‪spawn( "script_model", ‪GetMapCenter() + ( ‪VAL( level.rotator_x_offset, 0 ), ‪VAL( level.rotator_y_offset, 0 ), 1200 ) );
819  level.airsupport_rotator setModel( "tag_origin" );
820  level.airsupport_rotator.angles = ( 0, 115, 0 );
821  level.airsupport_rotator hide();
822  level.airsupport_rotator thread ‪RotateRig();
823  level.airsupport_rotator thread ‪SwayRig();
824 }
825 
826 function ‪RotateRig()
827 {
828  for (;;)
829  {
830  self rotateyaw( -360, 60 );
831  wait ( 60 );
832  }
833 }
834 
835 function ‪SwayRig()
836 {
837  centerOrigin = self.origin;
838 
839  for (;;)
840  {
841  z = randomIntRange( -200, -100 );
842 
843  time = randomIntRange( 3, 6 );
844  self moveto( centerOrigin + (0,0,z), time, 1, 1 );
845  wait ( time );
846 
847  z = randomIntRange( 100, 200 );
848 
849  time = randomIntRange( 3, 6 );
850  self moveto( centerOrigin + (0,0,z), time, 1, 1 );
851  wait ( time );
852  }
853 }
854 
855 function ‪StopRotation( time )
856 {
857  self endon( "death" );
858  wait( time );
859  self StopLoopSound();
860 }
861 
862 function ‪FlattenYaw( goal )
863 {
864  self endon( "death" );
865 
866  ‪increment = 3;
867  if ( self.angles[1] > goal )
868  {
869  ‪increment = ‪increment * -1;
870  }
871  while( abs( self.angles[1] - goal ) > 3 )
872  {
873  self.angles = (self.angles[0], self.angles[1] + ‪increment, self.angles[2] );
875  }
876 }
877 
878 function ‪FlattenRoll()
879 {
880  self endon( "death" );
881 
882  while (self.angles[2] < 0)
883  {
884  self.angles = (self.angles[0], self.angles[1], self.angles[2] + 2.5 );
886  }
887 }
888 
889 function ‪Leave( duration )
890 {
891  self unlink();
892 
893  self thread ‪StopRotation( 1 );
894 
895  tries = 10;
896  yaw = 0;
897  while( tries > 0 )
898  {
899  exitVector = ( anglestoforward( self.angles + ( 0, yaw, 0 ) ) * 20000 );
900  exitPoint = ( self.origin[0] + exitVector[0], self.origin[1] + exitVector[1], self.origin[2] - 2500);
901  exitPoint = self.origin + exitVector;
902 
903  nfz = ‪airsupport::crossesNoFlyZone (self.origin, exitPoint);
904  if( isdefined(nfz))
905  {
906  if ( tries != 1 )
907  {
908  if ( tries % 2 == 1)
909  {
910  yaw = yaw * -1;
911  }
912  else
913  {
914  yaw = yaw + 10;
915  yaw = yaw * -1;
916  }
917  }
918  tries--;
919  }
920  else
921  {
922  tries = 0;
923  }
924  }
925 
926  self thread ‪FlattenYaw( self.angles[1] + yaw );
927  if (self.angles[2] != 0)
928  {
929  self thread ‪FlattenRoll();
930  }
931 
932  if ( IsVehicle( self ) )
933  {
934  self SetSpeed( ( ( Length( exitVector ) / duration ) / ‪MPH_TO_INCHES_PER_SEC ), 60 );
935  self SetVehGoalPos( exitPoint, false, false );
936  }
937  else
938  {
939  self moveto( exitPoint, duration, 0, 0 );
940  }
941  self notify ( "leaving");
942 }
943 
944 
946 {
947  dist = -1 * GetDvarInt( "scr_supplydropIncomingDistance", 10000 );
948  pathRandomness = 100;
949  direction = ( 0, RandomIntRange( -2, 3 ), 0 );
950 
951  start_origin = ( AnglesToForward( direction ) * dist );
952  start_origin += ( ( randomfloat( 2 ) - 1 ) * pathRandomness, ( randomfloat( 2 ) - 1 ) * pathRandomness, 0 );
953 
954 /#
955  if ( GetDvarInt( "scr_noflyzones_debug", 0 ) )
956  {
957  if ( level.noFlyZones.size )
958  {
959  index = RandomIntRange( 0, level.noFlyZones.size );
960  delta = level.noFlyZones[ index ].origin;
961  delta = ( delta[0] + RandomInt( 10 ), delta[ 1 ] + RandomInt( 10 ), 0 );
962  delta = VectorNormalize( delta );
963  start_origin = ( delta * dist );
964  }
965  }
966 #/
967  return start_origin;
968 }
969 
970 
972 // debug
973 
975 {
976  /#
977  for ( i = 0; i < level.noFlyZones.size; i++ )
978  {
979  ‪debug_airsupport_cylinder( level.noFlyZones[i].origin, level.noFlyZones[i].radius, level.noFlyZones[i].height, (1,1,1), undefined, 5000 );
980  }
981  #/
982 }
983 
984 function ‪debug_plane_line( flyTime, flyspeed,pathStart, pathEnd )
985 {
986  thread ‪debug_line( pathStart, pathEnd, (1,1,1) );
987 
988  delta = VectorNormalize(pathEnd - pathStart);
989 
990  for ( i = 0; i < flyTime; i++ )
991  {
992  thread ‪debug_star( pathStart + VectorScale(delta, i * flyspeed), (1,0,0) );
993  }
994 }
995 
997 {
998  self notify("draw_explosion");
1000  self endon("draw_explosion");
1001 
1002  self waittill("projectile_impact", weapon, position );
1003 
1004  thread ‪debug_line( prevpos, position, (.5,1,0) );
1005  thread ‪debug_star( position, (1,0,0) );
1006 }
1007 
1008 function ‪debug_draw_bomb_path( projectile, color, time )
1009 {
1010 /#
1011  self endon("death");
1012  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1013 
1014  if ( !isdefined( color ) )
1015  {
1016  color = (.5,1,0);
1017  }
1018 
1019  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1.0 )
1020  {
1021  prevpos = self.origin;
1022  while(isdefined ( self.origin ) )
1023  {
1024  thread ‪debug_line( prevpos, self.origin, color, time );
1025  prevpos = self.origin;
1026 
1027  if ( isdefined(projectile) && projectile )
1028  {
1029  thread ‪debug_draw_bomb_explosion( prevpos );
1030  }
1031 
1032  wait .2;
1033  }
1034  }
1035 #/
1036 }
1037 
1038 function ‪debug_print3d_simple( message, ent, offset, frames )
1039 {
1040  /#
1041  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1042 
1043  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1.0 )
1044  {
1045  if( isdefined( frames ) )
1046  thread ‪draw_text( message, ( 0.8, 0.8, 0.8 ), ent, offset, frames );
1047  else
1048  thread ‪draw_text( message, ( 0.8, 0.8, 0.8 ), ent, offset, 0 );
1049  }
1050  #/
1051 }
1052 
1053 function ‪draw_text( msg, color, ent, offset, frames )
1054 {
1055  /#
1056  if( frames == 0 )
1057  {
1058  while ( isdefined( ent ) && isdefined( ent.origin ) )
1059  {
1060  print3d( ent.origin+offset, msg , color, 0.5, 4 );
1062  }
1063  }
1064  else
1065  {
1066  for( i=0; i < frames; i++ )
1067  {
1068  if( !isdefined( ent ) )
1069  break;
1070  print3d( ent.origin+offset, msg , color, 0.5, 4 );
1072  }
1073  }
1074  #/
1075 }
1076 
1077 
1078 function ‪debug_print3d( message, color, ent, origin_offset, frames )
1079 {
1080 /#
1081  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1082 
1083  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1.0 )
1084  self thread ‪draw_text( message, color, ent, origin_offset, frames );
1085 #/
1086 }
1087 
1088 
1089 function ‪debug_line( from, to, color, time, depthTest )
1090 {
1091 /#
1092  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1093 
1094  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1.0 )
1095  {
1096  if ( DistanceSquared( from, to ) < 0.01 )
1097  return;
1098 
1099  if ( !isdefined(time) )
1100  {
1101  time = 1000;
1102  }
1103  if ( !isdefined(depthTest) )
1104  {
1105  depthTest = true;
1106  }
1107  Line( from, to, color, 1, depthTest, time);
1108  }
1109 #/
1110 
1111 }
1112 
1113 function ‪debug_star( origin, color, time )
1114 {
1115 /#
1116  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1117 
1118  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1.0 )
1119  {
1120  if ( !isdefined(time) )
1121  {
1122  time = 1000;
1123  }
1124  if ( !isdefined(color) )
1125  {
1126  color = (1,1,1);
1127  }
1128  debugstar( origin, time, color );
1129  }
1130 #/
1131 }
1132 
1133 function ‪debug_circle( origin, radius, color, time )
1134 {
1135 /#
1136  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1137 
1138  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1 )
1139  {
1140  if ( !isdefined(time) )
1141  {
1142  time = 1000;
1143  }
1144  if ( !isdefined(color) )
1145  {
1146  color = (1,1,1);
1147  }
1148  circle( origin, radius, color, true, true, time );
1149  }
1150 #/
1151 }
1152 
1153 function ‪debug_sphere( origin, radius, color, alpha, time )
1154 {
1155 /#
1156  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1157 
1158  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1 )
1159  {
1160  if ( !isdefined(time) )
1161  {
1162  time = 1000;
1163  }
1164  if ( !isdefined(color) )
1165  {
1166  color = (1,1,1);
1167  }
1168 
1169  sides = Int(10 * ( 1 + Int(radius / 100) ));
1170  sphere( origin, radius, color, alpha, true, sides, time );
1171  }
1172 #/
1173 }
1174 
1175 function ‪debug_airsupport_cylinder( origin, radius, height, color, mustRenderHeight, time )
1176 {
1177 /#
1178  level.airsupport_debug = GetDvarInt( "scr_airsupport_debug", 0 ); // debug mode, draws debugging info on screen
1179 
1180  if ( isdefined( level.airsupport_debug ) && level.airsupport_debug == 1 )
1181  {
1182  ‪debug_cylinder( origin, radius, height, color, mustRenderHeight, time );
1183  }
1184 #/
1185 }
1186 
1187 function ‪debug_cylinder( origin, radius, height, color, mustRenderHeight, time )
1188 {
1189 /#
1190 
1191  subdivision = 600;
1192 
1193  {
1194  if ( !isdefined(time) )
1195  {
1196  time = 1000;
1197  }
1198  if ( !isdefined(color) )
1199  {
1200  color = (1,1,1);
1201  }
1202 
1203  count = (height/subdivision);
1204 
1205  for ( i = 0; i < count; i++ )
1206  {
1207  point = origin + ( 0, 0, i * subdivision );
1208  circle( point, radius, color, true, true, time );
1209  }
1210 
1211  if( isdefined( mustRenderHeight ) )
1212  {
1213  point = origin + ( 0, 0, mustRenderHeight );
1214  circle( point, radius, color, true, true, time );
1215  }
1216  }
1217 #/
1218 }
1219 function ‪getPointOnLine( startPoint, endPoint, ratio )
1220 {
1221  nextPoint = ( startPoint[0] + ( ( endPoint[0] - startPoint[0] ) * ratio ) ,
1222  startPoint[1] + ( ( endPoint[1] - startPoint[1] ) * ratio ) ,
1223  startPoint[2] + ( ( endPoint[2] - startPoint[2] ) * ratio ) );
1224 
1225  return nextPoint;
1226 }
1227 
1229 {
1230  if ( self HasPerk( "specialty_nottargetedbyairsupport" ) ||
1231  ( isdefined( self.specialty_nottargetedbyairsupport ) && self.specialty_nottargetedbyairsupport ) )
1232  {
1233  if ( !isdefined( self.notTargettedAI_underMinSpeedTimer ) || self.notTargettedAI_underMinSpeedTimer < GetDvarInt( "perk_nottargetedbyai_graceperiod" ) )
1234  return false;
1235  }
1236  return true;
1237 }
1238 
1239 
1240 function ‪monitorSpeed( spawnProtectionTime )
1241 {
1242  self endon( "death" );
1243  self endon( "disconnect" );
1244 
1245  if ( self HasPerk( "specialty_nottargetedbyairsupport" ) == false )
1246  {
1247  return;
1248  }
1249 
1250  GetDvarString( "perk_nottargetted_graceperiod" );
1251  ‪gracePeriod = GetDvarInt( "perk_nottargetedbyai_graceperiod" );
1252  minspeed = GetDvarInt( "perk_nottargetedbyai_min_speed" );
1253  minspeedSq = minspeed * minspeed;
1254  waitPeriod = 0.25;
1255  waitPeriodMilliseconds = waitPeriod * 1000;
1256  if ( minspeedSq == 0 ) // will never fail min speed check below so early out.
1257  return;
1258 
1259  self.notTargettedAI_underMinSpeedTimer = 0;
1260 
1261  if ( isdefined ( spawnProtectionTime ) )
1262  {
1263  wait( spawnProtectionTime );
1264  }
1265 
1266  while(1)
1267  {
1268  velocity = self GetVelocity();
1269 
1270  speedsq = lengthsquared( velocity );
1271 
1272  if ( speedSq < minspeedSq )
1273  {
1274  self.notTargettedAI_underMinSpeedTimer += waitPeriodMilliseconds;
1275  }
1276  else
1277  {
1278  self.notTargettedAI_underMinSpeedTimer = 0;
1279  }
1280 
1281  wait( waitPeriod );
1282  }
1283 }
1284 
1286 {
1287  if ( isdefined ( self.notTargettedAI_underMinSpeedTimer ) )
1288  self.notTargettedAI_underMinSpeedTimer = 0;
1289 }
‪insideNoFlyZones
‪function insideNoFlyZones(point, disregardHeight)
Definition: _airsupport.gsc:375
‪debug_circle
‪function debug_circle(origin, radius, color, time)
Definition: _airsupport.gsc:1133
‪damage_trace
‪function damage_trace(from, to, startRadius, ignore)
Definition: _weapons.gsc:1150
‪calculatePath
‪function calculatePath(start, end, startNoFlyZones, goalNoFlyZones)
Definition: _airsupport.gsc:595
‪clearUpLocationSelection
‪function clearUpLocationSelection()
Definition: _airsupport.gsc:127
‪clampTarget
‪function clampTarget(target)
Definition: _airsupport.gsc:304
‪debug_no_fly_zones
‪function debug_no_fly_zones()
Definition: _airsupport.gsc:974
‪find_box_center
‪function find_box_center(mins, maxs)
Definition: math_shared.gsc:86
‪finishHardpointLocationUsage
‪function finishHardpointLocationUsage(location, usedCallback)
Definition: _airsupport.gsc:58
‪monitorSpeed
‪function monitorSpeed(spawnProtectionTime)
Definition: _airsupport.gsc:1240
‪getMinimumFlyHeight
‪function getMinimumFlyHeight()
Definition: _airsupport.gsc:167
‪_shouldIgnoreStartGoalNoFlyZone
‪function _shouldIgnoreStartGoalNoFlyZone(noFlyZone, startNoFlyZones, goalNoFlyZones)
Definition: _airsupport.gsc:462
‪debug_sphere
‪function debug_sphere(origin, radius, color, alpha, time)
Definition: _airsupport.gsc:1153
‪gracePeriod
‪function gracePeriod()
Definition: _globallogic.gsc:3471
‪init
‪function init()
Definition: _airsupport.gsc:18
‪FlattenRoll
‪function FlattenRoll()
Definition: _airsupport.gsc:878
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪getNoFlyZoneHeight
‪function getNoFlyZoneHeight(point)
Definition: _airsupport.gsc:352
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪debug_draw_bomb_explosion
‪function debug_draw_bomb_explosion(prevpos)
Definition: _airsupport.gsc:996
‪endSelectionOnGameEnd
‪function endSelectionOnGameEnd()
Definition: _airsupport.gsc:78
‪FlattenYaw
‪function FlattenYaw(goal)
Definition: _airsupport.gsc:862
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪_insideNoFlyZoneByIndex
‪function _insideNoFlyZoneByIndex(point, index, disregardHeight)
Definition: _airsupport.gsc:341
‪determineGroundPoint
‪function determineGroundPoint(player, position)
Definition: _airsupport.gsc:279
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪crossesNoFlyZones
‪function crossesNoFlyZones(start, end)
Definition: _airsupport.gsc:410
‪getPointOnLine
‪function getPointOnLine(startPoint, endPoint, ratio)
Definition: _airsupport.gsc:1219
‪entLOSRadiusDamage
‪function entLOSRadiusDamage(ent, pos, radius, max, min, owner, eInflictor)
Definition: _airsupport.gsc:697
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪GetRandomHelicopterStartOrigin
‪function GetRandomHelicopterStartOrigin()
Definition: _airsupport.gsc:945
‪MPH_TO_INCHES_PER_SEC
‪#define MPH_TO_INCHES_PER_SEC
Definition: shared.gsh:268
‪GetMaxMapWidth
‪function GetMaxMapWidth()
Definition: _airsupport.gsc:802
‪error
‪function error(msg)
Definition: _util.gsc:28
‪debug_airsupport_cylinder
‪function debug_airsupport_cylinder(origin, radius, height, color, mustRenderHeight, time)
Definition: _airsupport.gsc:1175
‪SwayRig
‪function SwayRig()
Definition: _airsupport.gsc:835
‪GetMapCenter
‪function GetMapCenter()
Definition: _airsupport.gsc:766
‪debug_print3d
‪function debug_print3d(message, color, ent, origin_offset, frames)
Definition: _airsupport.gsc:1078
‪closest_point_on_line
‪function closest_point_on_line(point, lineStart, lineEnd)
Definition: math_shared.gsc:491
‪canTargetPlayerWithSpecialty
‪function canTargetPlayerWithSpecialty()
Definition: _airsupport.gsc:1228
‪debug_cylinder
‪function debug_cylinder(origin, radius, height, color, mustRenderHeight, time)
Definition: _airsupport.gsc:1187
‪InitRotatingRig
‪function InitRotatingRig()
Definition: _airsupport.gsc:816
‪getMaxTargetHeight
‪function getMaxTargetHeight()
Definition: _airsupport.gsc:299
‪followPath
‪function followPath(path, doneNotify, stopAtGoal)
Definition: _airsupport.gsc:501
‪debug_draw_bomb_path
‪function debug_draw_bomb_path(projectile, color, time)
Definition: _airsupport.gsc:1008
‪getNoFlyZoneHeightCrossed
‪function getNoFlyZoneHeightCrossed(start, end, minHeight)
Definition: _airsupport.gsc:430
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪getStrikePath
‪function getStrikePath(target, height, halfDistance, yaw)
Definition: _airsupport.gsc:654
‪debug_plane_line
‪function debug_plane_line(flyTime, flyspeed, pathStart, pathEnd)
Definition: _airsupport.gsc:984
‪calculatePath_r
‪function calculatePath_r(start, end, points, startNoFlyZones, goalNoFlyZones, depth)
Definition: _airsupport.gsc:566
‪finishDualHardpointLocationUsage
‪function finishDualHardpointLocationUsage(locationStart, locationEnd, usedCallback)
Definition: _airsupport.gsc:71
‪getMinTargetHeight
‪function getMinTargetHeight()
Definition: _airsupport.gsc:294
‪increment
‪function increment(str_field_name, n_increment_count=1)
Definition: clientfield_shared.gsc:110
‪clearPath
‪function clearPath(start, end, startNoFlyZone, goalNoFlyZone)
Definition: _airsupport.gsc:543
‪planeStrike
‪function planeStrike(owner, requiredDeathCount, pathStart, pathEnd, bombTime, flyTime, flyspeed, bombSpeedScale, direction, planeSpawnedFunction)
Definition: _airsupport.gsc:245
‪setGoalPosition
‪function setGoalPosition(goal, doneNotify, stopAtGoal)
Definition: _airsupport.gsc:522
‪_insideCylinder
‪function _insideCylinder(point, base, radius, height)
Definition: _airsupport.gsc:322
‪debug_print3d_simple
‪function debug_print3d_simple(message, ent, offset, frames)
Definition: _airsupport.gsc:1038
‪debug_star
‪function debug_star(origin, color, time)
Definition: _airsupport.gsc:1113
‪StopRotation
‪function StopRotation(time)
Definition: _airsupport.gsc:855
‪getHeliPath
‪function getHeliPath(start, goal)
Definition: _airsupport.gsc:477
‪clearmonitoredspeed
‪function clearmonitoredspeed()
Definition: _airsupport.gsc:1285
‪crossesNoFlyZone
‪function crossesNoFlyZone(start, end)
Definition: _airsupport.gsc:391
‪RotateRig
‪function RotateRig()
Definition: _airsupport.gsc:826
‪stopLoopSoundAfterTime
‪function stopLoopSoundAfterTime(time)
Definition: _airsupport.gsc:137
‪calculateFallTime
‪function calculateFallTime(flyHeight)
Definition: _airsupport.gsc:145
‪_shouldIgnoreNoFlyZone
‪function _shouldIgnoreNoFlyZone(noFlyZone, noFlyZones)
Definition: _airsupport.gsc:448
‪GetRandomMapPoint
‪function GetRandomMapPoint(x_offset, y_offset, map_x_percentage, map_y_percentage)
Definition: _airsupport.gsc:777
‪_getStrikePathStartAndEnd
‪function _getStrikePathStartAndEnd(goal, yaw, halfDistance)
Definition: _airsupport.gsc:624
‪draw_text
‪function draw_text(msg, color, ent, offset, frames)
Definition: _airsupport.gsc:1053
‪calculateReleaseTime
‪function calculateReleaseTime(flyTime, flyHeight, flySpeed, bombSpeedScale)
Definition: _airsupport.gsc:155
‪append_array
‪function append_array(dst, src)
Definition: _airsupport.gsc:558
‪endSelectionOnHostMigration
‪function endSelectionOnHostMigration()
Definition: _airsupport.gsc:90
‪debug_line
‪function debug_line(from, to, color, time, depthTest)
Definition: _airsupport.gsc:1089
‪doGlassDamage
‪function doGlassDamage(pos, radius, max, min, mod)
Definition: _airsupport.gsc:691
‪endSelectionThink
‪function endSelectionThink()
Definition: _airsupport.gsc:102
‪determineTargetPoint
‪function determineTargetPoint(player, position)
Definition: _airsupport.gsc:287
‪Leave
‪function Leave(duration)
Definition: _airsupport.gsc:889
‪callStrike
‪function callStrike(flightPlan)
Definition: _airsupport.gsc:197
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265