‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
robot_phalanx.gsc
Go to the documentation of this file.
1 #using scripts\shared\ai_shared;
2 #using scripts\shared\math_shared;
3 #using scripts\shared\spawner_shared;
4 #using scripts\shared\ai\archetype_utility;
5 
6 #insert scripts\shared\shared.gsh;
7 #insert scripts\shared\ai\robot_phalanx.gsh;
8 
9 #namespace RobotPhalanx;
10 
11 function private ‪_AssignPhalanxStance( robots, stance )
12 {
13  assert( IsArray( robots ) );
14 
15  foreach ( index, robot in robots )
16  {
17  if ( IsDefined( robot) && IsAlive( robot ) )
18  {
19  robot ‪ai::set_behavior_attribute( "phalanx_force_stance", stance );
20  }
21  }
22 }
23 
24 function private ‪_CreatePhalanxTier(
25  phalanxType, tier, phalanxPosition, forward, maxTierSize, spawner = undefined )
26 {
27  robots = [];
28 
29  if ( !IsSpawner( spawner ) )
30  {
31  spawner = ‪_GetPhalanxSpawner( tier );
32  }
33 
34  positions = ‪_GetPhalanxPositions( phalanxType, tier );
35  angles = VectorToAngles( forward );
36 
37  foreach ( index, position in positions )
38  {
39  if ( index >= maxTierSize )
40  {
41  break;
42  }
43 
44  orientedPos = ‪_RotateVec( position, angles[1] - ‪PHALANX_ROTATION_OFFSET );
45 
46  navMeshPosition = GetClosestPointOnNavMesh(
47  phalanxPosition + orientedPos, ‪PHALANX_NAVMESH_TOLERANCE );
48 
49  // Make sure the spawner can actually spawn a robot.
50  if ( !( spawner.spawnflags & ‪SPAWNFLAG_ACTOR_SCRIPTINFINITESPAWN ) )
51  {
52  spawner.count++;
53  }
54 
55  robot = spawner ‪spawner::spawn( true, "", navMeshPosition, angles );
56 
57  if ( IsAlive( robot ) )
58  {
59  ‪_InitializeRobot( robot );
60 
61  // Wait till all robots have been created.
63 
64  robots[ robots.size ] = robot;
65  }
66  }
67 
68  return robots;
69 }
70 
71 // Caps the maximum damage the phalanx takes from a single explosive entity.
72 function private ‪_DampenExplosiveDamage(
73  inflictor, attacker, ‪damage, flags, meansOfDamage, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
74 {
75  entity = self;
76 
77  isExplosive = IsInArray(
78  ‪array(
79  "MOD_GRENADE",
80  "MOD_GRENADE_SPLASH",
81  "MOD_PROJECTILE",
82  "MOD_PROJECTILE_SPLASH",
83  "MOD_EXPLOSIVE" ),
84  meansOfDamage );
85 
86  if ( isExplosive && IsDefined( inflictor ) && IsDefined( inflictor.weapon ) )
87  {
88  weapon = inflictor.weapon;
89 
90  distanceToEntity = Distance( entity.origin, inflictor.origin );
91 
92  // Linear falloff from grenade distance.
93  fractionDistance = 1;
94 
95  if ( weapon.explosionradius > 0 )
96  {
97  fractionDistance = ( weapon.explosionradius - distanceToEntity ) / weapon.explosionradius;
98  }
99 
100  // This causes near exponential damage falloff since the original damage already considers radius at a near linear falloff.
101  return Int( Max( ‪damage * fractionDistance, 1 ) );
102  }
103 
104  return ‪damage;
105 }
106 
107 function private ‪_GetPhalanxPositions( phalanxType, tier )
108 {
109  switch ( phalanxType )
110  {
111  case ‪PHALANX_WEDGE:
112  switch( tier )
113  {
114  case ‪PHALANX_TIER_ONE:
116  case ‪PHALANX_TIER_TWO:
120  }
121  break;
123  switch( tier )
124  {
125  case ‪PHALANX_TIER_ONE:
127  case ‪PHALANX_TIER_TWO:
131  }
132  break;
134  switch( tier )
135  {
136  case ‪PHALANX_TIER_ONE:
138  case ‪PHALANX_TIER_TWO:
142  }
143  break;
144  case ‪PHALANX_FORWARD:
145  switch( tier )
146  {
147  case ‪PHALANX_TIER_ONE:
149  case ‪PHALANX_TIER_TWO:
153  }
154  break;
155  case ‪PHALANX_COLUMN:
156  switch( tier )
157  {
158  case ‪PHALANX_TIER_ONE:
160  case ‪PHALANX_TIER_TWO:
164  }
165  break;
167  switch( tier )
168  {
169  case ‪PHALANX_TIER_ONE:
171  case ‪PHALANX_TIER_TWO:
175  }
176  break;
177  default:
178  assert( "Unknown phalanx type \"" + phalanxType + "\"." );
179  }
180 
181  assert( "Unknown phalanx tier \"" + tier + "\"." );
182 }
183 
184 function private ‪_GetPhalanxSpawner( tier )
185 {
186  spawner = GetSpawnerArray( tier, "targetname" );
187 
188  assert( spawner.size >= 0,
189  "No spawners for the robot phalanx system were found, make sure you include " +
190  "the \"game/map_source/_prefabs/ai/robot_phalanx.map\" prefab within your " +
191  "map to use the system." );
192  assert( spawner.size == 1,
193  "Too many spawners for the robot phalanx system were found, make sure you " +
194  "don't include multiple copies of the " +
195  "\"game/map_source/_prefabs/ai/robot_phalanx.map\" prefab in your map." );
196 
197  return spawner[0];
198 }
199 
200 function private ‪_HaltAdvance( robots )
201 {
202  assert( IsArray( robots ) );
203 
204  foreach ( index, robot in robots )
205  {
206  if ( IsDefined( robot) && IsAlive( robot ) && robot HasPath() )
207  {
208  navMeshPosition = GetClosestPointOnNavMesh(
209  robot.origin, ‪PHALANX_NAVMESH_TOLERANCE );
210 
211  robot UsePosition( navMeshPosition );
212  robot ClearPath();
213  }
214  }
215 }
216 
217 function private ‪_HaltFire( robots )
218 {
219  assert( IsArray( robots ) );
220 
221  foreach ( index, robot in robots )
222  {
223  if ( IsDefined( robot) && IsAlive( robot ) )
224  {
225  robot.ignoreall = true;
226  }
227  }
228 }
229 
230 function private ‪_InitializeRobot( robot )
231 {
232  assert( IsActor( robot ) );
233 
234  robot ‪ai::set_behavior_attribute( "phalanx", true );
235  robot ‪ai::set_behavior_attribute( "move_mode", "marching" );
236  robot ‪ai::set_behavior_attribute( "force_cover", true );
237  // robot.allowPain = false;
238  robot SetAvoidanceMask( "avoid none" );
239 
241 }
242 
243 function private ‪_MovePhalanxTier( robots, phalanxType, tier, destination, forward )
244 {
245  positions = ‪_GetPhalanxPositions( phalanxType, tier );
246  angles = VectorToAngles( forward );
247 
248  assert( robots.size <= positions.size,
249  "There must be enough positions for the phalanx tier to move to." );
250 
251  foreach ( index, robot in robots )
252  {
253  if ( IsDefined( robot ) && IsAlive( robot ) )
254  {
255  assert( IsVec( positions[ index ] ),
256  "Must have a formation position for position(" + index + ") in tier " +
257  tier + " of formation " + phalanxType );
258 
259  orientedPos = ‪_RotateVec( positions[ index ], angles[1] - ‪PHALANX_ROTATION_OFFSET );
260 
261  navMeshPosition = GetClosestPointOnNavMesh(
262  destination + orientedPos, ‪PHALANX_NAVMESH_TOLERANCE );
263 
264  robot UsePosition( navMeshPosition );
265  }
266  }
267 }
268 
269 function private ‪_PruneDead( robots )
270 {
271  liveRobots = [];
272 
273  // Removes dead robots and keeps living ones with the same array index.
274  foreach ( index, robot in robots )
275  {
276  if ( IsDefined( robot ) && IsAlive( robot ) )
277  {
278  liveRobots[ index ] = robot;
279  }
280  }
281 
282  return liveRobots;
283 }
284 
285 function private ‪_ReleaseRobot( robot )
286 {
287  if ( IsDefined( robot ) && IsAlive( robot ) )
288  {
289  robot ClearUsePosition();
290  robot PathMode( "move delayed", true, RandomFloatRange( 0.5, 1 ) );
291 
292  robot ‪ai::set_behavior_attribute( "phalanx", false );
293 
294  // Wait a frame to make sure robot's are released from the phalanx.
296 
297  robot ‪ai::set_behavior_attribute( "move_mode", "normal" );
298  robot ‪ai::set_behavior_attribute( "force_cover", false );
299  // robot.allowPain = true;
300  robot SetAvoidanceMask( "avoid all" );
301 
303  }
304 }
305 
306 function private ‪_ReleaseRobots( robots )
307 {
308  foreach ( index, robot in robots )
309  {
310  ‪_ResumeFire( robot );
311  ‪_ReleaseRobot( robot );
312 
313  // Release robots slowly from their group.
314  wait RandomFloatRange( 0.5, 5 );
315  }
316 }
317 
318 function private ‪_ResumeFire( robot )
319 {
320  if ( IsDefined( robot) && IsAlive( robot ) )
321  {
322  robot.ignoreall = false;
323  }
324 }
325 
326 function private ‪_ResumeFireRobots( robots )
327 {
328  assert( IsArray( robots ) );
329 
330  foreach ( index, robot in robots )
331  {
332  ‪_ResumeFire( robot );
333  }
334 }
335 
336 function private ‪_RotateVec( vector, angle )
337 {
338  return ( vector[0] * Cos( angle ) - vector[1] * Sin( angle ),
339  vector[0] * Sin( angle ) + vector[1] * Cos( angle ),
340  vector[2] );
341 }
342 
343 function private ‪_UpdatePhalanxThread( phalanx )
344 {
345  while ( [[ phalanx ]]->_UpdatePhalanx() )
346  {
348  }
349 }
350 
352 {
353  // Directly manage each tier of robots.
357 
358  // Total starting robots in the formation.
360  // Current count of all robots in the formation.
362 
363  // Number of robots that must die for the formation to scatter.
365 
366  // Phalanx move positions
369 
370  // Phalanx type
372 
373  // Mark whether the formation has already been scattered.
375 
377  {
378  ‪tier1Robots_ = [];
379  ‪tier2Robots_ = [];
380  ‪tier3Robots_ = [];
381 
384  ‪breakingPoint_ = 0;
385 
386  ‪scattered_ = false;
387  }
388 
390  {
391  }
392 
393  function private ‪_UpdatePhalanx()
394  {
395  if ( ‪scattered_ )
396  {
397  // Terminate the phalanx if someone else has already scattered the formation.
398  return false;
399  }
400 
401  // Discard dead robots from the phalanx.
405 
407 
408  // Break up the phalanx if enough robots died.
410  {
412 
413  return false;
414  }
415 
416  return true;
417  }
418 
419  function ‪HaltFire()
420  {
424  }
425 
426  function ‪HaltAdvance()
427  {
428  if ( !‪scattered_ )
429  {
433  }
434  }
435 
436  function ‪Initialize(
437  phalanxType,
438  origin,
439  destination,
440  breakingPoint,
441  maxTierSize = ‪PHALANX_MAX_TIER_SIZE,
442  tierOneSpawner = undefined,
443  tierTwoSpawner = undefined,
444  tierThreeSpawner = undefined )
445  {
446  assert( IsString( phalanxType ) );
447  assert( IsInt( breakingPoint ) );
448  assert( IsVec( origin ) );
449  assert( IsVec( destination ) );
450 
452 
453  forward = VectorNormalize( destination - origin );
454 
456  phalanxType, ‪PHALANX_TIER_ONE, origin, forward, maxTierSize, tierOneSpawner );
458  phalanxType, ‪PHALANX_TIER_TWO, origin, forward, maxTierSize, tierTwoSpawner );
460  phalanxType, ‪PHALANX_TIER_THREE, origin, forward, maxTierSize, tierThreeSpawner );
461 
462  // The first tier facing the enemy always crouches.
464 
465  // Assign phalanx positions to all robot tiers.
467  ‪tier1Robots_, phalanxType, ‪PHALANX_TIER_ONE, destination, forward );
469  ‪tier2Robots_, phalanxType, ‪PHALANX_TIER_TWO, destination, forward );
471  ‪tier3Robots_, phalanxType, ‪PHALANX_TIER_THREE, destination, forward );
472 
474  ‪breakingPoint_ = breakingPoint;
475  ‪startPosition_ = origin;
476  ‪endPosition_ = destination;
477  ‪phalanxType_ = phalanxType;
478 
479  // Initiate the main update loop, a single thread that updates the phalanx.
480  self thread ‪RobotPhalanx::_UpdatePhalanxThread( self );
481  }
482 
483  function ‪ResumeAdvance()
484  {
485  if ( !‪scattered_ )
486  {
488 
489  // TODO(David Young 10-21-14): Too hardcoded, waiting for animation to complete.
490  wait 1;
491 
492  forward = VectorNormalize( ‪endPosition_ - ‪startPosition_ );
493 
500 
502  }
503  }
504 
505  function ‪ResumeFire()
506  {
510  }
511 
512  function ‪ScatterPhalanx()
513  {
514  if ( !‪scattered_ )
515  {
516  ‪scattered_ = true;
517 
519  ‪tier1Robots_ = [];
520 
522 
523  // Settling time for the tier.
524  wait RandomFloatRange( 5, 7 );
525 
527  ‪tier2Robots_ = [];
528 
530 
531  // Settling time for the tier.
532  wait RandomFloatRange( 5, 7 );
533 
535  ‪tier3Robots_ = [];
536  }
537  }
538 }
‪PHALANX_DIAGONAL_LEFT_TIER_THREE
‪#define PHALANX_DIAGONAL_LEFT_TIER_THREE
Definition: phalanx.gsh:70
‪_ReleaseRobots
‪function private _ReleaseRobots(robots)
Definition: robot_phalanx.gsc:306
‪RobotPhalanx::currentRobotCount_
‪var currentRobotCount_
Definition: robot_phalanx.gsc:361
‪RemoveAIOverrideDamageCallback
‪function RemoveAIOverrideDamageCallback(entity, callback)
Definition: archetype_utility.gsc:577
‪_ResumeFireRobots
‪function private _ResumeFireRobots(robots)
Definition: robot_phalanx.gsc:326
‪RobotPhalanx::scattered_
‪var scattered_
Definition: robot_phalanx.gsc:374
‪AddAIOverrideDamageCallback
‪function AddAIOverrideDamageCallback(entity, callback, addToFront)
Definition: archetype_utility.gsc:542
‪PHALANX_WEDGE_TIER_THREE
‪#define PHALANX_WEDGE_TIER_THREE
Definition: phalanx.gsh:47
‪_HaltAdvance
‪function private _HaltAdvance(robots)
Definition: robot_phalanx.gsc:200
‪PHALANX_FORWARD_TIER_THREE
‪#define PHALANX_FORWARD_TIER_THREE
Definition: phalanx.gsh:98
‪RobotPhalanx
Definition: robot_phalanx.gsc:351
‪PHALANX_NAVMESH_TOLERANCE
‪#define PHALANX_NAVMESH_TOLERANCE
Definition: phalanx.gsh:130
‪_RotateVec
‪function private _RotateVec(vector, angle)
Definition: robot_phalanx.gsc:336
‪PHALANX_WEDGE_TIER_ONE
‪#define PHALANX_WEDGE_TIER_ONE
Definition: phalanx.gsh:36
‪PHALANX_DIAGONAL_LEFT
‪#define PHALANX_DIAGONAL_LEFT
Definition: phalanx.gsh:11
‪PHALANX_DIAGONAL_RIGHT_TIER_THREE
‪#define PHALANX_DIAGONAL_RIGHT_TIER_THREE
Definition: phalanx.gsh:84
‪_InitializeRobot
‪function private _InitializeRobot(robot)
Definition: robot_phalanx.gsc:230
‪PHALANX_FORWARD_TIER_TWO
‪#define PHALANX_FORWARD_TIER_TWO
Definition: phalanx.gsh:92
‪_AssignPhalanxStance
‪function private _AssignPhalanxStance(robots, stance)
Definition: robot_phalanx.gsc:11
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪_MovePhalanxTier
‪function private _MovePhalanxTier(robots, phalanxType, tier, destination, forward)
Definition: robot_phalanx.gsc:243
‪_DampenExplosiveDamage
‪function private _DampenExplosiveDamage(inflictor, attacker, damage, flags, meansOfDamage, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex)
Definition: robot_phalanx.gsc:72
‪PHALANX_FORWARD
‪#define PHALANX_FORWARD
Definition: phalanx.gsh:9
‪PHALANX_DIAGONAL_LEFT_TIER_TWO
‪#define PHALANX_DIAGONAL_LEFT_TIER_TWO
Definition: phalanx.gsh:64
‪RobotPhalanx::HaltFire
‪function HaltFire()
Definition: robot_phalanx.gsc:419
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪RobotPhalanx::startPosition_
‪var startPosition_
Definition: robot_phalanx.gsc:367
‪PHALANX_DIAGONAL_RIGHT_TIER_TWO
‪#define PHALANX_DIAGONAL_RIGHT_TIER_TWO
Definition: phalanx.gsh:78
‪PHALANX_DIAGONAL_LEFT_TIER_ONE
‪#define PHALANX_DIAGONAL_LEFT_TIER_ONE
Definition: phalanx.gsh:58
‪PHALANX_ROTATION_OFFSET
‪#define PHALANX_ROTATION_OFFSET
Definition: phalanx.gsh:132
‪PHALANX_WEDGE_TIER_TWO
‪#define PHALANX_WEDGE_TIER_TWO
Definition: phalanx.gsh:43
‪RobotPhalanx::tier2Robots_
‪var tier2Robots_
Definition: robot_phalanx.gsc:355
‪PHALANX_DIAGONAL_RIGHT_TIER_ONE
‪#define PHALANX_DIAGONAL_RIGHT_TIER_ONE
Definition: phalanx.gsh:72
‪PHALANX_TIER_TWO
‪#define PHALANX_TIER_TWO
Definition: phalanx.gsh:22
‪PHALANX_DIAGONAL_RIGHT
‪#define PHALANX_DIAGONAL_RIGHT
Definition: phalanx.gsh:10
‪PHALANX_TIER_ONE
‪#define PHALANX_TIER_ONE
Definition: phalanx.gsh:21
‪RobotPhalanx::destructor
‪destructor()
Definition: robot_phalanx.gsc:389
‪RobotPhalanx::ScatterPhalanx
‪function ScatterPhalanx()
Definition: robot_phalanx.gsc:512
‪_UpdatePhalanxThread
‪function private _UpdatePhalanxThread(phalanx)
Definition: robot_phalanx.gsc:343
‪PHALANX_COLUMN_TIER_TWO
‪#define PHALANX_COLUMN_TIER_TWO
Definition: phalanx.gsh:106
‪RobotPhalanx::Initialize
‪function Initialize(phalanxType, origin, destination, breakingPoint, maxTierSize=PHALANX_MAX_TIER_SIZE, tierOneSpawner=undefined, tierTwoSpawner=undefined, tierThreeSpawner=undefined)
Definition: robot_phalanx.gsc:436
‪RobotPhalanx::_UpdatePhalanx
‪function private _UpdatePhalanx()
Definition: robot_phalanx.gsc:393
‪RobotPhalanx::HaltAdvance
‪function HaltAdvance()
Definition: robot_phalanx.gsc:426
‪_GetPhalanxSpawner
‪function private _GetPhalanxSpawner(tier)
Definition: robot_phalanx.gsc:184
‪_CreatePhalanxTier
‪function private _CreatePhalanxTier(phalanxType, tier, phalanxPosition, forward, maxTierSize, spawner=undefined)
Definition: robot_phalanx.gsc:24
‪array
‪function filter array
Definition: array_shared.csc:16
‪RobotPhalanx::breakingPoint_
‪var breakingPoint_
Definition: robot_phalanx.gsc:364
‪PHALANX_COLUMN_TIER_ONE
‪#define PHALANX_COLUMN_TIER_ONE
Definition: phalanx.gsh:100
‪_PruneDead
‪function private _PruneDead(robots)
Definition: robot_phalanx.gsc:269
‪RobotPhalanx::tier1Robots_
‪var tier1Robots_
Definition: robot_phalanx.gsc:354
‪PHALANX_COLUMN
‪#define PHALANX_COLUMN
Definition: phalanx.gsh:7
‪PHALANX_TIER_THREE
‪#define PHALANX_TIER_THREE
Definition: phalanx.gsh:23
‪PHALANX_COLUMN_RIGHT
‪#define PHALANX_COLUMN_RIGHT
Definition: phalanx.gsh:8
‪_GetPhalanxPositions
‪function private _GetPhalanxPositions(phalanxType, tier)
Definition: robot_phalanx.gsc:107
‪PHALANX_FORWARD_TIER_ONE
‪#define PHALANX_FORWARD_TIER_ONE
Definition: phalanx.gsh:86
‪RobotPhalanx::tier3Robots_
‪var tier3Robots_
Definition: robot_phalanx.gsc:356
‪RobotPhalanx::ResumeFire
‪function ResumeFire()
Definition: robot_phalanx.gsc:505
‪set_behavior_attribute
‪function set_behavior_attribute(attribute, value)
Definition: ai_shared.gsc:159
‪_ReleaseRobot
‪function private _ReleaseRobot(robot)
Definition: robot_phalanx.gsc:285
‪RobotPhalanx::ResumeAdvance
‪function ResumeAdvance()
Definition: robot_phalanx.gsc:483
‪_ResumeFire
‪function private _ResumeFire(robot)
Definition: robot_phalanx.gsc:318
‪PHALANX_MIN_TIER_SIZE
‪#define PHALANX_MIN_TIER_SIZE
Definition: phalanx.gsh:136
‪PHALANX_WEDGE
‪#define PHALANX_WEDGE
Definition: phalanx.gsh:13
‪RobotPhalanx::phalanxType_
‪var phalanxType_
Definition: robot_phalanx.gsc:371
‪clamp
‪function clamp(val, val_min, val_max)
Definition: math_shared.csc:16
‪PHALANX_COLUMN_RIGHT_TIER_TWO
‪#define PHALANX_COLUMN_RIGHT_TIER_TWO
Definition: phalanx.gsh:120
‪RobotPhalanx::startRobotCount_
‪var startRobotCount_
Definition: robot_phalanx.gsc:359
‪PHALANX_MAX_TIER_SIZE
‪#define PHALANX_MAX_TIER_SIZE
Definition: phalanx.gsh:134
‪_HaltFire
‪function private _HaltFire(robots)
Definition: robot_phalanx.gsc:217
‪PHALANX_COLUMN_RIGHT_TIER_THREE
‪#define PHALANX_COLUMN_RIGHT_TIER_THREE
Definition: phalanx.gsh:122
‪PHALANX_COLUMN_TIER_THREE
‪#define PHALANX_COLUMN_TIER_THREE
Definition: phalanx.gsh:112
‪RobotPhalanx::endPosition_
‪var endPosition_
Definition: robot_phalanx.gsc:368
‪RobotPhalanx::constructor
‪constructor()
Definition: robot_phalanx.gsc:376
‪PHALANX_COLUMN_RIGHT_TIER_ONE
‪#define PHALANX_COLUMN_RIGHT_TIER_ONE
Definition: phalanx.gsh:114
‪PHALANX_UPDATE_RATE_SEC
‪#define PHALANX_UPDATE_RATE_SEC
Definition: robot_phalanx.gsh:123
‪SPAWNFLAG_ACTOR_SCRIPTINFINITESPAWN
‪#define SPAWNFLAG_ACTOR_SCRIPTINFINITESPAWN
Definition: shared.gsh:54
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265