‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_planemortar.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\scoreevents_shared;
6 #using scripts\shared\util_shared;
7 
8 #using scripts\mp\_challenges;
9 #using scripts\mp\_util;
10 #using scripts\mp\gametypes\_battlechatter;
11 #using scripts\mp\gametypes\_globallogic_audio;
12 #using scripts\mp\gametypes\_spawning;
13 #using scripts\mp\killstreaks\_airsupport;
14 #using scripts\mp\killstreaks\_killstreakrules;
15 #using scripts\mp\killstreaks\_killstreaks;
16 #using scripts\mp\killstreaks\_satellite;
17 
18 #insert scripts\mp\_hacker_tool.gsh;
19 #insert scripts\shared\shared.gsh;
20 #insert scripts\shared\version.gsh;
21 
22 #define PLANE_MORTAR_MODEL "veh_t7_mil_vtol_fighter_mp"
23 #define PLANE_MORTAR_MODEL_ENEMY "veh_t7_mil_vtol_fighter_mp_dark"
24 #define PLANE_MORTAR_LOCATION_SELECTOR "map_mortar_selector"
25 #define PLANE_MORTAR_LOCATION_SELECTOR_DONE "map_mortar_selector_done"
26 #define PLANE_MORTAR_SELECTION_RADIUS 800
27 #define PLANE_MORTAR_AIM_ASSIST_RADIUS_SQ 250000
28 #define PLANE_MORTAR_SELECTION_COUNT 3
29 #define PLANE_MORTAR_DELAY 0.8
30 #define PLANE_WINGMAN_DELAY 0.15
31 #define PLANE_WINGMAN_OFFSET 500
32 #define PLANE_MORTAR_FLIGHT_RADIUS 12000
33 #define PLANE_MORTAR_FLIGHT_SPEED 12000
34 #define PLANE_MORTAR_FLIGHT_TIME ( PLANE_MORTAR_FLIGHT_RADIUS * 2 / PLANE_MORTAR_FLIGHT_SPEED )
35 
36 #precache( "locationselector", PLANE_MORTAR_LOCATION_SELECTOR );
37 #precache( "locationselector", PLANE_MORTAR_LOCATION_SELECTOR_DONE );
38 #precache( "string", "MP_EARNED_PLANEMORTAR" );
39 #precache( "string", "KILLSTREAK_PLANEMORTAR_NOT_AVAILABLE" );
40 #precache( "string", "MP_WAR_PLANEMORTAR_INBOUND" );
41 #precache( "string", "MP_WAR_PLANEMORTAR_INBOUND_NEAR_YOUR_POSITION" );
42 #precache( "string", "KILLSTREAK_PLANEMORTAR_HACKED" );
43 #precache( "eventstring", "mpl_killstreak_planemortar" );
44 #precache( "fx", "killstreaks/fx_ls_exhaust_afterburner" );
45 
46 #namespace planemortar;
47 
48 function ‪init()
49 {
50  level.planeMortarExhaustFX = "killstreaks/fx_ls_exhaust_afterburner";
51  ‪clientfield::register( "scriptmover", "planemortar_contrail", ‪VERSION_SHIP, 1, "int" );
52  ‪killstreaks::register( "planemortar", "planemortar", "killstreak_planemortar", "planemortar_used",&‪useKillstreakPlaneMortar, true );
53  ‪killstreaks::register_strings( "planemortar", &"MP_EARNED_PLANEMORTAR", &"KILLSTREAK_PLANEMORTAR_NOT_AVAILABLE", &"MP_WAR_PLANEMORTAR_INBOUND", &"MP_WAR_PLANEMORTAR_INBOUND_NEAR_YOUR_POSITION", &"KILLSTREAK_PLANEMORTAR_HACKED" );
54  ‪killstreaks::register_dialog( "planemortar", "mpl_killstreak_planemortar", "planeMortarDialogBundle", "planeMortarPilotDialogBundle", "friendlyPlaneMortar", "enemyPlaneMortar", "enemyPlaneMortarMultiple", "friendlyPlaneMortarHacked", "enemyPlaneMortarHacked", "requestPlaneMortar" );
55  ‪killstreaks::set_team_kill_penalty_scale( "planemortar", level.teamKillReducedPenalty );
56 }
57 
58 function ‪useKillstreakPlaneMortar( hardpointType )
59 {
60  if ( self ‪killstreakrules::isKillstreakAllowed( hardpointType, self.team ) == false )
61  {
62  return false;
63  }
64 
65  ‪result = self ‪selectPlaneMortarLocation( hardpointType );
66 
67  if ( !isdefined( ‪result ) || !‪result )
68  {
69  return false;
70  }
71 
72  return true;
73 }
74 
76 {
77  self endon( "emp_jammed" );
78  self endon( "emp_grenaded" );
79 
80  self waittill( "confirm_location", location );
81 
82  return location;
83 }
84 
85 function ‪selectPlaneMortarLocation( hardpointType )
86 {
88  self.selectingLocation = true;
89 
91 
92  locations = [];
93  if (!isdefined(self.pers["mortarRadarUsed"]) || !self.pers["mortarRadarUsed"])
94  {
95  self thread ‪singleRadarSweep();
96 
97  otherTeam = ‪util::getOtherTeam( self.team );
98  ‪globallogic_audio::leader_dialog( "enemyPlaneMortarUsed", otherTeam );
99  }
100 
101  for ( i = 0 ; i < ‪PLANE_MORTAR_SELECTION_COUNT ; i++ )
102  {
103  location = self ‪waittill_confirm_location();
104 
105  // if the player gets disconnected, self will be undefined
106  if( !isdefined( self ) )
107  return false;
108 
109  if ( !isdefined( location ) )
110  {
111  self.pers["mortarRadarUsed"] = true;
112  self notify("cancel_selection");
113  // selection was canceled
114  return false;
115  }
116 
117  locations[i] = location;
118  }
119 
120  if ( self ‪killstreakrules::isKillstreakAllowed( hardpointType, self.team ) == false)
121  {
122  self.pers["mortarRadarUsed"] = true;
123  self notify("cancel_selection");
124  return false;
125  }
126 
127  self.pers["mortarRadarUsed"] = false;
128 
130 }
131 
132 function ‪waitPlayBackTime( soundAlias )
133 {
134  self endon ( "death" );
135  self endon ( "disconnect" );
136 
137  playbackTime = soundgetplaybacktime ( soundAlias );
138 
139  if ( playbackTime >= 0 )
140  {
141  waitTime = playbackTime * .001;
142 
143  wait ( waitTime );
144  }
145  else
146  {
147  wait ( 1.0 );
148  }
149  self notify ( soundAlias );
150 }
151 
153 {
154  self endon( "disconnect" );
155  self endon("cancel_selection");
156 
157  // give a bit for the map to come up
158  wait(0.5);
159 
160  self PlayLocalSound("mpl_killstreak_satellite");
161 
162  if ( level.teamBased )
163  {
164  has_satellite = ‪satellite::HasSatellite( self.team );
165  }
166  else
167  {
168  has_satellite = ‪satellite::HasSatellite( self.entnum );
169  }
170 
171  if (self.hasSpyplane == 0 && !has_satellite && !level.forceRadar )
172  {
173  self thread ‪doRadarSweep();
174  }
175 }
176 
177 function ‪doRadarSweep()
178 {
179  self setClientUIVisibilityFlag( "g_compassShowEnemies", 1 );
180 
181  wait ( 0.2 );
182 
183  self setClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
184 }
185 
186 function ‪usePlaneMortar( positions )
187 {
188  team = self.team;
189  killstreak_id = self ‪killstreakrules::killstreakStart( "planemortar", team, false, true );
190  if ( killstreak_id == -1 )
191  {
192  return false;
193  }
194 
195  self ‪killstreaks::play_killstreak_start_dialog( "planemortar", team, killstreak_id );
196 
197  self.planeMortarPilotIndex = ‪killstreaks::get_random_pilot_index( "planemortar" );
198  self ‪killstreaks::play_pilot_dialog( "arrive", "planemortar", undefined, self.planeMortarPilotIndex );
199 
200  self AddWeaponStat( GetWeapon( "planemortar" ), "used", 1 );
201  self thread ‪planeMortar_watchForEndNotify( team, killstreak_id );
202  self thread ‪doPlaneMortar( positions, team, killstreak_id );
203 
204  return true;
205 }
206 
207 function ‪doPlaneMortar( positions, team, killstreak_id )
208 {
209  self endon( "emp_jammed" );
210  self endon( "disconnect" );
211 
212  yaw = RandomIntRange( 0,360 );
213  odd = 0;
214  wait ( 1.25 );
215  foreach( position in positions )
216  {
217  level ‪spawning::create_enemy_influencer( "artillery", position, team );
218  self thread ‪doBombRun( position, yaw, team );
219 
220  if (odd == 0)
221  {
222  yaw = ( yaw + 35 ) % 360;
223  }
224  else
225  {
226  yaw = ( yaw + 290 ) % 360;
227  }
228  odd = ( odd + 1 ) % 2;
229 
231  }
232 
233  self notify( "planemortarcomplete" );
234  wait ( 1 );
235  self thread ‪plane_mortar_bda_dialog();
236 }
237 
239 {
240  if ( isdefined( self.planeMortarBda ) )
241  {
242  if (self.planeMortarBda === 1)
243  {
244  bdaDialog = "kill1";
245  }
246  else if (self.planeMortarBda === 2)
247  {
248  bdaDialog = "kill2";
249  }
250  else if (self.planeMortarBda === 3)
251  {
252  bdaDialog = "kill3";
253  }
254  else if (isdefined( self.planeMortarBda ) && self.planeMortarBda > 3)
255  {
256  bdaDialog = "killMultiple";
257  }
258 
259  self ‪killstreaks::play_pilot_dialog( bdaDialog, "planemortar", undefined, self.planeMortarPilotIndex );
260 
261  if ( ‪battlechatter::dialog_chance( "taacomPilotKillConfirmChance" ) )
262  {
263  self ‪killstreaks::play_taacom_dialog_response( "killConfirmed", "planemortar", undefined, self.planeMortarPilotIndex );
264  }
265  else
266  {
267  self ‪globallogic_audio::play_taacom_dialog( "confirmHit" );
268  }
269  }
270  else
271  {
272  ‪killstreaks::play_pilot_dialog( "killNone", "planemortar", undefined, self.planeMortarPilotIndex );
274  }
275 
276  self.planeMortarBda = undefined;
277 }
278 
279 function ‪planeMortar_watchForEndNotify( team, killstreak_id )
280 {
281  self ‪util::waittill_any( "disconnect", "joined_team", "joined_spectators", "planemortarcomplete", "emp_jammed" );
282 
283  ‪planeMortar_killstreakStop( team, killstreak_id );
284 }
285 
286 function ‪planeMortar_killstreakStop( team, killstreak_id )
287 {
288  ‪killstreakrules::killstreakStop( "planemortar", team, killstreak_id );
289 }
290 
291 
292 function ‪doBombRun( position, yaw, team )
293 {
294  self endon( "emp_jammed" );
295  player = self;
296 
297  angles = (0,yaw,0);
298  direction = AnglesToForward( angles );
299 
300  height = ‪airsupport::getMinimumFlyHeight() + 2000;
301  position = ( position[0], position[1], height );
302  startPoint = position + VectorScale( direction, -1 * ‪PLANE_MORTAR_FLIGHT_RADIUS );
303  endPoint = position + VectorScale( direction, ‪PLANE_MORTAR_FLIGHT_RADIUS * 1.5 );
304  height = ‪airsupport::getNoFlyZoneHeightCrossed( startPoint, endPoint, height );
305  startPoint = ( startPoint[0], startPoint[1], height );
306  position = ( position[0], position[1], height );
307  endPoint = ( endPoint[0], endPoint[1], height );
308 
309  plane = SpawnPlane( self, "script_model", startPoint );
310  plane.team = team;
311  plane.targetname = "plane_mortar";
312  plane.owner = self;
313 
314  plane endon( "delete" );
315  plane endon( "death" );
316 
317  plane thread ‪planeWatchForEmp( self );
318 
319  plane.angles = angles;
320  plane SetModel( ‪PLANE_MORTAR_MODEL );
321  plane SetEnemyModel( ‪PLANE_MORTAR_MODEL_ENEMY );
322  plane ‪clientfield::set( "planemortar_contrail", 1 );
323  plane ‪clientfield::set( "enemyvehicle", ‪ENEMY_VEHICLE_ACTIVE );
324  plane playsound( "mpl_lightning_flyover_boom" );
325  plane SetDrawInfrared( true );
326 
327  plane.killcamEnt = ‪spawn( "script_model", plane.origin+(0,0,700)+VectorScale( direction, -1 * 1500 ) );
329  plane.killcamEnt.angles = (15,yaw,0);
330  plane.killcamEnt.startTime = gettime();
331  plane.killcamEnt LinkTo( plane );
332  start = (position[0], position[1], plane.origin[2]);
333  impact = BulletTrace( start, start + (0,0,-100000), true, plane);
334 
335  plane MoveTo( endpoint, ‪PLANE_MORTAR_FLIGHT_TIME * 5/4, 0, 0 );
336 
337  plane.killcamEnt thread ‪followBomb( plane, position, direction, impact, player );
338 
339  wait ( ‪PLANE_MORTAR_FLIGHT_TIME /2 );
340  if ( isdefined ( self ) )
341  {
342  self thread ‪dropBomb( plane, position );
343  }
344 
345  wait ( ‪PLANE_MORTAR_FLIGHT_TIME * 3/4 );
346  plane ‪Plane_CleanUpOnDeath();
347 }
348 
349 function ‪followBomb( plane, position, direction, impact, player )
350 {
351  player endon( "emp_jammed" );
352 
353  wait ( ‪PLANE_MORTAR_FLIGHT_TIME * 5 / 12 );
354  plane.killcamEnt Unlink();
355  plane.killcamEnt MoveTo( impact["position"] + (0,0,1000) + VectorScale( direction, -1 * 600 ), 0.8, 0, 0.2);
356 }
357 
358 function ‪lookAtExplosion( bomb )
359 {
360  while (isdefined(self) && isdefined( bomb ))
361  {
362  angles = vectorToAngles( VectorNormalize( bomb.origin - self.origin ));
363  self.angles = ( max(angles[0], 15), angles[1], angles[2] );
365  }
366 }
367 
368 function ‪planeWatchForEmp( owner )
369 {
370  self endon( "delete" );
371  self endon( "death" );
372 
373  self waittill( "emp_deployed", attacker );
374 
375  thread ‪planeAwardScoreEvent( attacker, self );
376 
377  // possibly play destroyed effect
379 }
380 
381 
382 function ‪planeAwardScoreEvent( attacker, plane )
383 {
384  attacker endon( "disconnect" );
385  attacker notify( "planeAwardScoreEvent_singleton" );
386  attacker endon( "planeAwardScoreEvent_singleton" );
387  waittillframeend;
388 
389 
390  if( isdefined( attacker ) && ( !isdefined( plane.owner ) || plane.owner ‪util::IsEnemyPlayer( attacker ) ) )
391  {
392  ‪challenges::destroyedAircraft( attacker, GetWeapon( "emp" ), false );
393  ‪scoreevents::processScoreEvent( "destroyed_plane_mortar", attacker, plane.owner, GetWeapon( "emp" ) );
394  attacker ‪challenges::addFlySwatterStat( GetWeapon( "emp" ), plane );
395  }
396 }
397 
399 {
400  self Delete();
401 }
402 
403 
404 function ‪dropBomb( plane, bombPosition )
405 {
406  if ( !isdefined( plane.owner ) )
407  return;
408 
409  targets = getplayers();
410  foreach( target in targets )
411  {
412  if( plane.owner ‪util::IsEnemyPlayer(target) && Distance2DSquared( target.origin, bombPosition ) < ‪PLANE_MORTAR_AIM_ASSIST_RADIUS_SQ )
413  {
414  if( BulletTracePassed( (target.origin[0], target.origin[1], plane.origin[2]), target.origin, false, plane) )
415  {
416  bombPosition = target.origin;
417  break;
418  }
419  }
420  }
421 
422  bombPosition = (bombPosition[0],bombPosition[1],plane.origin[2]);
423  bomb = self LaunchBomb( GetWeapon( "planemortar" ), bombPosition, (0,0,-5000) );
424  bomb.soundmod = "heli";
425  bomb playsound( "mpl_lightning_bomb_incoming" );
426  bomb.killcamEnt = plane.killcamEnt;
427  plane.killcamEnt thread ‪lookAtExplosion( bomb );
428 }
‪dialog_chance
‪function dialog_chance(chanceKey)
Definition: _battlechatter.gsc:237
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪doBombRun
‪function doBombRun(position, yaw, team)
Definition: _planemortar.gsc:292
‪waitPlayBackTime
‪function waitPlayBackTime(soundAlias)
Definition: _planemortar.gsc:132
‪create_enemy_influencer
‪function create_enemy_influencer(name, origin, team)
Definition: _spawning.gsc:285
‪planeWatchForEmp
‪function planeWatchForEmp(owner)
Definition: _planemortar.gsc:368
‪finishHardpointLocationUsage
‪function finishHardpointLocationUsage(location, usedCallback)
Definition: _airsupport.gsc:58
‪plane_mortar_bda_dialog
‪function plane_mortar_bda_dialog()
Definition: _planemortar.gsc:238
‪getMinimumFlyHeight
‪function getMinimumFlyHeight()
Definition: _airsupport.gsc:167
‪planeMortar_watchForEndNotify
‪function planeMortar_watchForEndNotify(team, killstreak_id)
Definition: _planemortar.gsc:279
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪dropBomb
‪function dropBomb(plane, bombPosition)
Definition: _planemortar.gsc:404
‪play_killstreak_start_dialog
‪function play_killstreak_start_dialog(killstreakType, team, killstreakId)
Definition: _killstreaks.gsc:1905
‪deleteAfterTime
‪function deleteAfterTime(time)
Definition: util_shared.gsc:2710
‪play_taacom_dialog_response
‪function play_taacom_dialog_response(dialogKey, killstreakType, killstreakId, pilotIndex)
Definition: _killstreaks.gsc:2052
‪addFlySwatterStat
‪function addFlySwatterStat(weapon, aircraft)
Definition: challenges_shared.gsc:86
‪ENEMY_VEHICLE_ACTIVE
‪#define ENEMY_VEHICLE_ACTIVE
Definition: _hacker_tool.gsh:2
‪init
‪function init()
Definition: _planemortar.gsc:48
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪PLANE_MORTAR_FLIGHT_RADIUS
‪#define PLANE_MORTAR_FLIGHT_RADIUS
Definition: _planemortar.gsc:32
‪play_pilot_dialog
‪function play_pilot_dialog(dialogKey, killstreakType, killstreakId, pilotIndex)
Definition: _killstreaks.gsc:2024
‪getOtherTeam
‪function getOtherTeam(team)
Definition: _util.gsc:360
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪followBomb
‪function followBomb(plane, position, direction, impact, player)
Definition: _planemortar.gsc:349
‪doPlaneMortar
‪function doPlaneMortar(positions, team, killstreak_id)
Definition: _planemortar.gsc:207
‪PLANE_MORTAR_MODEL_ENEMY
‪#define PLANE_MORTAR_MODEL_ENEMY
Definition: _planemortar.gsc:23
‪destroyedAircraft
‪function destroyedAircraft(attacker, weapon, playerControlled)
Definition: challenges_shared.gsc:1405
‪planeAwardScoreEvent
‪function planeAwardScoreEvent(attacker, plane)
Definition: _planemortar.gsc:382
‪PLANE_MORTAR_LOCATION_SELECTOR
‪#define PLANE_MORTAR_LOCATION_SELECTOR
Definition: _planemortar.gsc:24
‪PLANE_MORTAR_DELAY
‪#define PLANE_MORTAR_DELAY
Definition: _planemortar.gsc:29
‪PLANE_MORTAR_LOCATION_SELECTOR_DONE
‪#define PLANE_MORTAR_LOCATION_SELECTOR_DONE
Definition: _planemortar.gsc:25
‪doRadarSweep
‪function doRadarSweep()
Definition: _planemortar.gsc:177
‪isKillstreakAllowed
‪function isKillstreakAllowed(hardpointType, team)
Definition: _killstreakrules.gsc:352
‪set_team_kill_penalty_scale
‪function set_team_kill_penalty_scale(killstreakType, scale, isInventory)
Definition: _killstreaks.gsc:404
‪getNoFlyZoneHeightCrossed
‪function getNoFlyZoneHeightCrossed(start, end, minHeight)
Definition: _airsupport.gsc:430
‪get_random_pilot_index
‪function get_random_pilot_index(killstreakType)
Definition: _killstreaks.gsc:2067
‪HasSatellite
‪function HasSatellite(team_or_entnum)
Definition: _satellite.gsc:259
‪PLANE_MORTAR_FLIGHT_TIME
‪#define PLANE_MORTAR_FLIGHT_TIME
Definition: _planemortar.gsc:34
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪singleRadarSweep
‪function singleRadarSweep()
Definition: _planemortar.gsc:152
‪waittill_confirm_location
‪function waittill_confirm_location()
Definition: _planemortar.gsc:75
‪register_dialog
‪function register_dialog(killstreakType, informDialog, taacomDialogBundleKey, pilotDialogArrayKey, startDialogKey, enemyStartDialogKey, enemyStartMultipleDialogKey, hackedDialogKey, hackedStartDialogKey, requestDialogKey, threatDialogKey, isInventory)
Definition: _killstreaks.gsc:239
‪usePlaneMortar
‪function usePlaneMortar(positions)
Definition: _planemortar.gsc:186
‪PLANE_MORTAR_AIM_ASSIST_RADIUS_SQ
‪#define PLANE_MORTAR_AIM_ASSIST_RADIUS_SQ
Definition: _planemortar.gsc:27
‪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
‪PLANE_MORTAR_MODEL
‪#define PLANE_MORTAR_MODEL
Definition: _planemortar.gsc:22
‪killstreakStart
‪function killstreakStart(hardpointType, team, hacked, displayTeamMessage)
Definition: _killstreakrules.gsc:184
‪useKillstreakPlaneMortar
‪function useKillstreakPlaneMortar(hardpointType)
Definition: _planemortar.gsc:58
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪leader_dialog
‪function leader_dialog(dialogKey, team, excludeList, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:435
‪PLANE_MORTAR_SELECTION_RADIUS
‪#define PLANE_MORTAR_SELECTION_RADIUS
Definition: _planemortar.gsc:26
‪lookAtExplosion
‪function lookAtExplosion(bomb)
Definition: _planemortar.gsc:358
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪play_taacom_dialog
‪function play_taacom_dialog(dialogKey, killstreakType, killstreakId)
Definition: _globallogic_audio.gsc:274
‪Plane_CleanUpOnDeath
‪function Plane_CleanUpOnDeath()
Definition: _planemortar.gsc:398
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪endSelectionThink
‪function endSelectionThink()
Definition: _airsupport.gsc:102
‪planeMortar_killstreakStop
‪function planeMortar_killstreakStop(team, killstreak_id)
Definition: _planemortar.gsc:286
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪selectPlaneMortarLocation
‪function selectPlaneMortarLocation(hardpointType)
Definition: _planemortar.gsc:85
‪PLANE_MORTAR_SELECTION_COUNT
‪#define PLANE_MORTAR_SELECTION_COUNT
Definition: _planemortar.gsc:28