‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
archetype_utility.gsc
Go to the documentation of this file.
1 #using scripts\shared\ai_shared;
2 #using scripts\shared\ai\systems\ai_interface;
3 #using scripts\shared\ai\systems\animation_state_machine_utility;
4 #using scripts\shared\ai\systems\behavior_state_machine;
5 #using scripts\shared\ai\systems\behavior_tree_utility;
6 #using scripts\shared\ai\systems\blackboard;
7 #using scripts\shared\ai\systems\shared;
8 #using scripts\shared\ai\archetype_utility;
9 #using scripts\shared\array_shared;
10 #using scripts\shared\util_shared;
11 
12 //AI VS AI MELEE BEHAVIOR
13 #using scripts\shared\ai\archetype_aivsaimelee;
14 
15 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
16 #insert scripts\shared\ai\systems\behavior.gsh;
17 #insert scripts\shared\ai\systems\behavior_state_machine.gsh;
18 #insert scripts\shared\ai\systems\behavior_tree.gsh;
19 #insert scripts\shared\ai\systems\blackboard.gsh;
20 #insert scripts\shared\ai\utility.gsh;
21 #insert scripts\shared\shared.gsh;
22 
23 #define ARCHETYPE_VEHICLE_RAPS "raps"
24 
25 #precache( "fx", "lensflares/fx_lensflare_sniper_glint" );
26 
27 #namespace AiUtility;
28 
30 {
31  ‪BT_REGISTER_API("forceRagdoll", &‪forceRagdoll);
32  ‪BT_REGISTER_API("hasAmmo", &‪hasAmmo);
33  ‪BT_REGISTER_API("hasLowAmmo", &‪hasLowAmmo);
34  ‪BT_REGISTER_API("hasEnemy", &‪hasEnemy);
35  ‪BT_REGISTER_API("isSafeFromGrenades", &‪isSafeFromGrenades);
36  ‪BT_REGISTER_API("inGrenadeBlastRadius", &‪inGrenadeBlastRadius);
37  ‪BT_REGISTER_API("recentlySawEnemy", &‪recentlySawEnemy);
38  ‪BT_REGISTER_API("shouldBeAggressive", &‪shouldBeAggressive);
39  ‪BT_REGISTER_API("shouldOnlyFireAccurately", &‪shouldOnlyFireAccurately);
40 
41  ‪BT_REGISTER_API("shouldReactToNewEnemy", &‪shouldReactToNewEnemy);
42  ‪BSM_REGISTER_CONDITION("shouldReactToNewEnemy", &‪shouldReactToNewEnemy);
43 
44  ‪BT_REGISTER_API("hasWeaponMalfunctioned", &‪hasWeaponMalfunctioned);
45 
46  ‪BT_REGISTER_API("shouldStopMoving", &‪shouldStopMoving);
47  ‪BSM_REGISTER_CONDITION("shouldStopMoving", &‪shouldStopMoving);
48 
49  ‪BT_REGISTER_API("chooseBestCoverNodeASAP", &‪chooseBestCoverNodeASAP);
50  ‪BT_REGISTER_API("chooseBetterCoverService", &‪chooseBetterCoverServiceCodeVersion);
51  ‪BT_REGISTER_API("trackCoverParamsService", &‪trackCoverParamsService);
52  ‪BT_REGISTER_API("refillAmmoIfNeededService", &‪refillAmmo);
53  ‪BT_REGISTER_API("tryStoppingService", &‪tryStoppingService);
54  ‪BT_REGISTER_API("isFrustrated", &‪isFrustrated);
55  ‪BT_REGISTER_API("updatefrustrationLevel", &‪updateFrustrationLevel);
56  ‪BT_REGISTER_API("isLastKnownEnemyPositionApproachable", &‪isLastKnownEnemyPositionApproachable);
57  ‪BT_REGISTER_API("tryAdvancingOnLastKnownPositionBehavior", &‪tryAdvancingOnLastKnownPositionBehavior);
58  ‪BT_REGISTER_API("tryGoingToClosestNodeToEnemyBehavior", &‪tryGoingToClosestNodeToEnemyBehavior);
59  ‪BT_REGISTER_API("tryRunningDirectlyToEnemyBehavior", &‪tryRunningDirectlyToEnemyBehavior);
60  ‪BT_REGISTER_API("flagEnemyUnAttackableService", &‪flagEnemyUnAttackableService);
61 
62  ‪BT_REGISTER_API("keepClaimNode", &‪keepClaimNode);
63  ‪BSM_REGISTER_API("keepClaimNode", &‪keepClaimNode);
64 
65  ‪BT_REGISTER_API("releaseClaimNode", &‪releaseClaimNode);
66  ‪BT_REGISTER_API("startRagdoll", &‪scriptStartRagdoll);
67  ‪BT_REGISTER_API("notStandingCondition", &‪notStandingCondition );
68  ‪BT_REGISTER_API("notCrouchingCondition", &‪notCrouchingCondition );
69  ‪BT_REGISTER_API("explosiveKilled", &‪explosiveKilled );
70  ‪BT_REGISTER_API("electrifiedKilled", &‪electrifiedKilled );
71  ‪BT_REGISTER_API("burnedKilled", &‪burnedKilled );
72  ‪BT_REGISTER_API("rapsKilled", &‪rapsKilled );
73  ‪BT_REGISTER_API( "meleeAcquireMutex", &‪meleeAcquireMutex );
74  ‪BT_REGISTER_API( "meleeReleaseMutex", &‪meleeReleaseMutex );
75  ‪BT_REGISTER_API( "shouldMutexMelee", &‪shouldMutexMelee );
76  ‪BT_REGISTER_API( "prepareForExposedMelee", &‪prepareForExposedMelee );
77  ‪BT_REGISTER_API( "cleanupMelee", &‪cleanupMelee );
78  ‪BT_REGISTER_API( "shouldNormalMelee", &‪shouldNormalMelee );
79 
80  ‪BT_REGISTER_API( "shouldMelee", &‪shouldMelee );
81  ‪BSM_REGISTER_CONDITION( "shouldMelee", &‪shouldMelee );
82 
83  ‪BT_REGISTER_API( "hasCloseEnemyMelee", &‪hasCloseEnemyToMelee );
84  ‪BT_REGISTER_API( "isBalconyDeath", &‪isBalconyDeath );
85  ‪BT_REGISTER_API( "balconyDeath", &‪balconyDeath );
86  ‪BT_REGISTER_API( "useCurrentPosition", &‪useCurrentPosition );
87  ‪BT_REGISTER_API( "isUnarmed", &‪isUnarmed );
88 
89  // ------- CHARGE MELEE -----------//
90  ‪BT_REGISTER_API( "shouldChargeMelee", &‪shouldChargeMelee );
91  ‪BT_REGISTER_API( "shouldAttackInChargeMelee", &‪shouldAttackInChargeMelee );
92  ‪BT_REGISTER_API( "cleanupChargeMelee", &‪cleanupChargeMelee );
93  ‪BT_REGISTER_API( "cleanupChargeMeleeAttack", &‪cleanupChargeMeleeAttack );
94  ‪BT_REGISTER_API( "setupChargeMeleeAttack", &‪setupChargeMeleeAttack );
95 
96  // ------- SPECIAL PAIN -----------//
97  ‪BT_REGISTER_API( "shouldChooseSpecialPain", &‪shouldChooseSpecialPain );
98  ‪BT_REGISTER_API( "shouldChooseSpecialPronePain", &‪shouldChooseSpecialPronePain );
99 
100 
101  // ------- SPECIAL DEATH -----------//
102  ‪BT_REGISTER_API( "shouldChooseSpecialDeath", &‪shouldChooseSpecialDeath );
103  ‪BT_REGISTER_API( "shouldChooseSpecialProneDeath", &‪shouldChooseSpecialProneDeath );
104  ‪BT_REGISTER_API( "setupExplosionAnimScale", &‪setupExplosionAnimScale );
105 
106  // ------- STEALTH -----------//
107  ‪BT_REGISTER_API( "shouldStealth", &‪shouldStealth );
108  ‪BT_REGISTER_API( "stealthReactCondition", &‪stealthReactCondition );
109  ‪BT_REGISTER_API( "locomotionShouldStealth", &‪locomotionShouldStealth );
110  ‪BT_REGISTER_API( "shouldStealthResume", &‪shouldStealthResume );
111  ‪BSM_REGISTER_CONDITION( "locomotionShouldStealth", &‪locomotionShouldStealth );
112  ‪BSM_REGISTER_CONDITION( "stealthReactCondition", &‪stealthReactCondition );
113  ‪BT_REGISTER_API( "stealthReactStart", &‪stealthReactStart );
114  ‪BT_REGISTER_API( "stealthReactTerminate", &‪stealthReactTerminate );
115  ‪BT_REGISTER_API( "stealthIdleTerminate", &‪stealthIdleTerminate );
116 
117  // ------- PHALANX -----------//
118  ‪BT_REGISTER_API( "isInPhalanx", &‪isInPhalanx );
119  ‪BT_REGISTER_API( "isInPhalanxStance", &‪isInPhalanxStance );
120  ‪BT_REGISTER_API( "togglePhalanxStance", &‪togglePhalanxStance );
121 
122  // ------- FLASHBANG -----------//
123  ‪BT_REGISTER_API( "tookFlashbangDamage", &‪tookFlashbangDamage );
124 
125  // ------- ATTACKABLES ---------//
126  ‪BT_REGISTER_API( "isAtAttackObject", &‪isAtAttackObject );
127  ‪BT_REGISTER_API( "shouldAttackObject", &‪shouldAttackObject );
128 
129  // DEFAULT ACTIONS
130  ‪BT_REGISTER_ACTION_SIMPLE( "defaultAction" );
131 
132  //AI vs AI MELEE BEHAVIOR
134 }
135 
136 // ------- UTILITY BLACKBOARD -----------//
137 
138 // Has to be called from the any archetype who wants to use the utility blackboard
139 function ‪RegisterUtilityBlackboardAttributes() // has to be called on AI
140 {
141  ‪BB_REGISTER_ATTRIBUTE( ‪ARRIVAL_STANCE, undefined, &BB_GetArrivalStance );
142  ‪BB_REGISTER_ATTRIBUTE( ‪CONTEXT, undefined, undefined );
143  ‪BB_REGISTER_ATTRIBUTE( ‪CONTEXT_2, undefined, undefined );
149  ‪BB_REGISTER_ATTRIBUTE( ‪EXPOSED_TYPE, undefined, &BB_GetCurrentExposedType );
161  ‪BB_REGISTER_ATTRIBUTE( ‪FIRE_MODE, undefined, &GetFireMode);
162  ‪BB_REGISTER_ATTRIBUTE( ‪GIB_LOCATION, undefined, undefined );
163  ‪BB_REGISTER_ATTRIBUTE( ‪JUKE_DIRECTION, undefined, undefined );
164  ‪BB_REGISTER_ATTRIBUTE( ‪JUKE_DISTANCE, undefined, undefined );
165  ‪BB_REGISTER_ATTRIBUTE( ‪LOCOMOTION_ARRIVAL_DISTANCE, undefined, &BB_GetLocomotionArrivalDistance );
166  ‪BB_REGISTER_ATTRIBUTE( ‪LOCOMOTION_ARRIVAL_YAW, undefined, &BB_GetLocomotionArrivalYaw );
169  ‪BB_REGISTER_ATTRIBUTE( ‪LOCOMOTION_MOTION_ANGLE, undefined, &BB_GetLocomotionMotionAngle );
172  ‪BB_REGISTER_ATTRIBUTE( ‪LOCOMOTION_TURN_YAW, undefined, &BB_GetLocomotionTurnYaw );
180  ‪BB_REGISTER_ATTRIBUTE( ‪TRAVERSAL_TYPE, undefined, undefined );
181  ‪BB_REGISTER_ATTRIBUTE( ‪MELEE_DISTANCE, undefined, undefined );
184  ‪BB_REGISTER_ATTRIBUTE( ‪THROW_DISTANCE, undefined, undefined );
189  ‪BB_REGISTER_ATTRIBUTE( ‪MELEE_ENEMY_TYPE, undefined, undefined );
190 
193  ‪BB_REGISTER_ATTRIBUTE( ‪STAIRCASE_STATE, undefined, undefined );
194  ‪BB_REGISTER_ATTRIBUTE( ‪STAIRCASE_DIRECTION, undefined, undefined );
195  ‪BB_REGISTER_ATTRIBUTE( ‪STAIRCASE_EXIT_TYPE, undefined, undefined );
197 
198  // ENABLE DEBUGGING IN ODYSSEY
200 }
201 
202 function private ‪BB_GetStairsNumSkipSteps()
203 {
204  assert( IsDefined( self._stairsStartNode ) && IsDefined( self._stairsEndNode ) );
205 
208 
210 
211  numOutSteps = 2;
212  totalStepsWithoutOut = numTotalSteps - numOutSteps;
213 
214  assert( stepsSoFar < ( totalStepsWithoutOut ) );
215 
216  remainingSteps = totalStepsWithoutOut - stepsSoFar;
217 
218  // Try 8 steps first
219  if( remainingSteps >= 8 )
220  {
221  return ‪STAIR_SKIP_8;
222  }
223  else if( remainingSteps >= 6 )
224  {
225  return ‪STAIR_SKIP_6;
226  }
227 
228  assert( remainingSteps >= 3 );
229  return ‪STAIR_SKIP_3;
230 }
231 
232 function private ‪BB_GetAwareness()
233 {
234  // Awareness is always "combat" unless this agent is in stealth mode
235  if( !isDefined( self.stealth ) || !IsDefined( self.awarenesslevelcurrent ) )
236  return "combat";
237 
238  return self.awarenesslevelcurrent;
239 }
240 
241 function private ‪BB_GetAwarenessPrevious()
242 {
243  // Awareness is always "combat" unless this agent is in stealth mode
244  if( !isDefined( self.stealth ) || !IsDefined( self.awarenesslevelprevious ) )
245  return "combat";
246 
247  return self.awarenesslevelprevious;
248 }
249 
250 #define NEAR_COVER_NODE_SQ SQR( 24 )
251 #define NEAR_COVER_NODE_WIDE_SQ SQR( 64 )
252 function private ‪BB_GetYawToCoverNode()
253 {
254  if( !IsDefined( self.node ) )
255  {
256  return 0;
257  }
258 
259  distToNodeSqr = Distance2DSquared( self GetNodeOffsetPosition( self.node ), self.origin );
260 
261  if ( ‪IS_TRUE( self.keepClaimedNode ) )
262  {
263  if ( distToNodeSqr > ‪NEAR_COVER_NODE_WIDE_SQ )
264  {
265  return 0;
266  }
267  }
268  else if ( distToNodeSqr > ‪NEAR_COVER_NODE_SQ )
269  {
270  return 0;
271  }
272 
273  angleToNode = Ceil( AngleClamp180( self.angles[1] - self GetNodeOffsetAngles( self.node )[1] ) );
274 
275  return angleToNode;
276 }
277 
279 {
280  If( self IsAtCoverNodeStrict() && self ShouldUseCoverNode() )
281  {
282  highestStance = ‪AiUtility::getHighestNodeStance( self.node );
283  return highestStance;
284  }
285  else
286  {
288  }
289 }
290 
291 
293 {
294  if( IsDefined( self.prevrelativedir ) )
295  {
296  direction = self.prevrelativedir;
297 
298  switch( direction )
299  {
310  }
311  }
312 
314 }
315 
317 {
318  return ‪AiUtility::getCoverType( self.node );
319 }
320 
322 {
323  if ( ‪AiUtility::isCoverConcealed( self.node ) )
324  {
326  }
327 
329 }
330 
332 {
333  // Returns the cover node type that the AI is currently at.
334  // This version of cover node type is resilient to timing issues during node selections.
335 
336  if ( IsDefined( self.node ) && DistanceSquared( self.origin, self.node.origin ) < ‪SQR( 48 ) )
337  {
339  }
340 
342 }
343 
345 {
346 /#
347  if( IsDefined( level._debug_damage_direction ) )
348  return level._debug_damage_direction;
349 #/
350  if ( self.damageyaw > 135 || self.damageyaw <= -135 )
351  {
352  self.damage_direction = ‪DAMAGE_DIRECTION_FRONT;
354  }
355 
356  if ( ( self.damageyaw > 45 ) && ( self.damageyaw <= 135 ) )
357  {
358  self.damage_direction = ‪DAMAGE_DIRECTION_RIGHT;
360  }
361 
362  if ( ( self.damageyaw > -45 ) && ( self.damageyaw <= 45 ) )
363  {
364  self.damage_direction = ‪DAMAGE_DIRECTION_BACK;
366  }
367 
368  self.damage_direction = ‪DAMAGE_DIRECTION_LEFT;
370 }
371 
373 {
374 /#
375  if( IsDefined( level._debug_damage_pain_location ) )
376  return level._debug_damage_pain_location;
377 #/
378 
379  sHitLoc = self.damagelocation;
380 
381  possibleHitLocations = ‪array();
382 
383  if ( ‪IS_HITLOC_HEAD(sHitLoc) )
384  {
385  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_HEAD;
386  }
387 
388  if ( ‪IS_HITLOC_CHEST(sHitLoc) )
389  {
390  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_CHEST;
391  }
392 
393  if( ‪IS_HITLOC_HIPS(sHitLoc) )
394  {
395  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_GROIN;
396  }
397 
398  if ( ‪IS_HITLOC_HIPS(sHitLoc) )
399  {
400  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_LEGS;
401  }
402 
403  if ( ‪IS_HITLOC_LEFT_ARM(sHitLoc) )
404  {
405  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_LEFT_ARM;
406  }
407 
408  if ( ‪IS_HITLOC_RIGHT_ARM(sHitLoc) )
409  {
410  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_RIGHT_ARM;
411  }
412 
413  if ( ‪IS_HITLOC_LEGS(sHitLoc) )
414  {
415  possibleHitLocations[possibleHitLocations.size] = ‪HITLOC_LEGS;
416  }
417 
418  // if this AI was shot recently, then try to not repeat the same damagelocation, so that we get two different responses
419  if( IsDefined( self.lastDamageTime ) && GetTime() > self.lastDamageTime && GetTime() <= self.lastDamageTime + 1 * 1000 )
420  {
421  if( IsDefined( self.lastDamageLocation ) )
422  ArrayRemoveValue( possibleHitLocations, self.lastDamageLocation );
423  }
424 
425  if( possibleHitLocations.size == 0 )
426  {
427  // SUMEET (07/02/2015) - There is an underlying VM bug where something modifying 0 size array does not work.
428  // This script happens to be one of the places where that issue happens often. Just creating a completely new
429  // array seems to fix the issue in this case.
430  possibleHitLocations = undefined;
431  possibleHitLocations = [];
432 
433  possibleHitLocations[0] = ‪HITLOC_CHEST;
434  possibleHitLocations[1] = ‪HITLOC_GROIN;
435  }
436 
437  assert( possibleHitLocations.size > 0, possibleHitLocations.size );
438 
439  damageLocation = possibleHitLocations[RandomInt(possibleHitLocations.size)];
440 
441  // save the last damage location
442  self.lastDamageLocation = damageLocation;
443 
444  return damageLocation;
445 }
446 
448 {
449  if ( IsDefined( self.damageMod ) )
450  {
451  if ( IsInArray( ‪array( "mod_rifle_bullet" ), ToLower( self.damageMod ) ) )
452  return "rifle";
453 
454  if ( IsInArray( ‪array( "mod_pistol_bullet" ), ToLower( self.damageMod ) ) )
455  return "pistol";
456 
457  if ( IsInArray( ‪array( "mod_melee", "mod_melee_assassinate", "mod_melee_weapon_butt" ), ToLower( self.damageMod ) ) )
458  return "melee";
459 
460  if ( IsInArray( ‪array( "mod_grenade", "mod_grenade_splash", "mod_projectile", "mod_projectile_splash", "mod_explosive" ), ToLower( self.damageMod ) ) )
461  return "explosive";
462  }
463 
464  return "rifle";
465 }
466 
468 {
469  if(isdefined(self.special_weapon) &&isdefined(self.special_weapon.name) )
470  {
471  return self.special_weapon.name;
472  }
473 
474  if (isDefined(self.damageWeapon) && isDefined(self.damageWeapon.name) )
475  {
476  return self.damageWeapon.name;
477  }
478 
479  return "unknown";
480 }
481 
483 {
484  if (isDefined(self.damageMod))
485  {
486  return ToLower(self.damageMod);
487  }
488 
489  return "unknown";
490 }
491 
493 {
494 /#
495  if( IsDefined( level._debug_damage_intensity ) )
496  return level._debug_damage_intensity;
497 #/
498 
499  damageTaken = self.damageTaken;
500  maxHealth = self.maxHealth;
501  damageTakenType = ‪DAMAGE_LIGHT;
502 
503  if( IsAlive( self ) )
504  {
505  // pain damage
506 // if( IsDefined( self.lastDamageTime ) && IsDefined( self.lastDamageLocation ) )
507 // {
508 // if( GetTime() > self.lastDamageTIme && GetTime() < self.lastDamageTime + HEAVY_CONSECUTIVE_ATTACK_INTERVAL )
509 // damageTakenType = DAMAGE_HEAVY;
510 // }
511 // else
512 // {
513  ratio = damageTaken / self.maxHealth;
514 
515  if( ratio > ‪HEAVY_DAMAGE_RATIO )
516  damageTakenType = ‪DAMAGE_HEAVY;
517 // }
518 
519  self.lastDamageTime = GetTime();
520  }
521  else
522  {
523  // death/fatal damage
524  ratio = damageTaken / self.maxHealth;
525 
526  if( ratio > ‪HEAVY_DAMAGE_RATIO )
527  damageTakenType = ‪DAMAGE_HEAVY;
528  }
529 
530  return damageTakenType;
531 }
532 
533 /*
535 "Function Name: AddAIOverrideDamageCallback \n"
536 <br/>"Summary: Adds an AI damage callback function. This should only be used by the AI system.\n"
537 <br/>"Mandatory Argument(s): <entity> : Entity to add the damage callback to.\n"
538 <br/>"Mandatory Argument(s): <function> : Damage callback function.\n"
539 <br/>"Optional Argument(s): <boolean> : Whether to add the callback to the front of the overrides\n"
541 */
542 function ‪AddAIOverrideDamageCallback( entity, ‪callback, addToFront )
543 {
544  assert( IsEntity( entity ) );
545  assert( IsFunctionPtr( ‪callback ) );
546  assert( !IsDefined( entity.aiOverrideDamage ) || IsArray( entity.aiOverrideDamage ) );
547 
548  ‪MAKE_ARRAY( entity.aiOverrideDamage );
549 
550  if ( ‪IS_TRUE( addToFront ) )
551  {
552  damageOverrides = [];
553  damageOverrides[ damageOverrides.size ] = ‪callback;
554 
555  foreach( override in entity.aiOverrideDamage )
556  {
557  damageOverrides[ damageOverrides.size ] = override;
558  }
559 
560  entity.aiOverrideDamage = damageOverrides;
561  }
562  else
563  {
564  ‪ARRAY_ADD( entity.aiOverrideDamage, ‪callback );
565  }
566 }
567 
568 /*
570 "Function Name: RemoveAIOverrideDamageCallback \n"
571 <br/>"Summary: Removes an AI damage callback function. This should only be used by the AI system.\n"
572 <br/>"Mandatory Argument(s): <entity> : Entity to remove the damage callback from.\n"
573 <br/>"Mandatory Argument(s): <function> : Damage callback function.\n"
574 <br/>"Optional Argument(s): \n"
576 */
578 {
579  assert( IsEntity( entity ) );
580  assert( IsFunctionPtr( ‪callback ) );
581  assert( IsArray( entity.aiOverrideDamage ) );
582 
583  currentDamageCallbacks = entity.aiOverrideDamage;
584 
585  entity.aiOverrideDamage = [];
586 
587  foreach (key, value in currentDamageCallbacks)
588  {
589  if ( value != ‪callback )
590  {
591  entity.aiOverrideDamage[ entity.aiOverrideDamage.size ] = value;
592  }
593  }
594 }
595 
596 /*
598 "Function Name: ClearAIOverrideDamageCallbacks \n"
599 <br/>"Summary: Removes all AI damage callback function. This should only be used by the AI system.\n"
600 <br/>"Mandatory Argument(s): <entity> : Entity to clear the damage callbacks from.\n"
601 <br/>"Optional Argument(s): \n"
603 */
605 {
606  entity.aiOverrideDamage = [];
607 }
608 
609 /*
611 "Function Name: AddAIOverrideKilledCallback \n"
612 <br/>"Summary: Adds a AI killed callback function. This should only be used by the AI system.\n"
613 <br/>"Mandatory Argument(s): <entity> : Entity to add the killed callback to.\n"
614 <br/>"Mandatory Argument(s): <function> : Killed callback function.\n"
615 <br/>"Optional Argument(s): \n"
617 */
619 {
620  assert( IsEntity( entity ) );
621  assert( IsFunctionPtr( ‪callback ) );
622  assert( !IsDefined( entity.aiOverrideKilled ) || IsArray( entity.aiOverrideKilled ) );
623 
624  ‪ARRAY_ADD( entity.aiOverrideKilled, ‪callback );
625 }
626 
627 function ‪ActorGetPredictedYawToEnemy( entity, lookAheadTime )
628 {
629  // don't run this more than once per frame
630  if( IsDefined(entity.predictedYawToEnemy) && IsDefined(entity.predictedYawToEnemyTime) && entity.predictedYawToEnemyTime == GetTime() )
631  return entity.predictedYawToEnemy;
632 
633  selfPredictedPos = entity.origin;
634  moveAngle = entity.angles[1] + entity getMotionAngle();
635  selfPredictedPos += (cos( moveAngle ), sin( moveAngle ), 0) * 200.0 * lookAheadTime;
636 
637  yaw = VectorToAngles( entity LastKnownPos( entity.enemy ) - selfPredictedPos)[1] - entity.angles[1];
638  yaw = AbsAngleClamp360( yaw );
639 
640  // cache
641  entity.predictedYawToEnemy = yaw;
642  entity.predictedYawToEnemyTime = GetTime();
643 
644  return yaw;
645 }
646 
648 {
649  entity = self;
650 
651  if( entity ‪ai::has_behavior_attribute( "patrol" )
652  && entity ‪ai::get_behavior_attribute( "patrol" ) )
653  {
654  return ‪PATROL_ENABLED;
655  }
656 
657  return ‪PATROL_DISABLED;
658 }
659 
661 {
662  entity = self;
663 
664  if ( IsDefined( entity.enemy ) )
665  {
666  return ‪HAS_ENEMY;
667  }
668 
669  return ‪NO_ENEMY;
670 }
671 
672 #define DEFAULT_ENEMY_YAW 0
674 {
675  // enemy yaw from AI's forward direction
676  enemy = self.enemy;
677 
678  if( !IsDefined( enemy ) )
679  return ‪DEFAULT_ENEMY_YAW;
680 
681  toEnemyYaw = ‪ActorGetPredictedYawToEnemy( self, 0.2 );
683 
684  return toEnemyYaw;
685 }
686 
688 {
689  // enemy yaw from AI's forward direction
690  enemy = self.enemy;
691 
692  if( !IsDefined( enemy ) )
693  return ‪DEFAULT_ENEMY_YAW;
694 
695  toEnemyYaw = VectorToAngles( enemy.origin - self.origin )[1] - self.angles[1];
696  toEnemyYaw = AbsAngleClamp360( toEnemyYaw );
697  /# recordEntText( "EnemyYaw: " + toEnemyYaw, self, ‪RED, "Animscript" ); #/
698 
699  return toEnemyYaw;
700 }
701 
703 {
704  ‪result = 0;
705 
706  if ( isDefined( self.react_yaw ) )
707  {
708  ‪result = self.react_yaw;
709  self.react_yaw = undefined;
710  }
711  else
712  {
713  v_origin = self GetEventPointOfInterest();
714  if ( isDefined( v_origin ) )
715  {
716  str_typeName = self GetCurrentEventTypeName();
717  e_originator = self GetCurrentEventOriginator();
718 
719  if ( str_typeName == "bullet" && isDefined( e_originator ) )
720  {
721  // React to the source of the bullet, not the bullet whiz by location
722  v_origin = e_originator.origin;
723  }
724 
725  deltaOrigin = v_origin - self.origin;
726  deltaAngles = VectorToAngles( deltaOrigin );
727  ‪result = AbsAngleClamp360( self.angles[‪YAW] - deltaAngles[‪YAW] );
728  }
729  }
730 
731  return ‪result;
732 }
733 
735 {
736 /#
737  if( IsDefined( level._debug_damage_location ) )
738  return level._debug_damage_location;
739 #/
740  sHitLoc = self.damagelocation;
741 
742  if( IsDefined( sHitLoc ) )
743  {
744  if( ‪IS_HITLOC_HEAD( sHitLoc ) )
745  return ‪HITLOC_HEAD;
746 
747  if( ‪IS_HITLOC_CHEST( sHitLoc ) )
748  return ‪HITLOC_CHEST;
749 
750  if( ‪IS_HITLOC_HIPS( sHitLoc ) )
751  return ‪HITLOC_HIPS;
752 
753  if( ‪IS_HITLOC_RIGHT_ARM( sHitLoc ) )
754  return ‪HITLOC_RIGHT_ARM;
755 
756  if( ‪IS_HITLOC_LEFT_ARM( sHitLoc ) )
757  return ‪HITLOC_LEFT_ARM;
758 
759  if( ‪IS_HITLOC_LEGS( sHitLoc ) )
760  return ‪HITLOC_LEGS;
761  }
762 
763  randomLocs = ‪array( ‪HITLOC_CHEST, ‪HITLOC_HIPS );
764  return randomLocs[ RandomInt( randomLocs.size ) ];
765 }
766 
767 function ‪GetAngleUsingDirection( direction )
768 {
769  directionYaw = VectorToAngles(direction)[1];
770  yawDiff = directionYaw - self.angles[1];
771  yawDiff = yawDiff * (1.0 / 360.0);
772  flooredYawDiff = floor(yawDiff + 0.5);
773  turnAngle = (yawDiff - flooredYawDiff) * 360.0;
774 
776 
777  return AbsAngleClamp360( turnAngle );
778 }
779 
780 
782 {
783  if( IsDefined( self.prevNode ) )
784  {
785  if( ‪NODE_TYPE_COVER( self.prevNode ) )
786  return true;
787  }
788 
789  return false;
790 }
791 
792 function ‪BB_GetLocomotionExitYaw( blackboard, yaw )
793 {
794  exitYaw = undefined;
795 
796  if( self HasPath() )
797  {
798  predictedLookAheadInfo = self PredictExit();
799  status = predictedLookAheadInfo["path_prediction_status"];
800 
801  if( !IsDefined( self.pathgoalpos ) )
802  {
803  return ‪INVALID_EXIT_YAW;
804  }
805 
806  if( DistanceSquared( self.origin, self.pathgoalpos ) <= ‪MIN_EXITYAW_DISTANCE_SQ )
807  {
808  return ‪INVALID_EXIT_YAW;
809  }
810 
812  {
813  start = self.origin;
814  ‪end = start + VectorScale( ( 0, predictedLookAheadInfo["path_prediction_travel_vector"][1], 0 ), 100 );
815 
816  angleToExit = VectorToAngles( predictedLookAheadInfo["path_prediction_travel_vector"] )[1];
817  exitYaw = AbsAngleClamp360( angleToExit - self.prevnode.angles[1] );
818  }
819  else if( status == ‪CORNER_PREDICTOR_STATUS_EXITING_EXPOSED )
820  {
821  start = self.origin;
822  ‪end = start + VectorScale( ( 0, predictedLookAheadInfo["path_prediction_travel_vector"][1], 0 ), 100 );
823 
824  angleToExit = VectorToAngles( predictedLookAheadInfo["path_prediction_travel_vector"] )[1];
825  exitYaw = AbsAngleClamp360( angleToExit - self.angles[1] );
826  }
827  else if( status == ‪CORNER_PREDICTOR_STATUS_SUCCESS )
828  {
829  if( ‪wasAtCoverNode() && DistanceSquared( self.prevNode.origin, self.origin ) < (5 * 5) )
830  {
831  ‪end = self.pathgoalpos;
832 
833  angleToDestination = VectorToAngles( ‪end - self.origin )[1];
834  angleDifference = AbsAngleClamp360( angleToDestination - self.prevnode.angles[1] );
836  return angleDifference;
837  }
838 
839  start = predictedLookAheadInfo["path_prediction_start_point"];
840  ‪end = start + predictedLookAheadInfo["path_prediction_travel_vector"];
841 
842  exitYaw = ‪GetAngleUsingDirection( predictedLookAheadInfo["path_prediction_travel_vector"] );
843  }
845  {
846  if( DistanceSquared( self.origin, self.pathgoalpos ) <= ‪MIN_EXITYAW_DISTANCE_SQ )
847  {
849  return undefined;
850  }
851 
852  if( ‪wasAtCoverNode() && DistanceSquared( self.prevNode.origin, self.origin ) < (5 * 5) )
853  {
854  ‪end = self.pathgoalpos;
855 
856  angleToDestination = VectorToAngles( ‪end - self.origin )[1];
857  angleDifference = AbsAngleClamp360( angleToDestination - self.prevnode.angles[1] );
859  return angleDifference;
860  }
861 
862  start = self.origin;
863  ‪end = self.pathgoalpos;
864 
865  exitYaw = ‪GetAngleUsingDirection( VectorNormalize( ‪end - start ) );
866  }
867  }
868 
869  /#
870  if ( IsDefined( exitYaw ) )
871  {
872  Record3DText( "Exit Yaw: " + Int( exitYaw ), self.origin - ( 0, 0, 5 ), ‪RED, "Animscript", undefined, 0.4 );
873  }
874  #/
875 
876  return exitYaw;
877 }
878 
880 {
881  /#
882  // Used by cp_ai_arrival to force a tactical walk direction
883  walkString = GetDvarString( "tacticalWalkDirection" );
884  switch( walkString )
885  {
886  case "RIGHT":
888  case "LEFT":
890  case "BACK":
892  }
893  #/
894 
895  if( IsDefined( self.relativedir ) )
896  {
897  direction = self.relativedir;
898 
899  switch( direction )
900  {
911  }
912  }
913 
915 }
916 
917 
919 {
920  if( self HasPath() )
921  {
922 
923  predictedLookAheadInfo = self PredictPath();
924  status = predictedLookAheadInfo["path_prediction_status"];
925 
926  startPos = self.origin;
927 
928  // if AI is going in a straight line to the goal, then just need to make sure that, AI will not overshoot
929  furthestPointTowardsGoalClear = true;
930 
932  {
933  furthestPointAlongTowardsGoal = startPos + VectorScale( self.lookaheaddir, ‪LOCOMOTION_MOVING_PAIN_DIST_LONG );
934  furthestPointTowardsGoalClear = self FindPath( startPos, furthestPointAlongTowardsGoal, false, false ) && self MayMoveToPoint( furthestPointAlongTowardsGoal );
935  }
936 
937  if( furthestPointTowardsGoalClear )
938  {
939  forwardDir = AnglesToForward( self.angles );
940  possiblePainTypes = [];
941 
942  endPos = startPos + VectorScale( forwardDir, ‪LOCOMOTION_MOVING_PAIN_DIST_LONG );
943  if( self MayMoveToPoint( endpos ) && self FindPath( startPos, endpos, false, false ) )
944  {
945  possiblePainTypes[possiblePainTypes.size] = ‪LOCOMOTION_MOVING_PAIN_LONG;
946  }
947 
948  endPos = startPos + VectorScale( forwardDir, ‪LOCOMOTION_MOVING_PAIN_DIST_MED );
949  if( self MayMoveToPoint( endpos ) && self FindPath( startPos, endpos, false, false ) )
950  {
951  possiblePainTypes[possiblePainTypes.size] = ‪LOCOMOTION_MOVING_PAIN_MED;
952  }
953 
954  endPos = startPos + VectorScale( forwardDir, ‪LOCOMOTION_MOVING_PAIN_DIST_SHORT );
955  if( self MayMoveToPoint( endpos ) && self FindPath( startPos, endpos, false, false ) )
956  {
957  possiblePainTypes[possiblePainTypes.size] = ‪LOCOMOTION_MOVING_PAIN_SHORT;
958  }
959 
960  if( possiblePainTypes.size )
961  {
962  return array::random( possiblePainTypes );
963  }
964  }
965  }
966 
968 }
969 
971 {
972  return AbsAngleClamp360( VectorToAngles( self.lookaheaddir )[1] - self.angles[1] );
973 }
974 
976 {
977  return ‪AiUtility::getCoverType( self.prevNode );
978 }
979 
980 #define TRACKING_TURN_PERFECT_INFO_DIST 180
981 #define TRACKING_TURN_GIVE_UP_TIME 5000
983 {
984  PixBeginEvent( "BB_ActorGetTrackingTurnYaw" );
985 
986  if( IsDefined( self.enemy ) )
987  {
988  predictedPos = undefined;
989 
990  // If the enemy is less than the perfect info distance to enemy it looks better
991  // to just turn to the enemy, instead of using smaller turns.
992 
993  // TODO(David Young 2-16-15): Look into using the highlyawareradius instead of a define.
994  if ( Distance2DSquared( self.enemy.origin, self.origin ) < ‪SQR( ‪TRACKING_TURN_PERFECT_INFO_DIST ) )
995  {
996  predictedPos = self.enemy.origin;
997 
998  // Cheating the enemy's position, don't react to the enemy.
999  self.newEnemyReaction = false;
1000  }
1001  else if ( !IsSentient( self.enemy ) || ( self LastKnownTime( self.enemy ) + ‪TRACKING_TURN_GIVE_UP_TIME ) >= GetTime() )
1002  {
1003  predictedPos = self LastKnownPos( self.enemy );
1004  }
1005 
1006  if( IsDefined( predictedPos ) )
1007  {
1008  turnYaw = AbsAngleClamp360( self.angles[1] - ‪GET_YAW( self, predictedPos ) );
1009  PixEndEvent();
1010  return turnYaw;
1011  }
1012  }
1013 
1014  PixEndEvent();
1015  return undefined;
1016 }
1017 
1019 {
1020  // Default to rifle.
1021  return ‪DEFAULT_WEAPON;
1022 }
1023 
1024 // ------- UTILITY -----------//
1025 function ‪notStandingCondition( behaviorTreeEntity )
1026 {
1027  if( ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE ) != ‪STANCE_STAND )
1028  {
1029  return true;
1030  }
1031 
1032  return false;
1033 }
1034 
1035 function ‪notCrouchingCondition( behaviorTreeEntity )
1036 {
1037  if( ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE ) != ‪STANCE_CROUCH )
1038  {
1039  return true;
1040  }
1041 
1042  return false;
1043 }
1044 
1045 function ‪scriptStartRagdoll( behaviorTreeEntity )
1046 {
1047  behaviorTreeEntity StartRagdoll();
1048 }
1049 
1050 
1051 // ------- EXPOSED MELEE -----------//
1052 function private ‪prepareForExposedMelee( behaviorTreeEntity )
1053 {
1054  ‪AiUtility::keepClaimNode( behaviorTreeEntity );
1055  ‪AiUtility::meleeAcquireMutex( behaviorTreeEntity );
1056 
1057  currentStance = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE );
1058 
1059  if(isDefined(behaviorTreeEntity.enemy) && isDefined(behaviorTreeEntity.enemy.vehicletype) && isSubStr(behaviorTreeEntity.enemy.vehicletype,"firefly") )
1060  {
1062  }
1063 
1064  if( currentStance == ‪STANCE_CROUCH )
1065  {
1067  }
1068 }
1069 
1070 
1071 /*
1073 "Function Name: isFrustrated \n"
1074 <br/>"Summary: When AI has nothing to do from the cover, then AI's frustration will grow. When he will perform one of the actions, he will reset it.
1075 This should give AI a better behavior to handle situations where he has nothing to do that will be considered as effective attack."
1076 <br/>"Mandatory Argument(s): \n"
1077 <br/>"Optional Argument(s): \n"
1078 "Module: Behavior \n"
1080 */
1081 function ‪isFrustrated( behaviorTreeEntity )
1082 {
1083  return ( IsDefined( behaviorTreeEntity.frustrationLevel ) && behaviorTreeEntity.frustrationLevel > 0 );
1084 }
1085 
1086 #define MAX_FRUSTRATION 4
1087 #define MIN_FRUSTRATION 0
1088 
1089 function ‪clampFrustration( frustrationLevel )
1090 {
1091  if ( frustrationLevel > ‪MAX_FRUSTRATION )
1092  {
1093  return ‪MAX_FRUSTRATION;
1094  }
1095  else if ( frustrationLevel < ‪MIN_FRUSTRATION )
1096  {
1097  return ‪MIN_FRUSTRATION;
1098  }
1099 
1100  return frustrationLevel;
1101 }
1102 
1103 #define AGGRESSIVE_BOOST_TIME 5000
1104 
1105 /*
1107 "Function Name: updateFrustrationLevel \n"
1108 <br/>"Summary: When AI has nothing to do from the cover, then AI's frustration will grow. We track this using frustrationLevel
1109 <br/>"Mandatory Argument(s): \n"
1110 <br/>"Optional Argument(s): \n"
1111 "Module: Behavior \n"
1113 */
1114 function ‪updateFrustrationLevel( entity )
1115 {
1116  if( !entity IsBadGuy() )
1117  {
1118  return false;
1119  }
1120 
1121  if( !IsDefined( entity.frustrationLevel ) )
1122  {
1123  entity.frustrationLevel = 0;
1124  }
1125 
1126  if( !IsDefined( entity.enemy ) )
1127  {
1128  entity.frustrationLevel = 0;
1129  return false;
1130  }
1131 
1132  /#record3DText( "frustrationLevel " + entity.frustrationLevel, entity.origin, ‪ORANGE, "Animscript" );#/
1133 
1134  if ( IsActor( entity.enemy ) || IsPlayer( entity.enemy ) )
1135  {
1136  // Aggressive AI types get frustrated regularly to keep them close to their enemy.
1137  if ( entity.aggressiveMode )
1138  {
1139  if ( !IsDefined( entity.lastFrustrationBoost ) )
1140  {
1141  entity.lastFrustrationBoost = GetTime();
1142  }
1143 
1144  if ( ( entity.lastFrustrationBoost + ‪AGGRESSIVE_BOOST_TIME ) < GetTime() )
1145  {
1146  entity.frustrationLevel++;
1147  entity.lastFrustrationBoost = GetTime();
1148  entity.frustrationLevel = ‪clampFrustration( entity.frustrationLevel );
1149  }
1150  }
1151 
1152  // AI is aware of the enemy for a while?
1153  isAwareOfEnemy = ( GetTime() - entity LastKnownTime( entity.enemy ) ) < 10 * 1000;
1154 
1155  // AI has seen the enemy for a while?
1156  if( entity.frustrationLevel == 4 )
1157  hasSeenEnemy = entity SeeRecently( entity.enemy, 2 );
1158  else
1159  hasSeenEnemy = entity SeeRecently( entity.enemy, 5 );
1160 
1161  // AI has attacked the enemy recently
1162  hasAttackedEnemyRecently = entity AttackedRecently( entity.enemy, 5 );
1163 
1164  if( !isAwareOfEnemy || IsActor( entity.enemy ) )
1165  {
1166  if ( !hasSeenEnemy )
1167  {
1168  entity.frustrationLevel++;
1169  }
1170  else if ( !hasAttackedEnemyRecently )
1171  {
1172  entity.frustrationLevel += 2;
1173  }
1174 
1175  entity.frustrationLevel = ‪clampFrustration( entity.frustrationLevel );
1176 
1177  return true;
1178  }
1179 
1180  if ( hasAttackedEnemyRecently )
1181  {
1182  entity.frustrationLevel -= 2;
1183  entity.frustrationLevel = ‪clampFrustration( entity.frustrationLevel );
1184 
1185  return true;
1186  }
1187  else if ( hasSeenEnemy )
1188  {
1189  entity.frustrationLevel--;
1190  entity.frustrationLevel = ‪clampFrustration( entity.frustrationLevel );
1191 
1192  return true;
1193  }
1194  }
1195 
1196  return false;
1197 }
1198 
1199 /*
1201 "Function Name: flagEnemyUnAttackableService \n"
1202 <br/>"Summary: AI will mark the enemy unattackable for certain amount of time. Desired result will be that he will look for some other enemy to fight against.\n"
1203 <br/>"Mandatory Argument(s): \n"
1204 <br/>"Optional Argument(s): \n"
1205 "Module: Behavior \n"
1207 */
1208 function ‪flagEnemyUnAttackableService( behaviorTreeEntity )
1209 {
1210  behaviorTreeEntity FlagEnemyUnattackable();
1211 }
1212 
1213 /*
1215 "Function Name: isLastKnownEnemyPositionApproachable \n"
1216 <br/>"Summary: Returns true if the last known position of the enemy is within goal and pathable.\n"
1217 <br/>"Mandatory Argument(s): \n"
1218 <br/>"Optional Argument(s): \n"
1219 "Module: Behavior \n"
1221 */
1222 function ‪isLastKnownEnemyPositionApproachable( behaviorTreeEntity )
1223 {
1224  if( IsDefined( behaviorTreeEntity.enemy ) )
1225  {
1226  lastKnownPositionOfEnemy = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1227 
1228  if( behaviorTreeEntity IsInGoal( lastKnownPositionOfEnemy )
1229  && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, lastKnownPositionOfEnemy, true, false )
1230  )
1231  {
1232  return true;
1233  }
1234  }
1235 
1236  return false;
1237 }
1238 
1239 
1240 /*
1242 "Function Name: tryAdvancingOnLastKnownPositionBehavior \n"
1243 <br/>"Summary: AI will try to run to the last known position of the enemy as long as it is within the goal.\n"
1244 <br/>"Mandatory Argument(s): \n"
1245 <br/>"Optional Argument(s): \n"
1246 "Module: Behavior \n"
1248 */
1249 function ‪tryAdvancingOnLastKnownPositionBehavior( behaviorTreeEntity )
1250 {
1251  if( IsDefined( behaviorTreeEntity.enemy ) )
1252  {
1253  if( ‪IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1254  {
1255  lastKnownPositionOfEnemy = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1256 
1257  if( behaviorTreeEntity IsInGoal( lastKnownPositionOfEnemy )
1258  && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, lastKnownPositionOfEnemy, true, false )
1259  )
1260  {
1261  behaviorTreeEntity UsePosition( lastKnownPositionOfEnemy, lastKnownPositionOfEnemy );
1262 
1263  ‪AiUtility::setNextFindBestCoverTime( behaviorTreeEntity, undefined );
1264 
1265  return true;
1266  }
1267  }
1268  }
1269 
1270  return false;
1271 }
1272 
1273 
1274 /*
1276 "Function Name: tryGoingToClosestNodeToEnemyBehavior \n"
1277 <br/>"Summary: AI will try to run to the closest node to the enemy as long as it is within the goal.\n"
1278 <br/>"Mandatory Argument(s): \n"
1279 <br/>"Optional Argument(s): \n"
1280 "Module: Behavior \n"
1282 */
1283 function ‪tryGoingToClosestNodeToEnemyBehavior( behaviorTreeEntity )
1284 {
1285  if( IsDefined( behaviorTreeEntity.enemy ) )
1286  {
1287  closestRandomNode = behaviorTreeEntity FindBestCoverNodes( behaviorTreeEntity.engageMaxDist, behaviorTreeEntity.enemy.origin )[0];
1288 
1289  if( IsDefined( closestRandomNode )
1290  && behaviorTreeEntity IsInGoal( closestRandomNode.origin )
1291  && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, closestRandomNode.origin, true, false )
1292  )
1293  {
1294  ‪useCoverNodeWrapper( behaviorTreeEntity, closestRandomNode );
1295 
1296  return true;
1297  }
1298  }
1299 
1300  return false;
1301 }
1302 
1303 
1304 /*
1306 "Function Name: tryRunningDirectlyToEnemyBehavior \n"
1307 <br/>"Summary: AI will try to run directly to enemy as long as it is within the goal. This is a little cheating as we share the origin directly\n
1308 with the enemy, but in combat, it will make AI look smarter."
1309 <br/>"Mandatory Argument(s): \n"
1310 <br/>"Optional Argument(s): \n"
1311 "Module: Behavior \n"
1313 */
1314 function ‪tryRunningDirectlyToEnemyBehavior( behaviorTreeEntity )
1315 {
1316  if( IsDefined( behaviorTreeEntity.enemy ) && ‪IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1317  {
1318  origin = behaviorTreeEntity.enemy.origin;
1319 
1320  if( behaviorTreeEntity IsInGoal( origin )
1321  && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, origin, true, false )
1322  )
1323  {
1324  behaviorTreeEntity UsePosition( origin, origin );
1325 
1326  ‪AiUtility::setNextFindBestCoverTime( behaviorTreeEntity, undefined );
1327 
1328  return true;
1329  }
1330  }
1331 
1332  return false;
1333 }
1334 
1335 /*
1337 "Function Name: shouldReactToNewEnemy \n"
1338 <br/>"Summary: returns true if AI should react to enemy.\n"
1339 <br/>"Mandatory Argument(s): \n"
1340 <br/>"Optional Argument(s): \n"
1341 "Module: Behavior \n"
1343 */
1344 function ‪shouldReactToNewEnemy( behaviorTreeEntity )
1345 {
1346  // TODO(David Young 4-25-15): Currently disabling reactions till they are more reliable.
1347  return false;
1348 
1349  if( ‪IS_TRUE( behaviorTreeEntity.newEnemyReaction ) )
1350  {
1351  return true;
1352  }
1353 
1354  stance = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE );
1355 
1356  return stance == ‪STANCE_STAND && behaviorTreeEntity.newEnemyReaction && !(behaviorTreeEntity IsAtCoverNodeStrict());
1357 }
1358 
1359 /*
1361 "Function Name: hasWeaponMalfunctioned \n"
1362 <br/>"Summary: returns true if AI has malfunction state.\n"
1363 <br/>"Mandatory Argument(s): \n"
1364 <br/>"Optional Argument(s): \n"
1365 "Module: Behavior \n"
1367 */
1368 function ‪hasWeaponMalfunctioned( behaviorTreeEntity )
1369 {
1370  return( ‪IS_TRUE( behaviorTreeEntity.malFunctionReaction ) );
1371 }
1372 
1373 /*
1375 "Function Name: isSafeFromGrenades\n"
1376 <br/>"Summary: returns if the AI is safe from grenades.\n"
1377 <br/>"Mandatory Argument(s): \n"
1378 <br/>"Optional Argument(s): \n"
1379 "Module: Behavior \n"
1381 */
1382 function ‪isSafeFromGrenades( entity )
1383 {
1384  if( IsDefined( entity.grenade ) &&
1385  IsDefined( entity.grenade.weapon ) &&
1386  entity.grenade !== entity.knownGrenade &&
1387  !entity IsSafeFromGrenade() )
1388  {
1389  if ( IsDefined( entity.node ) )
1390  {
1391  offsetOrigin = entity GetNodeOffsetPosition( entity.node );
1392 
1393  // If the entity is going towards a node, check if the node is safe from a grenade.
1394  percentRadius = Distance( entity.grenade.origin, offsetOrigin );
1395 
1396  if ( entity.grenadeAwareness >= percentRadius )
1397  {
1398  return true;
1399  }
1400  }
1401  else
1402  {
1403  percentRadius = Distance( entity.grenade.origin, entity.origin ) / entity.grenade.weapon.explosionradius;
1404 
1405  if ( entity.grenadeAwareness >= percentRadius )
1406  {
1407  return true;
1408  }
1409  }
1410 
1411  entity.knownGrenade = entity.grenade;
1412  return false;
1413  }
1414 
1415  // if this AI is not supposed to be aware of the grenades then just assume that he is safe.
1416  return true;
1417 }
1418 
1419 /*
1421 "Function Name: inGrenadeBlastRadius\n"
1422 <br/>"Summary: returns true if the AI is within the blast radius of an enemy grenade.\n"
1423 <br/>"Mandatory Argument(s): \n"
1424 <br/>"Optional Argument(s): \n"
1425 "Module: Behavior \n"
1427 */
1428 function ‪inGrenadeBlastRadius( entity )
1429 {
1430  return !entity IsSafeFromGrenade();
1431 }
1432 
1433 /*
1435 "Function Name: recentlySawEnemy \n"
1436 <br/>"Summary: returns true if an AI has recently seen the enemy (within 4 sec).\n"
1437 <br/>"Mandatory Argument(s): \n"
1438 <br/>"Optional Argument(s): \n"
1439 "Module: Behavior \n"
1441 */
1442 function ‪recentlySawEnemy( behaviorTreeEntity )
1443 {
1444  const RECENTLY_SEEN_TIME = 6;
1445 
1446  if( IsDefined( behaviorTreeEntity.enemy ) && behaviorTreeEntity SeeRecently( behaviorTreeEntity.enemy, RECENTLY_SEEN_TIME ) )
1447  return true;
1448 
1449  return false;
1450 }
1451 
1452 /*
1454 "Function Name: shouldOnlyFireAccurately \n"
1455 <br/>"Summary: returns at the aitype accurateFire flag.\n"
1456 <br/>"Mandatory Argument(s): \n"
1457 <br/>"Optional Argument(s): \n"
1458 "Module: Behavior \n"
1460 */
1461 function ‪shouldOnlyFireAccurately( behaviorTreeEntity )
1462 {
1463  if( ‪IS_TRUE( behaviorTreeEntity.accurateFire ) )
1464  return true;
1465 
1466  return false;
1467 }
1468 
1469 /*
1471 "Function Name: shouldBeAggressive \n"
1472 <br/>"Summary: returns at the aitype agressiveMode flag.\n"
1473 <br/>"Mandatory Argument(s): \n"
1474 <br/>"Optional Argument(s): \n"
1475 "Module: Behavior \n"
1477 */
1478 function ‪shouldBeAggressive( behaviorTreeEntity )
1479 {
1480  if( ‪IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1481  return true;
1482 
1483  return false;
1484 }
1485 
1486 /*
1488 "Function Name: useCoverNodeWrapper \n"
1489 <br/>"Summary: Tells an actor to use a given cover node. Also updates nextFindBestCoverTime based on engagement distance.\n"
1490 <br/>"Mandatory Argument(s): node\n"
1491 <br/>"Optional Argument(s): \n"
1492 "Module: Behavior \n"
1494 */
1495 function ‪useCoverNodeWrapper( behaviorTreeEntity, node )
1496 {
1497  sameNode = behaviorTreeEntity.node === node;
1498 
1499  behaviorTreeEntity UseCoverNode( node );
1500 
1501  if ( !sameNode )
1502  {
1503  // TODO(David Young 4-10-14): This fixes issues where cover_mode is still set to cover_alert
1504  // even when AI's are walking around. Need to find a better way of doing this.
1507  }
1508 
1509  ‪setNextFindBestCoverTime( behaviorTreeEntity, node );
1510 }
1511 
1512 function ‪setNextFindBestCoverTime( behaviorTreeEntity, node )
1513 {
1514  // Optimized to code as this function rose to the top of time spent in script VM
1515  behaviorTreeEntity.nextFindBestCoverTime = behaviorTreeEntity GetNextFindBestCoverTime( behaviorTreeEntity.engageMinDist, behaviorTreeEntity.engagemaxdist, behaviorTreeEntity.coversearchinterval );
1516 }
1517 
1518 /*
1520 "Function Name: trackCoverParamsService \n"
1521 <br/>"Summary: tracks behaviorTreeEntity.coverNode and nextFindBestCoverTime.\n"
1522 <br/>"Mandatory Argument(s): \n"
1523 <br/>"Optional Argument(s): \n"
1524 "Module: Behavior \n"
1526 */
1527 function ‪trackCoverParamsService( behaviorTreeEntity )
1528 {
1529  if( IsDefined( behaviorTreeEntity.node )
1530  && behaviorTreeEntity IsAtCoverNodeStrict()
1531  && behaviorTreeEntity ShouldUseCoverNode() )
1532  {
1533  if( !IsDefined( behaviorTreeEntity.coverNode ) )
1534  {
1535  behaviorTreeEntity.coverNode = behaviorTreeEntity.node;
1536  ‪setNextFindBestCoverTime( behaviorTreeEntity, behaviorTreeEntity.node );
1537  }
1538 
1539  return;
1540  }
1541 
1542  behaviorTreeEntity.coverNode = undefined;
1543 }
1544 
1545 
1546 function ‪chooseBestCoverNodeASAP( behaviorTreeEntity )
1547 {
1548  if( !IsDefined( behaviorTreeEntity.enemy ) )
1549  return false;
1550 
1551  node = ‪AiUtility::getBestCoverNodeIfAvailable( behaviorTreeEntity );
1552  if ( IsDefined( node ) )
1553  {
1554  ‪useCoverNodeWrapper( behaviorTreeEntity, node );
1555  }
1556 }
1557 
1558 /*
1560 "Function Name: shouldChooseBetterCover \n"
1561 <br/>"Summary: Returns true if AI should find a better cover node soon.\n"
1562 <br/>"Mandatory Argument(s): \n"
1563 <br/>"Optional Argument(s): \n"
1564 "Module: Behavior \n"
1566 */
1567 function ‪shouldChooseBetterCover( behaviorTreeEntity )
1568 {
1569  const NEAR_ARRIVAL_DIST_SQ = 64 * 64;
1570 
1571  if( behaviorTreeEntity ‪ai::has_behavior_attribute( "stealth" )
1572  && behaviorTreeEntity ‪ai::get_behavior_attribute( "stealth" ) )
1573  {
1574  return false;
1575  }
1576 
1577  if ( ‪IS_TRUE( behaviorTreeEntity.avoid_cover ) )
1578  {
1579  return false;
1580  }
1581 
1582  if( behaviorTreeEntity IsInAnyBadPlace() )
1583  {
1584  return true;
1585  }
1586 
1587  if( IsDefined( behaviorTreeEntity.enemy ) )
1588  {
1589  shouldUseCoverNodeResult = false;
1590  shouldBeBoredAtCurrentCover = false;
1591  aboutToArriveAtCover = false;
1592  isWithinEffectiveRangeAlready = false;
1593  isLookingAroundForEnemy = false;
1594 
1595  // SHOULD HOLD GROUND AGAINST THE ENEMY - Withing pathEnemyFightDist
1596  if( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
1597  return false;
1598 
1599  // ABOUT TO ARRIVE AT COVER
1600  if( behaviorTreeEntity HasPath() && IsDefined( behaviorTreeEntity.arrivalFinalPos ) && IsDefined( behaviorTreeEntity.pathGoalPos ) && self.pathGoalPos == behaviorTreeEntity.arrivalFinalPos )
1601  {
1602  if( DistanceSquared( behaviorTreeEntity.origin, behaviorTreeEntity.arrivalFinalPos ) < NEAR_ARRIVAL_DIST_SQ )
1603  {
1604  aboutToArriveAtCover = true;
1605  }
1606  }
1607 
1608  // COVER RANGES ARE VALID
1609  shouldUseCoverNodeResult = behaviorTreeEntity ShouldUseCoverNode();
1610 
1611  // ONLY CARE FOR ENGAGEMENT DISTANCE AND LOOKING AROUND IF WITHIN THE GOAL
1612  if( self IsAtGoal() )
1613  {
1614  // IS WITHIN APPROPRIATE ENGAGEMENT DISTANCE BAND
1615  if( shouldUseCoverNodeResult && IsDefined( behaviorTreeEntity.node ) && self IsAtGoal() )
1616  {
1617  lastKnownPos = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1618 
1619  dist = Distance2D( behaviorTreeEntity.origin, lastKnownPos );
1620 
1621  if( dist > behaviorTreeEntity.engageMinFalloffDist && dist <= behaviorTreeEntity.engageMaxFalloffDist )
1622  isWithinEffectiveRangeAlready = true;
1623  }
1624 
1625  // SHOULD BE BORED AT CURRENT COVER
1626  shouldBeBoredAtCurrentCover = !isWithinEffectiveRangeAlready && behaviorTreeEntity IsAtCoverNode() && ( GetTime() > self.nextFindBestCoverTime );
1627 
1628  // IS LOOKING AROUND ENEMY AND FRUSTRATED
1629  if( !shouldUseCoverNodeResult )
1630  {
1631  if( IsDefined( behaviorTreeEntity.frustrationLevel ) && behaviorTreeEntity.frustrationLevel > 0 && behaviorTreeEntity HasPath() )
1632  isLookingAroundForEnemy = true;
1633  }
1634  }
1635 
1636  shouldLookForBetterCover = !isLookingAroundForEnemy
1637  && !aboutToArriveAtCover
1638  && !isWithinEffectiveRangeAlready
1639  && ( !shouldUseCoverNodeResult || shouldBeBoredAtCurrentCover || !self IsAtGoal() );
1640 
1641  /#
1642  if( shouldLookForBetterCover )
1643  color = ‪GREEN;
1644  else
1645  color = ‪RED;
1646 
1647  recordEntText( "ChooseBetterCoverReason: SUC:" + shouldUseCoverNodeResult
1648  + " LAE:" + isLookingAroundForEnemy
1649  + " ARR:" + aboutToArriveAtCover
1650  + " EFF:" + isWithinEffectiveRangeAlready
1651  + " BOR:" + shouldBeBoredAtCurrentCover
1652  , behaviorTreeEntity, color, "Animscript" );
1653  #/
1654  }
1655  else
1656  {
1657  return !( behaviorTreeEntity ShouldUseCoverNode() && behaviorTreeEntity IsApproachingGoal() );
1658  }
1659 
1660  return shouldLookForBetterCover;
1661 }
1662 
1663 
1664 /*
1666 "Function Name: chooseBetterCoverServiceCodeVersion \n"
1667 <br/>"Summary: Finds a better cover node using faster code version.\n"
1668 <br/>"Mandatory Argument(s): \n"
1669 <br/>"Optional Argument(s): \n"
1670 "Module: Behavior \n"
1672 */
1673 function ‪chooseBetterCoverServiceCodeVersion( behaviorTreeEntity )
1674 {
1675  if( isDefined( behaviorTreeEntity.stealth ) && behaviorTreeEntity ‪ai::get_behavior_attribute( "stealth" ) )
1676  {
1677  return false;
1678  }
1679 
1680  if ( ‪IS_TRUE( behaviorTreeEntity.avoid_cover ) )
1681  {
1682  return false;
1683  }
1684 
1685  if ( IsDefined( behaviorTreeEntity.knownGrenade ) )
1686  {
1687  // Don't choose a new cover if the AI is already reacting to a grenade.
1688  return false;
1689  }
1690 
1691  if ( !‪aiutility::isSafeFromGrenades( behaviorTreeEntity ) )
1692  {
1693  // Force a new cover selection if not safe from a grenade.
1694  behaviorTreeEntity.nextFindBestCoverTime = 0;
1695  }
1696 
1697  newNode = behaviorTreeEntity ChooseBetterCoverNode();
1698 
1699  if( IsDefined( newNode ) )
1700  {
1701  ‪useCoverNodeWrapper( behaviorTreeEntity, newNode );
1702  return true;
1703  }
1704 
1705  ‪setNextFindBestCoverTime( behaviorTreeEntity, undefined );
1706 
1707  return false;
1708 }
1709 
1710 /*
1712 "Function Name: chooseBetterCoverService \n"
1713 <br/>"Summary: Finds a better cover node.\n"
1714 <br/>"Mandatory Argument(s): \n"
1715 <br/>"Optional Argument(s): \n"
1716 "Module: Behavior \n"
1718 */
1719 function private ‪chooseBetterCoverService( behaviorTreeEntity )
1720 {
1721  shouldChooseBetterCoverResult = ‪shouldChooseBetterCover( behaviorTreeEntity );
1722 
1723  // Only search for a new cover node if the AI isn't trying to keep their current claimed node.
1724  if( shouldChooseBetterCoverResult && !behaviorTreeEntity.keepClaimedNode )
1725  {
1726  transitionRunning = behaviorTreeEntity ASMIsTransitionRunning();
1727  subStatePending = behaviorTreeEntity ASMIsSubStatePending();
1728  transDecRunning = behaviorTreeEntity AsmIsTransDecRunning();
1729  isBehaviorTreeInRunningState = behaviorTreeEntity GetBehaviortreeStatus() == ‪BHTN_RUNNING;
1730 
1731  if( !transitionRunning && !subStatePending && !transDecRunning && isBehaviorTreeInRunningState )
1732  {
1733  node = ‪AiUtility::getBestCoverNodeIfAvailable( behaviorTreeEntity );
1734  goingToDifferentNode = IsDefined( node ) && ( !IsDefined( behaviorTreeEntity.node ) || node != behaviorTreeEntity.node );
1735 
1736  if ( goingToDifferentNode )
1737  {
1738  ‪useCoverNodeWrapper( behaviorTreeEntity, node );
1739  return true;
1740  }
1741 
1742  // Set the next find time, even though we did not find a cover to go to
1743  ‪setNextFindBestCoverTime( behaviorTreeEntity, undefined );
1744  }
1745  }
1746 
1747  return false;
1748 }
1749 
1750 /*
1752 "Function Name: refillAmmo \n"
1753 <br/>"Summary: Refills the bullets in clip of the AI.\n"
1754 <br/>"Mandatory Argument(s): AI behaviorTreeEntity\n"
1755 <br/>"Optional Argument(s): \n"
1756 "Module: Behavior \n"
1758 */
1759 function ‪refillAmmo( behaviorTreeEntity )
1760 {
1761  if ( behaviorTreeEntity.weapon != level.weaponNone )
1762  {
1763  behaviorTreeEntity.bulletsInClip = behaviorTreeEntity.weapon.clipSize;
1764  }
1765 }
1766 
1767 /*
1769 "Function Name: hasAmmo \n"
1770 <br/>"Summary: Returns true if AI has any ammo left.\n"
1771 <br/>"Mandatory Argument(s): \n"
1772 <br/>"Optional Argument(s): \n"
1773 "Module: Behavior \n"
1775 */
1776 function ‪hasAmmo( behaviorTreeEntity )
1777 {
1778  if( behaviorTreeEntity.bulletsInClip > 0 )
1779  return true;
1780  else
1781  return false;
1782 }
1783 
1784 function ‪hasLowAmmo( behaviorTreeEntity )
1785 {
1786  if ( behaviorTreeEntity.weapon != level.weaponNone )
1787  {
1788  return behaviorTreeEntity.bulletsInClip < (behaviorTreeEntity.weapon.clipSize * 0.2);
1789  }
1790 
1791  return false;
1792 }
1793 
1794 /*
1796 "Function Name: HasEnemy \n"
1797 <br/>"Summary: Returns true if AI has enemy.\n"
1798 <br/>"Mandatory Argument(s): \n"
1799 <br/>"Optional Argument(s): \n"
1800 "Module: Behavior \n"
1802 */
1803 function ‪hasEnemy( behaviorTreeEntity )
1804 {
1805  if( IsDefined( behaviorTreeEntity.enemy ) )
1806  {
1807  return true;
1808  }
1809 
1810  return false;
1811 }
1812 
1813 /*
1815 "Function Name: getBestCoverNodeIfAvailable \n"
1816 <br/>"Summary: Get a good covernode to take against enemy.\n"
1817 <br/>"Mandatory Argument(s): \n"
1818 <br/>"Optional Argument(s): \n"
1819 "Module: Behavior \n"
1821 */
1822 function ‪getBestCoverNodeIfAvailable( behaviorTreeEntity )
1823 {
1824  node = behaviorTreeEntity FindBestCoverNode();
1825 
1826  if ( !IsDefined(node) )
1827  {
1828  return undefined;
1829  }
1830 
1831  if( behaviorTreeEntity NearClaimNode() )
1832  {
1833  currentNode = self.node;
1834  }
1835 
1836  if ( IsDefined( currentNode ) && node == currentNode )
1837  {
1838  return undefined;
1839  }
1840 
1841  // work around FindBestCoverNode() resetting my .node in rare cases involving overlapping nodes
1842  // This prevents us from thinking we've found a new node somewhere when in reality it's the one we're already at, so we won't abort our script.
1843  if ( IsDefined( behaviorTreeEntity.coverNode ) && node == behaviorTreeEntity.coverNode )
1844  {
1845  return undefined;
1846  }
1847 
1848  return node;
1849 }
1850 
1851 function ‪getSecondBestCoverNodeIfAvailable( behaviorTreeEntity )
1852 {
1853  // when fixed node is set, AI should not try to find a better cover on its own.
1854  if( IsDefined( behaviorTreeEntity.fixedNode ) && behaviorTreeEntity.fixedNode )
1855  return undefined;
1856 
1857  nodes = behaviorTreeEntity FindBestCoverNodes( behaviorTreeEntity.goalRadius, behaviorTreeEntity.origin );
1858 
1859  if ( nodes.size > 1 )
1860  {
1861  node = nodes[1];
1862  }
1863 
1864  if ( !IsDefined(node) )
1865  {
1866  return undefined;
1867  }
1868 
1869  if( behaviorTreeEntity NearClaimNode() )
1870  {
1871  currentNode = self.node;
1872  }
1873 
1874  if ( IsDefined( currentNode ) && node == currentNode )
1875  {
1876  return undefined;
1877  }
1878 
1879  // work around FindBestCoverNode() resetting my .node in rare cases involving overlapping nodes
1880  // This prevents us from thinking we've found a new node somewhere when in reality it's the one we're already at, so we won't abort our script.
1881  if ( IsDefined( behaviorTreeEntity.coverNode ) && node == behaviorTreeEntity.coverNode )
1882  {
1883  return undefined;
1884  }
1885 
1886  return node;
1887 }
1888 
1889 /*
1891 "Function Name: getCoverType \n"
1892 <br/>"Summary: returns a covernode type.\n"
1893 <br/>"Mandatory Argument(s): \n"
1894 <br/>"Optional Argument(s): \n"
1895 "Module: Behavior \n"
1897 */
1898 function ‪getCoverType( node )
1899 {
1900  if( IsDefined( node ) )
1901  {
1902  if( ‪NODE_COVER_PILLAR( node ) )
1903  return ‪COVER_PILLAR;
1904  else if( ‪NODE_COVER_LEFT( node ) )
1905  return ‪COVER_LEFT;
1906  else if( ‪NODE_COVER_RIGHT( node ) )
1907  return ‪COVER_RIGHT;
1908  else if( ‪NODE_COVER_STAND( node ) )
1909  return ‪COVER_STAND;
1910  else if( ‪NODE_COVER_CROUCH( node ) )
1911  return ‪COVER_CROUCH;
1912  else if( ‪NODE_EXPOSED( node ) || ‪NODE_GUARD( node ) )
1913  return ‪COVER_EXPOSED;
1914  }
1915 
1916  return ‪COVER_NONE;
1917 }
1918 
1919 /*
1921 "Function Name: isCoverConcealed \n"
1922 <br/>"Summary: checks if node is a concealed node.\n"
1923 <br/>"Mandatory Argument(s): \n"
1924 <br/>"Optional Argument(s): \n"
1925 "Module: Behavior \n"
1927 */
1928 function ‪isCoverConcealed( node )
1929 {
1930  if ( IsDefined( node ) )
1931  {
1932  return ‪NODE_CONCEALED( node );
1933  }
1934 
1935  return false;
1936 }
1937 
1938 /*
1940 "Function Name: canSeeEnemyWrapper \n"
1941 <br/>"Summary: checks if the enemy can be seen from a node or from exposed.\n"
1942 <br/>"Mandatory Argument(s): \n"
1943 <br/>"Optional Argument(s): \n"
1944 "Module: Behavior \n"
1946 */
1948 {
1949  if( !IsDefined( self.enemy ) )
1950  return false;
1951 
1952  if( !IsDefined( self.node ) )
1953  {
1954  return self canSee( self.enemy );
1955  }
1956  else
1957  {
1958  node = self.node;
1959  enemyEye = self.enemy GetEye();
1960  yawToEnemy = ‪GET_YAW_TO_ORIGIN180( node, enemyEye );
1961 
1962  // check corner yaw first
1963  if( ‪NODE_COVER_LEFT(node) || ‪NODE_COVER_RIGHT(node) )
1964  {
1965  // we don't need anything like this for pillar as we switch sides if needed.
1967  return false;
1968 
1969  // if this is stand node, then AI can not shoot in "Over" mode
1970  if( ‪NODE_SUPPORTS_STANCE_STAND(node) )
1971  {
1972  if( ‪NODE_COVER_LEFT(node) && yawToEnemy > ‪COVER_CORNER_VALID_YAW_RANGE_MIN )
1973  {
1975  return false;
1976  }
1977 
1978  if( ‪NODE_COVER_RIGHT(node) && yawToEnemy < -‪COVER_CORNER_VALID_YAW_RANGE_MIN )
1979  {
1981  return false;
1982  }
1983  }
1984  }
1985 
1986  nodeOffset = (0,0,0);
1987 
1988  if( ‪NODE_COVER_PILLAR(node) )
1989  {
1990  Assert( !‪ISNODEDONTRIGHT(node) || !‪ISNODEDONTLEFT(node) );
1991  canSeeFromLeft = true;
1992  canSeeFromRight = true;
1993 
1994  // PILLAR LEFT
1995  nodeOffset = ‪COVER_PILLAR_LEFT_OFFSET;
1996  lookFromPoint = ‪calculateNodeOffsetPosition( node, nodeOffset );
1997  canSeeFromLeft = sightTracePassed( lookFromPoint, enemyEye, false, undefined );
1998 
1999  // PILLAR RIGHT
2000  nodeOffset = ‪COVER_PILLAR_RIGHT_OFFSET;
2001  lookFromPoint = ‪calculateNodeOffsetPosition( node, nodeOffset );
2002  canSeeFromRight = sightTracePassed( lookFromPoint, enemyEye, false, undefined );
2003 
2004  return ( canSeeFromRight || canSeeFromLeft );
2005  }
2006  else
2007  {
2008  if( ‪NODE_COVER_LEFT(node) )
2009  {
2010  nodeOffset = ‪COVER_LEFT_OFFSET;
2011  }
2012  else if( ‪NODE_COVER_RIGHT(node) )
2013  {
2014  nodeOffset = ‪COVER_RIGHT_OFFSET;
2015  }
2016  else if( ‪NODE_COVER_STAND(node) )
2017  {
2018  nodeOffset = ‪COVER_STAND_OFFSET;
2019  }
2020  else if( ‪NODE_COVER_CROUCH(node) )
2021  {
2022  nodeOffset = ‪COVER_CROUCH_OFFSET;
2023  }
2024 
2025  lookFromPoint = ‪calculateNodeOffsetPosition( node, nodeOffset );
2026 
2027  if( sightTracePassed( lookFromPoint, enemyEye, false, undefined ) )
2028  {
2030  return true;
2031  }
2032  else
2033  {
2035  return false;
2036  }
2037  }
2038 
2039  }
2040 }
2041 
2042 function ‪calculateNodeOffsetPosition( node, nodeOffset )
2043 {
2044  right = AnglesToRight( node.angles );
2045  forward = AnglesToForward( node.angles );
2046 
2047  return node.origin + VectorScale( right, nodeOffset[0] ) + VectorScale( forward, nodeOffset[1] ) + ( 0, 0, nodeOffset[2] );
2048 }
2049 
2050 /*
2052 "Function Name: getHighestNodeStance \n"
2053 <br/>"Summary: returns the highest stance allowed at a given cover node.\n"
2054 <br/>"Mandatory Argument(s): \n"
2055 <br/>"Optional Argument(s): \n"
2056 "Module: Behavior \n"
2058 */
2059 function ‪getHighestNodeStance( node )
2060 {
2061  assert( IsDefined( node ) );
2062 
2063  if( ‪NODE_SUPPORTS_STANCE_STAND(node) ) // check for stand
2064  return "stand";
2065 
2066  if( ‪NODE_SUPPORTS_STANCE_CROUCH(node) ) // check for crouch
2067  return "crouch";
2068 
2069  if( ‪NODE_SUPPORTS_STANCE_PRONE(node) ) // check for crouch
2070  return "prone";
2071 
2072  /#
2073  ErrorMsg( node.type + " node at" + node.origin + " supports no stance." );
2074  #/
2075 
2076  // Fallback just in case there are no valid spawn flags(bad node).
2077  if ( ‪NODE_COVER_CROUCH( node ) )
2078  {
2079  return "crouch";
2080  }
2081 
2082  return "stand";
2083 }
2084 
2085 /*
2087 "Function Name: isStanceAllowedAtNode \n"
2088 <br/>"Summary: returns whether a given stance is allowed at a given cover node.\n"
2089 <br/>"Mandatory Argument(s): \n"
2090 <br/>"Optional Argument(s): \n"
2091 "Module: Behavior \n"
2093 */
2094 function ‪isStanceAllowedAtNode( stance, node )
2095 {
2096  assert( IsDefined( stance ) );
2097  assert( IsDefined( node ) );
2098 
2099  if( stance == ‪STANCE_STAND && ‪NODE_SUPPORTS_STANCE_STAND( node ) )
2100  return true;
2101 
2102  if( stance == ‪STANCE_CROUCH && ‪NODE_SUPPORTS_STANCE_CROUCH( node ) )
2103  return true;
2104 
2105  if( stance == ‪STANCE_PRONE && ‪NODE_SUPPORTS_STANCE_PRONE( node ) )
2106  return true;
2107 
2108  return false;
2109 }
2110 
2111 /*
2113 "Function Name: tryStoppingService \n"
2114 <br/>"Summary: Clears the path if enemy is within pathEnemyFightDist.\n"
2115 <br/>"Mandatory Argument(s): \n"
2116 <br/>"Optional Argument(s): \n"
2117 "Module: Behavior \n"
2119 */
2120 function ‪tryStoppingService( behaviorTreeEntity )
2121 {
2122  if ( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
2123  {
2124  behaviorTreeEntity ClearPath();
2125  behaviorTreeEntity.keepClaimedNode = true;
2126  return true;
2127  }
2128 
2129  behaviorTreeEntity.keepClaimedNode = false;
2130  return false;
2131 }
2132 
2133 /*
2135 "Function Name: shouldStopMoving \n"
2136 <br/>"Summary: Return true if enemy is within pathEnemyFightDist.\n"
2137 <br/>"Mandatory Argument(s): \n"
2138 <br/>"Optional Argument(s): \n"
2139 "Module: Behavior \n"
2141 */
2142 function ‪shouldStopMoving( behaviorTreeEntity )
2143 {
2144  if ( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
2145  {
2146  return true;
2147  }
2148 
2149  return false;
2150 }
2151 
2152 function ‪setCurrentWeapon(weapon)
2153 {
2154  self.weapon = weapon;
2155  self.weaponclass = weapon.weapClass;
2156 
2157  if( weapon != level.weaponNone )
2158  assert( IsDefined( weapon.worldModel ), "Weaopon " + weapon.name + " has no world model set in GDT." );
2159 
2160  self.weaponmodel = weapon.worldModel;
2161 }
2162 
2163 function ‪setPrimaryWeapon(weapon)
2164 {
2165  self.primaryweapon = weapon;
2166  self.primaryweaponclass = weapon.weapClass;
2167 
2168  if( weapon != level.weaponNone )
2169  assert( IsDefined( weapon.worldModel ), "Weaopon " + weapon.name + " has no world model set in GDT." );
2170 }
2171 
2172 function ‪setSecondaryWeapon(weapon)
2173 {
2174  self.secondaryweapon = weapon;
2175  self.secondaryweaponclass = weapon.weapClass;
2176 
2177  if( weapon != level.weaponNone )
2178  assert( IsDefined( weapon.worldModel ), "Weaopon " + weapon.name + " has no world model set in GDT." );
2179 }
2180 
2181 function ‪keepClaimNode( behaviorTreeEntity )
2182 {
2183  behaviorTreeEntity.keepClaimedNode = true;
2184 
2185  return true;
2186 }
2187 
2188 function ‪releaseClaimNode( behaviorTreeEntity )
2189 {
2190  behaviorTreeEntity.keepClaimedNode = false;
2191 
2192  return true;
2193 }
2194 
2198 function ‪getAimYawToEnemyFromNode( behaviorTreeEntity, node, enemy )
2199 {
2200  return AngleClamp180( VectorToAngles( ( behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) ) - node.origin )[1] - node.angles[1] );
2201 }
2202 
2206 function ‪getAimPitchToEnemyFromNode( behaviorTreeEntity, node, enemy )
2207 {
2208  return AngleClamp180( VectorToAngles( ( behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) ) - node.origin )[0] - node.angles[0] );
2209 }
2210 
2211 
2215 function ‪chooseFrontCoverDirection( behaviorTreeEntity )
2216 {
2217  coverDirection = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪COVER_DIRECTION );
2218 
2219  ‪Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, ‪PREVIOUS_COVER_DIRECTION, coverDirection );
2221 }
2222 
2223 /*
2225 "Function Name: shouldTacticalWalk \n"
2226 <br/>"Summary: returns true if AI should tactical walk facing the enemy/target.\n"
2227 <br/>"Mandatory Argument(s): \n"
2228 <br/>"Optional Argument(s): \n"
2229 "Module: Behavior \n"
2231 */
2232 function ‪shouldTacticalWalk( behaviorTreeEntity )
2233 {
2234  if( !behaviorTreeEntity HasPath() )
2235  {
2236  return false;
2237  }
2238 
2239  if ( ‪ai::HasAiAttribute( behaviorTreeEntity, "forceTacticalWalk" ) &&
2240  ‪ai::GetAiAttribute( behaviorTreeEntity, "forceTacticalWalk" ) )
2241  {
2242  return true;
2243  }
2244 
2245  if ( ‪ai::HasAiAttribute( behaviorTreeEntity, "disablesprint" ) &&
2246  !‪ai::GetAiAttribute( behaviorTreeEntity, "disablesprint" ) )
2247  {
2248  // if the script interface needs sprinting
2249  if ( ‪ai::HasAiAttribute( behaviorTreeEntity, "sprint" ) &&
2250  ‪ai::GetAiAttribute( behaviorTreeEntity, "sprint" ) )
2251  {
2252  return false;
2253  }
2254  }
2255 
2256  goalPos = undefined;
2257 
2258  if( IsDefined( behaviorTreeEntity.arrivalFinalPos ) )
2259  goalPos = behaviorTreeEntity.arrivalFinalPos;
2260  else
2261  goalPos = behaviorTreeEntity.pathGoalPos;
2262 
2263  // for moving short distances
2264  if( Isdefined( behaviorTreeEntity.pathStartPos ) && Isdefined( goalPos ) )
2265  {
2266  pathDist = DistanceSquared( behaviorTreeEntity.pathStartPos, goalPos );
2267 
2268  if( pathDist < ‪TACTICAL_WALK_SHORT_DIST_SQ )
2269  {
2270  return true;
2271  }
2272  }
2273 
2274  if( behaviorTreeEntity ShouldFaceMotion() )
2275  {
2276  return false;
2277  }
2278 
2279  if ( !behaviorTreeEntity IsSafeFromGrenade() )
2280  {
2281  return false;
2282  }
2283 
2284  return true;
2285 }
2286 
2287 /*
2289 "Function Name: shouldStealth \n"
2290 <br/>"Summary: returns true if AI should be doing stealth behavior.\n"
2291 <br/>"Mandatory Argument(s): \n"
2292 <br/>"Optional Argument(s): \n"
2293 "Module: Behavior \n"
2295 */
2296 function ‪shouldStealth( behaviorTreeEntity )
2297 {
2298  if ( isDefined( behaviorTreeEntity.stealth ) )
2299  {
2300  now = GetTime();
2301 
2302  if ( behaviorTreeEntity IsInScriptedState() )
2303  return false;
2304 
2305  // Make sure that while transitioning from stealth to combat the stealth reaction still takes place
2306  if ( behaviorTreeEntity HasValidInterrupt( "react" ) )
2307  {
2308  behaviorTreeEntity.stealth_react_last = now;
2309  return true;
2310  }
2311  if ( ‪IS_TRUE( behaviorTreeEntity.stealth_reacting ) || ( isDefined( behaviorTreeEntity.stealth_react_last ) && ( now - behaviorTreeEntity.stealth_react_last ) < 250 ) )
2312  {
2313  return true;
2314  }
2315 
2316  if( behaviorTreeEntity ‪ai::has_behavior_attribute( "stealth" )
2317  && behaviorTreeEntity ‪ai::get_behavior_attribute( "stealth" ) )
2318  {
2319  return true;
2320  }
2321  }
2322 
2323  return false;
2324 }
2325 
2326 /*
2328 "Function Name: locomotionShouldStealth \n"
2329 <br/>"Summary: returns true if AI should be moving along a path in stealth.\n"
2330 <br/>"Mandatory Argument(s): \n"
2331 <br/>"Optional Argument(s): \n"
2332 "Module: Behavior \n"
2334 */
2335 function ‪locomotionShouldStealth( behaviorTreeEntity )
2336 {
2337  if ( !‪shouldStealth( behaviorTreeEntity ) )
2338  return false;
2339 
2340  if( behaviorTreeEntity HasPath() )
2341  {
2342  if ( isDefined( behaviorTreeEntity.arrivalFinalPos ) || isDefined( behaviorTreeEntity.pathGoalPos ) )
2343  {
2344  hasWait = ( isDefined( self.currentgoal ) && isDefined( self.currentgoal.script_wait_min ) && isDefined( self.currentgoal.script_wait_max ) );
2345  if ( hasWait )
2346  hasWait = self.currentgoal.script_wait_min > 0 || self.currentgoal.script_wait_max > 0;
2347 
2348  if ( hasWait || !isDefined( self.currentgoal ) || ( isDefined( self.currentgoal ) && isDefined( self.currentgoal.scriptbundlename ) ) )
2349  {
2350  // Needs to stop at current goal
2351  goalPos = undefined;
2352  if( IsDefined( behaviorTreeEntity.arrivalFinalPos ) )
2353  goalPos = behaviorTreeEntity.arrivalFinalPos;
2354  else
2355  goalPos = behaviorTreeEntity.pathGoalPos;
2356 
2357  goalDistSq = DistanceSquared( behaviorTreeEntity.origin, goalPos );
2358 
2359  // FIXME: base this on arrival animation movement delta?
2360  if ( goalDistSq <= ( 44 * 44 ) && ( goalDistSq <= behaviorTreeEntity.goalradius * behaviorTreeEntity.goalradius ) )
2361  return false; // do arrival and stop
2362  }
2363  }
2364 
2365  return true;
2366  }
2367 
2368  return false;
2369 }
2370 
2371 /*
2373 "Function Name: shouldStealthResume \n"
2374 <br/>"Summary: returns true if AI is resuming back to less aware status.\n"
2375 <br/>"Mandatory Argument(s): \n"
2376 <br/>"Optional Argument(s): \n"
2377 "Module: Behavior \n"
2379 */
2380 function ‪shouldStealthResume( behaviorTreeEntity )
2381 {
2382  if ( !‪shouldStealth( behaviorTreeEntity ) )
2383  return false;
2384 
2385  if ( ‪IS_TRUE( behaviorTreeEntity.stealth_resume ) )
2386  {
2387  behaviorTreeEntity.stealth_resume = undefined;
2388  return true;
2389  }
2390 
2391  return false;
2392 }
2393 
2394 /*
2396 "Function Name: stealthReactCondition \n"
2397 <br/>"Summary: returns true if AI should react to spotting/hearing something.\n"
2398 <br/>"Mandatory Argument(s): \n"
2399 <br/>"Optional Argument(s): \n"
2400 "Module: Behavior \n"
2402 */
2403 function private ‪stealthReactCondition( entity )
2404 {
2405  inScene = ( isDefined( self._o_scene ) && isDefined( self._o_scene._str_state ) && self._o_scene._str_state == "play" );
2406 
2407  return ( !‪IS_TRUE( entity.stealth_reacting ) && entity HasValidInterrupt( "react" ) && !inScene );
2408 }
2409 
2410 /*
2412 "Function Name: stealthReactStart \n"
2413 <br/>"Summary: called when actor starts reacting to stealth alert event.\n"
2414 "Module: Behavior \n"
2416 */
2417 function private ‪stealthReactStart( behaviorTreeEntity )
2418 {
2419  behaviorTreeEntity.stealth_reacting = true;
2420 }
2421 
2422 /*
2424 "Function Name: stealthReactTerminate \n"
2425 <br/>"Summary: called when actor finishes reacting to stealth alert event.\n"
2426 "Module: Behavior \n"
2428 */
2429 function private ‪stealthReactTerminate( behaviorTreeEntity )
2430 {
2431  behaviorTreeEntity.stealth_reacting = undefined;
2432 }
2433 
2434 /*
2436 "Function Name: stealthIdleTerminate \n"
2437 <br/>"Summary: called when actor finishes a stealth idle anim.\n"
2438 "Module: Behavior \n"
2440 */
2441 function private ‪stealthIdleTerminate( behaviorTreeEntity )
2442 {
2443  behaviortreeentity notify("stealthIdleTerminate");
2444 
2445  if ( ‪IS_TRUE( behaviortreeentity.stealth_resume_after_idle ) )
2446  {
2447  behaviortreeentity.stealth_resume_after_idle = undefined;
2448  behaviortreeentity.stealth_resume = true;
2449  }
2450 }
2451 
2452 /*
2454 "Function Name: locomotionShouldPatrol \n"
2455 <br/>"Summary: returns true if AI should patrol walk.\n"
2456 <br/>"Mandatory Argument(s): \n"
2457 <br/>"Optional Argument(s): \n"
2458 "Module: Behavior \n"
2460 */
2461 function ‪locomotionShouldPatrol( behaviorTreeEntity )
2462 {
2463  // Stealth state takes precedence over normal patrol state
2464  if ( ‪shouldStealth( behaviortreeentity ) )
2465  return false;
2466 
2467  // if the script interface needs patrol
2468  if( behaviorTreeEntity HasPath() &&
2469  behaviorTreeEntity ‪ai::has_behavior_attribute( "patrol" )
2470  && behaviorTreeEntity ‪ai::get_behavior_attribute( "patrol" ) )
2471  {
2472  return true;
2473  }
2474 
2475  return false;
2476 }
2477 
2478 
2479 /*
2481 "Function Name: explosiveKilled \n"
2482 <br/>"Summary: returns true if AI was killed by an explosive weapon.\n"
2483 <br/>"Mandatory Argument(s): \n"
2484 <br/>"Optional Argument(s): \n"
2485 "Module: Behavior \n"
2487 */
2488 function ‪explosiveKilled( behaviorTreeEntity )
2489 {
2490  if( ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪DAMAGE_WEAPON_CLASS ) == "explosive" )
2491  {
2492  return true;
2493  }
2494 
2495  return false;
2496 }
2497 
2498 function private ‪_dropRiotShield( riotshieldInfo )
2499 {
2500  entity = self;
2501 
2502  entity ‪shared::ThrowWeapon( riotshieldInfo.weapon, riotshieldInfo.tag, false );
2503 
2504  if ( IsDefined( entity ) )
2505  {
2506  entity Detach( riotshieldInfo.model, riotshieldInfo.tag );
2507  }
2508 }
2509 
2510 /*
2512 "Function Name: attachRiotshield \n"
2513 <br/>"Summary: Attaches a riotshield to the AI.\n"
2514 <br/>"Mandatory Argument(s): <entity> : Entity to attach the riotshield to.\n"
2515 <br/>"Mandatory Argument(s): <weapon> : Specific riotshield weapon, used for dropping.\n"
2516 <br/>"Mandatory Argument(s): <string> : Model to attach to the entity.\n"
2517 <br/>"Mandatory Argument(s): <string> : Tag to attach the riotshield to.\n"
2518 <br/>"Optional Argument(s): \n"
2519 "Module: Behavior \n"
2521 */
2522 function ‪attachRiotshield( entity, riotshieldWeapon, riotshieldModel, riotshieldTag )
2523 {
2524  riotshield = SpawnStruct();
2525  riotshield.weapon = riotshieldWeapon;
2526  riotshield.tag = riotshieldTag;
2527  riotshield.model = riotshieldModel;
2528 
2529  entity Attach( riotshieldModel, riotshield.tag );
2530 
2531  entity.riotshield = riotshield;
2532 }
2533 
2534 /*
2536 "Function Name: dropRiotshield \n"
2537 <br/>"Summary: Drops the AI's riotshield if the AI has a riotshield.\n"
2538 <br/>"Mandatory Argument(s): <entity> : Entity to drop the riotshield from.\n"
2539 <br/>"Optional Argument(s): \n"
2540 "Module: Behavior \n"
2542 */
2543 function ‪dropRiotshield( behaviorTreeEntity )
2544 {
2545  if ( IsDefined( behaviorTreeEntity.riotshield ) )
2546  {
2547  riotshieldInfo = behaviorTreeEntity.riotshield;
2548 
2549  behaviorTreeEntity.riotshield = undefined;
2550  behaviorTreeEntity thread ‪_dropRiotShield( riotshieldInfo );
2551  }
2552 }
2553 
2554 
2555 /*
2557 "Function Name: electrifiedKilled \n"
2558 <br/>"Summary: returns true if AI was killed by an electrified weapon.\n"
2559 <br/>"Mandatory Argument(s): \n"
2560 <br/>"Optional Argument(s): \n"
2561 "Module: Behavior \n"
2563 */
2564 function ‪electrifiedKilled( behaviorTreeEntity )
2565 {
2566  if( behaviorTreeEntity.damageweapon.rootweapon.name == "shotgun_pump_taser" )
2567  {
2568  return true;
2569  }
2570 
2571  if( ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪DAMAGE_MOD ) == "mod_electrocuted" )
2572  {
2573  return true;
2574  }
2575 
2576  return false;
2577 
2578 }
2579 
2580 /*
2582 "Function Name: burnedKilled \n"
2583 <br/>"Summary: returns true if AI was killed by flames.\n"
2584 <br/>"Mandatory Argument(s): \n"
2585 <br/>"Optional Argument(s): \n"
2586 "Module: Behavior \n"
2588 */
2589 function ‪burnedKilled( behaviorTreeEntity )
2590 {
2591  if( ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪DAMAGE_MOD ) == "mod_burned" )
2592  {
2593  return true;
2594  }
2595 
2596  return false;
2597 }
2598 
2599 /*
2601 "Function Name: rapsKilled \n"
2602 <br/>"Summary: returns true if AI was killed by a Raps explosion.\n"
2603 <br/>"Mandatory Argument(s): \n"
2604 <br/>"Optional Argument(s): \n"
2605 "Module: Behavior \n"
2607 */
2608 function ‪rapsKilled( behaviorTreeEntity )
2609 {
2610  if( isDefined(self.attacker) && isDefined(self.attacker.archetype) && self.attacker.archetype == ‪ARCHETYPE_VEHICLE_RAPS)
2611  {
2612  return true;
2613  }
2614 
2615  return false;
2616 }
2617 
2618 
2619 // ------- EXPOSED - MELEE MUTEX -----------//
2620 function ‪meleeAcquireMutex( behaviorTreeEntity )
2621 {
2622  if( isDefined( behaviorTreeEntity ) && isDefined( behaviorTreeEntity.enemy ))
2623  {
2624  behaviorTreeEntity.melee = spawnStruct();
2625  behaviorTreeEntity.melee.enemy = behaviorTreeEntity.enemy;
2626 
2627  if( IsPlayer( behaviorTreeEntity.melee.enemy ) )
2628  {
2629  if( !isDefined( behaviorTreeEntity.melee.enemy.meleeAttackers) )
2630  {
2631  behaviorTreeEntity.melee.enemy.meleeAttackers = 0;
2632  }
2633  //assert( behaviorTreeEntity.enemy.meleeAttackers <= MAX_MELEE_PLAYER_ATTACKERS);
2634  behaviorTreeEntity.melee.enemy.meleeAttackers++;
2635  }
2636  }
2637 }
2638 
2639 function ‪meleeReleaseMutex( behaviorTreeEntity )
2640 {
2641  if( isdefined(behaviorTreeEntity.melee) )
2642  {
2643  if( isdefined(behaviorTreeEntity.melee.enemy) )
2644  {
2645  if( IsPlayer( behaviorTreeEntity.melee.enemy ) )
2646  {
2647  if( isDefined( behaviorTreeEntity.melee.enemy.meleeAttackers) )
2648  {
2649  behaviorTreeEntity.melee.enemy.meleeAttackers = behaviorTreeEntity.melee.enemy.meleeAttackers - 1;
2650  if ( behaviorTreeEntity.melee.enemy.meleeAttackers <= 0 )
2651  {
2652  behaviorTreeEntity.melee.enemy.meleeAttackers = undefined;
2653  }
2654  }
2655  }
2656  }
2657 
2658  behaviorTreeEntity.melee = undefined;
2659  }
2660 }
2661 
2662 
2663 function ‪shouldMutexMelee( behaviorTreeEntity )
2664 {
2665  // Can't acquire when someone is targeting us for a melee
2666  if ( isDefined( behaviorTreeEntity.melee ) )
2667  {
2668  return false;
2669  }
2670 
2671  // Can't acquire enemy mutex if he's already in a melee process
2672  if ( isDefined( behaviorTreeEntity.enemy))
2673  {
2674  if( !isPlayer ( behaviorTreeEntity.enemy ))
2675  {
2676  if( isDefined( behaviorTreeEntity.enemy.melee ) )
2677  {
2678  return false;
2679  }
2680  }
2681  else
2682  {
2683  // Disregard the mutex melee check against the player when not in a campaign game.
2684  if ( !SessionModeIsCampaignGame() )
2685  {
2686  return true;
2687  }
2688 
2689  if (!isDefined( behaviorTreeEntity.enemy.meleeAttackers))
2690  {
2691  behaviorTreeEntity.enemy.meleeAttackers = 0;
2692  }
2693 
2694  return behaviorTreeEntity.enemy.meleeAttackers < ‪MAX_MELEE_PLAYER_ATTACKERS;
2695  }
2696  }
2697 
2698  return true;
2699 }
2700 
2701 function ‪shouldNormalMelee( behaviorTreeEntity)
2702 {
2703  return ‪AiUtility::hasCloseEnemyToMelee( behaviorTreeEntity );
2704 }
2705 
2706 #define SHOULD_MELEE_CHECK_TIME 50
2707 function ‪shouldMelee( entity )
2708 {
2709  if ( IsDefined( entity.lastShouldMeleeResult ) &&
2710  !entity.lastShouldMeleeResult &&
2711  ( entity.lastShouldMeleeCheckTime + ‪SHOULD_MELEE_CHECK_TIME ) >= GetTime() )
2712  {
2713  // Last check was false, and very little time has progressed, return false.
2714  return false;
2715  }
2716 
2717  entity.lastShouldMeleeCheckTime = GetTime();
2718  entity.lastShouldMeleeResult = false;
2719 
2720  if ( !IsDefined( entity.enemy ) )
2721  return false;
2722 
2723  if ( !( entity.enemy.allowDeath ) )
2724  return false;
2725 
2726  if ( !IsAlive( entity.enemy ) )
2727  return false;
2728 
2729  if ( !IsSentient( entity.enemy ) )
2730  return false;
2731 
2732  if ( IsVehicle( entity.enemy ) && !‪IS_TRUE( entity.enemy.good_melee_target ) )
2733  return false;
2734 
2735  // Don't melee prone players.
2736  if ( IsPlayer( entity.enemy ) && entity.enemy GetStance() == "prone" )
2737  return false;
2738 
2739  chargeDistSQ = ( IsDefined( entity.melee_charge_rangeSQ) ? entity.melee_charge_rangeSQ : ‪CHARGE_RANGE_SQ_VS_PLAYER );
2740  if( DistanceSquared( entity.origin, entity.enemy.origin ) > chargeDistSQ )
2741  return false;
2742 
2743  if( !‪AiUtility::shouldMutexMelee( entity ) )
2744  return false;
2745 
2746  if( ‪ai::HasAiAttribute( entity, "can_melee" ) && !‪ai::GetAiAttribute( entity, "can_melee" ) )
2747  return false;
2748 
2749  if( ‪ai::HasAiAttribute( entity.enemy, "can_be_meleed" ) && !‪ai::GetAiAttribute( entity.enemy, "can_be_meleed" ) )
2750  return false;
2751 
2753  {
2754  entity.lastShouldMeleeResult = true;
2755  return true;
2756  }
2757 
2758  return false;
2759 }
2760 
2761 function ‪hasCloseEnemyToMelee( entity )
2762 {
2764 }
2765 
2766 
2767 function ‪hasCloseEnemyToMeleeWithRange( entity, melee_range_sq )
2768 {
2769  assert( IsDefined( entity.enemy ) );
2770 
2771  if ( !entity CanSee( entity.enemy ) )
2772  {
2773  return false;
2774  }
2775 
2776  predicitedPosition = entity.enemy.origin + VectorScale(entity GetEnemyVelocity(), ‪MELEE_ENEMY_DISTANCE_PREDICTION_TIME );
2777  distSQ = DistanceSquared( entity.origin, predicitedPosition );
2778  yawToEnemy = AngleClamp180( entity.angles[ 1 ] - ‪GET_YAW( entity, entity.enemy.origin ) );
2779 
2780  //within 3feet, dont need the movetopoint check
2781  if( distSQ <= ‪MELEE_NEAR_RANGE_SQ )
2782  {
2783  return abs( yawToEnemy ) <= ‪MELEE_YAW_THRESHOLDNEAR;
2784  }
2785 
2786  //less than minThresh and there isn't anything blocking us.
2787  if( distSQ <= melee_range_sq && entity MayMoveToPoint( entity.enemy.origin ) )
2788  {
2789  return abs( yawToEnemy ) <= ‪MELEE_YAW_THRESHOLD;
2790  }
2791 
2792  return false;
2793 }
2794 
2795 // ------- CHARGE MELEE -----------//
2796 function ‪shouldChargeMelee( entity )
2797 {
2798  assert( IsDefined( entity.enemy ) );
2799 
2800  currentStance = ‪Blackboard::GetBlackBoardAttribute( entity, ‪STANCE );
2801  if ( currentStance != ‪STANCE_STAND )
2802  return false;
2803 
2804  if ( IsDefined( entity.nextChargeMeleeTime ) )
2805  {
2806  if ( GetTime() < entity.nextChargeMeleeTime )
2807  return false;
2808  }
2809 
2810  enemyDistSq = DistanceSquared( entity.origin, entity.enemy.origin );
2811 
2812  // already close, no need to charge
2813  if ( enemyDistSq < ‪MELEE_RANGE_SQ )
2814  return false;
2815 
2816  // not trying to move to the EXACT location of enemy, just within close melee range
2817  offset = entity.enemy.origin - ( VectorNormalize( entity.enemy.origin - entity.origin) * ‪MELEE_NEAR_RANGE);
2818 
2819  chargeDistSQ = (isDefined(entity.melee_charge_rangeSQ)?entity.melee_charge_rangeSQ:‪CHARGE_RANGE_SQ_VS_PLAYER);
2820  if ( enemyDistSq < chargeDistSQ && entity MayMoveToPoint(offset,true,true) )
2821  {
2822  yawToEnemy = AngleClamp180( entity.angles[ 1 ] - ‪GET_YAW( entity, entity.enemy.origin ) );
2823  return abs( yawToEnemy ) <= ‪MELEE_YAW_THRESHOLD;
2824  }
2825 
2826  return false;
2827 }
2828 
2829 function private ‪shouldAttackInChargeMelee( behaviorTreeEntity )
2830 {
2831  if ( IsDefined( behaviorTreeEntity.enemy ) )
2832  {
2833  if ( DistanceSquared( behaviorTreeEntity.origin, behaviorTreeEntity.enemy.origin ) < ‪BLEND_MELEE_RANGE_SQ )
2834  {
2835  yawToEnemy = AngleClamp180( behaviorTreeEntity.angles[ 1 ] - ‪GET_YAW(behaviorTreeEntity, behaviorTreeEntity.enemy.origin ) );
2836  if ( abs( yawToEnemy ) > ‪MELEE_YAW_THRESHOLD )
2837  return false;
2838 
2839  return true;
2840  }
2841  }
2842 }
2843 
2844 function private ‪setupChargeMeleeAttack( behaviorTreeEntity )
2845 {
2846  if(isDefined(behaviorTreeEntity.enemy) && isDefined(behaviorTreeEntity.enemy.vehicletype) && isSubStr(behaviorTreeEntity.enemy.vehicletype,"firefly") )
2847  {
2849  }
2850  ‪aiutility::meleeAcquireMutex( behaviorTreeEntity );
2851  ‪aiutility::keepClaimNode( behaviorTreeEntity );
2852 }
2853 
2854 function private ‪cleanupMelee( behaviorTreeEntity )
2855 {
2856  ‪aiutility::meleeReleaseMutex( behaviorTreeEntity );
2857  ‪AiUtility::releaseClaimNode( behaviorTreeEntity );
2858  ‪Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, ‪MELEE_ENEMY_TYPE, undefined);
2859 }
2860 
2861 
2862 function private ‪cleanupChargeMelee( behaviorTreeEntity )
2863 {
2864  behaviorTreeEntity.nextChargeMeleeTime = GetTime() + ‪NEXT_CHARGE_MELEE_TIME;
2865  ‪Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, ‪MELEE_ENEMY_TYPE, undefined);
2866 
2867  ‪aiutility::meleeReleaseMutex( behaviorTreeEntity );
2868  ‪AiUtility::releaseClaimNode( behaviorTreeEntity );
2869 
2870  // Dont move for a sec
2871  behaviorTreeEntity PathMode( "move delayed", true, RandomFloatRange( 0.75, 1.5 ) );
2872 }
2873 
2874 function ‪cleanupChargeMeleeAttack( behaviorTreeEntity )
2875 {
2876  ‪AiUtility::meleeReleaseMutex( behaviorTreeEntity );
2877  ‪AiUtility::releaseClaimNode( behaviorTreeEntity );
2878  ‪Blackboard::SetBlackBoardAttribute( behaviorTreeEntity, ‪MELEE_ENEMY_TYPE, undefined);
2879 
2880  // Dont move for a sec
2881  behaviorTreeEntity PathMode( "move delayed", true, RandomFloatRange( 0.5, 1 ) );
2882 }
2883 // ------- CHARGE MELEE -----------//
2884 
2885 function private ‪shouldChooseSpecialPronePain ( behaviorTreeEntity )
2886 {
2887  stance = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE );
2888  return (stance == ‪STANCE_PRONE_ON_BACK || stance == ‪STANCE_PRONE_ON_FRONT);
2889 }
2890 
2891 // ------- SPECIAL PAIN -----------//
2892 function private ‪shouldChooseSpecialPain( behaviorTreeEntity )
2893 {
2894  if(IsDefined( behaviorTreeEntity.damageWeapon ))
2895  {
2896  return behaviorTreeEntity.damageWeapon.specialpain || isdefined(behaviorTreeEntity.special_weapon);
2897  }
2898 
2899  return false;
2900 }
2901 
2902 // ------- SPECIAL DEATH -----------//
2903 function private ‪shouldChooseSpecialDeath( behaviorTreeEntity )
2904 {
2905  if(IsDefined( behaviorTreeEntity.damageWeapon ))
2906  {
2907  return behaviorTreeEntity.damageWeapon.specialpain;
2908  }
2909  return false;
2910 }
2911 
2912 function private ‪shouldChooseSpecialProneDeath( behaviorTreeEntity )
2913 {
2914  stance = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪STANCE );
2915  return (stance == ‪STANCE_PRONE_ON_BACK || stance == ‪STANCE_PRONE_ON_FRONT);
2916 }
2917 
2918 function private ‪setupExplosionAnimScale( entity, asmStateName )
2919 {
2920  self.animtranslationScale = 2.0;
2921  self ASMSetAnimationRate( 0.7 );
2922 
2923  return ‪BHTN_SUCCESS;
2924 }
2925 
2926 /*
2928 "Function Name: isBalconyDeath \n"
2929 <br/>"Summary: returns true if AI was killed while on a balcony node.\n"
2930 <br/>"Mandatory Argument(s): \n"
2931 <br/>"Optional Argument(s): \n"
2932 "Module: Behavior \n"
2934 */
2935 function ‪isBalconyDeath( behaviorTreeEntity )
2936 {
2937  //do i have a node?
2938  if( !isDefined(behaviorTreeEntity.node) )
2939  return false;
2940 
2941  if(!((behaviorTreeEntity.node.spawnflags & ‪SPAWNFLAG_PATH_BALCONY) || (behaviorTreeEntity.node.spawnflags & ‪SPAWNFLAG_PATH_BALCONY_NORAILING)))
2942  {
2943  return false;
2944  }
2945 
2946  coverMode = ‪Blackboard::GetBlackBoardAttribute( behaviorTreeEntity, ‪COVER_MODE );
2947 
2948  // Don't trigger a balcony death when AI is idling at cover.
2949  if ( coverMode == ‪COVER_ALERT_MODE || coverMode == ‪COVER_MODE_NONE )
2950  {
2951  return false;
2952  }
2953 
2954  if (isDefined(behaviorTreeEntity.node.script_balconydeathchance) && RandomInt(100) > int(100.0 * behaviorTreeEntity.node.script_balconydeathchance))
2955  return false;
2956 
2957  //am i close enough to the cover node?
2958  distSQ = DistanceSquared(behaviorTreeEntity.origin,behaviorTreeEntity.node.origin);
2959  if (distSQ > ‪SQR(16))
2960  return false;
2961 
2962  // get the closest player
2963  if(isDefined(level.players) && level.players.size > 0)
2964  {
2965  closest_player = ‪util::get_closest_player( behaviorTreeEntity.origin, level.players[0].team);
2966 
2967  if(isDefined(closest_player))
2968  {
2969  //Am I in the same level as the closest player
2970  if(abs(closest_player.origin[2] - behaviorTreeEntity.origin[2]) < 100)
2971  {
2972  distance2DfromPlayerSq = Distance2DSquared(closest_player.origin, behaviorTreeEntity.origin);
2973 
2974  //Am I too close to that player
2975  if(distance2DfromPlayerSq < ‪SQR(600))
2976  {
2977  return false;
2978  }
2979  }
2980  }
2981  }
2982 
2983  self.b_balcony_death = true;
2984  return true;
2985 }
2986 
2987 
2988 /*
2990 "Function Name: balconyDeath \n"
2991 <br/>"Summary: sets the BB special_death attribute to appropriate balcony type\n"
2992 <br/>"Mandatory Argument(s): AI behaviorTreeEntity\n"
2993 <br/>"Optional Argument(s): \n"
2994 "Module: Behavior \n"
2996 */
2997 function ‪balconyDeath( behaviorTreeEntity )
2998 {
2999  behaviorTreeEntity.clamptonavmesh = 0;
3000 
3001  if( behaviorTreeEntity.node.spawnflags & ‪SPAWNFLAG_PATH_BALCONY )
3002  {
3004  }
3005  else if( behaviorTreeEntity.node.spawnflags & ‪SPAWNFLAG_PATH_BALCONY_NORAILING )
3006  {
3008  }
3009 }
3010 
3011 function ‪useCurrentPosition( entity )
3012 {
3013  entity UsePosition( entity.origin );
3014 }
3015 
3016 /*
3018 "Function Name: isUnarmed \n"
3019 <br/>"Summary: returns true if AI doesn't have a weapon.\n"
3020 <br/>"Mandatory Argument(s): \n"
3021 <br/>"Optional Argument(s): \n"
3022 "Module: Behavior \n"
3024 */
3025 function ‪isUnarmed( behaviorTreeEntity )
3026 {
3027  if ( behaviorTreeEntity.weapon == level.weaponNone )
3028  {
3029  return true;
3030  }
3031 
3032  return false;
3033 }
3034 
3035 /*
3037 "Function Name: forceRagdoll \n"
3038 <br/>"Summary: Starts ragdoll on the entity.\n"
3039 <br/>"Mandatory Argument(s): \n"
3040 <br/>"Optional Argument(s): \n"
3041 "Module: Behavior \n"
3043 */
3044 function ‪forceRagdoll( entity )
3045 {
3046  entity StartRagdoll();
3047 }
3048 
3049 
3050 
3052 {
3053  self endon( "death" );
3054  if( !isDefined( ai.laserstatus ))
3055  {
3056  ai.laserstatus = false;
3057  }
3058 
3059  sniper_glint = "lensflares/fx_lensflare_sniper_glint";
3060 
3061  While( 1 )
3062  {
3063  self waittill( "about_to_fire" );
3064  if( ai.laserstatus !== true )
3065  {
3066  ai LaserOn();
3067  ai.laserstatus = true;
3068 
3069  if( ai.team != "allies" )
3070  {
3071  tag = ai GetTagOrigin( "tag_glint");
3072 
3073  if( isDefined( tag ))
3074  {
3075  playfxontag( sniper_glint , ai , "tag_glint" );
3076  }
3077  else
3078  {
3079  type = ‪STR( ai.classname );
3080  /#println( "AI " + type + " does not have a tag_glint to play sniper glint effects from, playing from tag_eye" );#/
3081  playfxontag( sniper_glint , ai , "tag_eye" );
3082  }
3083  }
3084  }
3085  }
3086 
3087 }
3088 
3089 
3091 {
3092  self endon( "death" );
3093 
3094  While( 1 )
3095  {
3096  self waittill( "stopped_firing" );
3097  if( ai.laserstatus === true )
3098  {
3099  ai LaserOff();
3100  ai.laserstatus = false;
3101  }
3102  }
3103 
3104 }
3105 
3106 function private ‪isInPhalanx( entity )
3107 {
3108  return entity ‪ai::get_behavior_attribute( "phalanx" );
3109 }
3110 
3111 function private ‪isInPhalanxStance( entity )
3112 {
3113  phalanxStance = entity ‪ai::get_behavior_attribute( "phalanx_force_stance" );
3114  currentStance = ‪Blackboard::GetBlackBoardAttribute( entity, ‪STANCE );
3115 
3116  switch ( phalanxStance )
3117  {
3118  case "stand":
3119  return currentStance == ‪STANCE_STAND;
3120  case "crouch":
3121  return currentStance == ‪STANCE_CROUCH;
3122  }
3123 
3124  return true;
3125 }
3126 
3127 function private ‪togglePhalanxStance( entity )
3128 {
3129  phalanxStance = entity ‪ai::get_behavior_attribute( "phalanx_force_stance" );
3130 
3131  switch ( phalanxStance )
3132  {
3133  case "stand":
3135  break;
3136  case "crouch":
3138  break;
3139  }
3140 }
3141 
3142 function private ‪tookFlashbangDamage( entity )
3143 {
3144  if ( IsDefined( entity.damageweapon ) && IsDefined( entity.damagemod ) )
3145  {
3146  weapon = entity.damageweapon;
3147 
3148  return entity.damagemod == "MOD_GRENADE_SPLASH" &&
3149  IsDefined( weapon.rootweapon ) &&
3150  ( IsSubStr( weapon.rootweapon.name, "flash_grenade" ) ||
3151  IsSubStr( weapon.rootweapon.name, "concussion_grenade" ) ||
3152  IsSubStr( weapon.rootweapon.name, "proximity_grenade" ) ); //checking substring for flashbang grenade variant; probably this should be a gdt checkbox 'flashbang damage' or similar
3153  }
3154  return false;
3155 }
3156 
3157 function ‪isAtAttackObject( entity )
3158 {
3159  if ( IsDefined( entity.enemyoverride ) && IsDefined( entity.enemyoverride[1] ) )
3160  {
3161  return false;
3162  }
3163 
3164  if ( IsDefined( entity.attackable ) && ‪IS_TRUE( entity.attackable.is_active ) )
3165  {
3166  if ( !IsDefined( entity.attackable_slot ) )
3167  {
3168  return false;
3169  }
3170 
3171  if ( entity IsAtGoal() )
3172  {
3173  entity.is_at_attackable = true;
3174  return true;
3175  }
3176  }
3177 
3178  return false;
3179 }
3180 
3181 function ‪shouldAttackObject( entity )
3182 {
3183  if ( IsDefined( entity.enemyoverride ) && IsDefined( entity.enemyoverride[1] ) )
3184  {
3185  return false;
3186  }
3187 
3188  if ( IsDefined( entity.attackable ) && ‪IS_TRUE( entity.attackable.is_active ) )
3189  {
3190  if ( ‪IS_TRUE( entity.is_at_attackable ) )
3191  {
3192  return true;
3193  }
3194  }
3195 
3196  return false;
3197 }
3198 
‪scriptStartRagdoll
‪function scriptStartRagdoll(behaviorTreeEntity)
Definition: archetype_utility.gsc:1045
‪IS_HITLOC_LEGS
‪#define IS_HITLOC_LEGS(__sHitLoc)
Definition: blackboard.gsh:418
‪JUKE_DISTANCE
‪#define JUKE_DISTANCE
Definition: blackboard.gsh:134
‪PREVIOUS_COVER_TYPE
‪#define PREVIOUS_COVER_TYPE
Definition: blackboard.gsh:56
‪shouldBeAggressive
‪function shouldBeAggressive(behaviorTreeEntity)
Definition: archetype_utility.gsc:1478
‪IS_HITLOC_LEFT_ARM
‪#define IS_HITLOC_LEFT_ARM(__sHitLoc)
Definition: blackboard.gsh:417
‪COVER_MODE
‪#define COVER_MODE
Definition: blackboard.gsh:41
‪shouldChooseSpecialDeath
‪function private shouldChooseSpecialDeath(behaviorTreeEntity)
Definition: archetype_utility.gsc:2903
‪wasAtCoverNode
‪function wasAtCoverNode()
Definition: archetype_utility.gsc:781
‪MAX_MELEE_PLAYER_ATTACKERS
‪#define MAX_MELEE_PLAYER_ATTACKERS
Definition: behavior.gsh:64
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪isBalconyDeath
‪function isBalconyDeath(behaviorTreeEntity)
Definition: archetype_utility.gsc:2935
‪shouldOnlyFireAccurately
‪function shouldOnlyFireAccurately(behaviorTreeEntity)
Definition: archetype_utility.gsc:1461
‪clampFrustration
‪function clampFrustration(frustrationLevel)
Definition: archetype_utility.gsc:1089
‪SPAWNFLAG_PATH_BALCONY_NORAILING
‪#define SPAWNFLAG_PATH_BALCONY_NORAILING
Definition: shared.gsh:86
‪chooseFrontCoverDirection
‪function chooseFrontCoverDirection(behaviorTreeEntity)
‪Sets the cover direction blackboard to the front direction.
Definition: archetype_utility.gsc:2215
‪RemoveAIOverrideDamageCallback
‪function RemoveAIOverrideDamageCallback(entity, callback)
Definition: archetype_utility.gsc:577
‪COVER_RIGHT_OFFSET
‪#define COVER_RIGHT_OFFSET
Definition: behavior.gsh:24
‪MELEE_ENEMY_TYPE_FIREFLY
‪#define MELEE_ENEMY_TYPE_FIREFLY
Definition: blackboard.gsh:410
‪shouldReactToNewEnemy
‪function shouldReactToNewEnemy(behaviorTreeEntity)
Definition: archetype_utility.gsc:1344
‪LOOKAHEAD_ANGLE
‪#define LOOKAHEAD_ANGLE
Definition: blackboard.gsh:77
‪shouldMelee
‪function shouldMelee(entity)
Definition: archetype_utility.gsc:2707
‪LOCOMOTION_MOVING_PAIN_SHORT
‪#define LOCOMOTION_MOVING_PAIN_SHORT
Definition: blackboard.gsh:323
‪BB_GetDamageMOD
‪function BB_GetDamageMOD()
Definition: archetype_utility.gsc:482
‪YAW_TO_COVER
‪#define YAW_TO_COVER
Definition: blackboard.gsh:44
‪TRACKING_TURN_YAW
‪#define TRACKING_TURN_YAW
Definition: blackboard.gsh:34
‪BB_GetAwareness
‪function private BB_GetAwareness()
Definition: archetype_utility.gsc:232
‪SPAWNFLAG_PATH_BALCONY
‪#define SPAWNFLAG_PATH_BALCONY
Definition: shared.gsh:83
‪AddAIOverrideDamageCallback
‪function AddAIOverrideDamageCallback(entity, callback, addToFront)
Definition: archetype_utility.gsc:542
‪refillAmmo
‪function refillAmmo(behaviorTreeEntity)
Definition: archetype_utility.gsc:1759
‪setCurrentWeapon
‪function setCurrentWeapon(weapon)
Definition: archetype_utility.gsc:2152
‪BT_REGISTER_API
‪#define BT_REGISTER_API(name, function)
Definition: behavior.gsh:1
‪LOCOMOTION_MOVING_PAIN_DIST_SHORT
‪#define LOCOMOTION_MOVING_PAIN_DIST_SHORT
Definition: blackboard.gsh:319
‪DAMAGE_DIRECTION_RIGHT
‪#define DAMAGE_DIRECTION_RIGHT
Definition: blackboard.gsh:333
‪NODE_TYPE_COVER
‪#define NODE_TYPE_COVER(_node)
Definition: utility.gsh:17
‪inGrenadeBlastRadius
‪function inGrenadeBlastRadius(entity)
Definition: archetype_utility.gsc:1428
‪NODE_COVER_STAND
‪#define NODE_COVER_STAND(_node)
Definition: utility.gsh:9
‪ActorGetPredictedYawToEnemy
‪function ActorGetPredictedYawToEnemy(entity, lookAheadTime)
Definition: archetype_utility.gsc:627
‪THROW_DISTANCE
‪#define THROW_DISTANCE
Definition: blackboard.gsh:37
‪locomotionShouldStealth
‪function locomotionShouldStealth(behaviorTreeEntity)
Definition: archetype_utility.gsc:2335
‪preShootLaserAndGlintOn
‪function preShootLaserAndGlintOn(ai)
Definition: archetype_utility.gsc:3051
‪LOCOMOTION_MOVING_PAIN_DIST_MED
‪#define LOCOMOTION_MOVING_PAIN_DIST_MED
Definition: blackboard.gsh:320
‪setupChargeMeleeAttack
‪function private setupChargeMeleeAttack(behaviorTreeEntity)
Definition: archetype_utility.gsc:2844
‪forceRagdoll
‪function forceRagdoll(entity)
Definition: archetype_utility.gsc:3044
‪AddAIOverrideKilledCallback
‪function AddAIOverrideKilledCallback(entity, callback)
Definition: archetype_utility.gsc:618
‪isUnarmed
‪function isUnarmed(behaviorTreeEntity)
Definition: archetype_utility.gsc:3025
‪STAIRCASE_NUM_STEPS
‪#define STAIRCASE_NUM_STEPS
Definition: blackboard.gsh:374
‪BSM_REGISTER_API
‪#define BSM_REGISTER_API(name, scriptFunction)
Definition: behavior_state_machine.gsh:17
‪shouldStealthResume
‪function shouldStealthResume(behaviorTreeEntity)
Definition: archetype_utility.gsc:2380
‪CONTEXT_2
‪#define CONTEXT_2
Definition: blackboard.gsh:17
‪notCrouchingCondition
‪function notCrouchingCondition(behaviorTreeEntity)
Definition: archetype_utility.gsc:1035
‪BB_GetHighestStance
‪function BB_GetHighestStance()
Definition: archetype_utility.gsc:278
‪chooseBetterCoverService
‪function private chooseBetterCoverService(behaviorTreeEntity)
Definition: archetype_utility.gsc:1719
‪DEFAULT_ENEMY_YAW
‪#define DEFAULT_ENEMY_YAW
Definition: archetype_utility.gsc:672
‪useCoverNodeWrapper
‪function useCoverNodeWrapper(behaviorTreeEntity, node)
Definition: archetype_utility.gsc:1495
‪rapsKilled
‪function rapsKilled(behaviorTreeEntity)
Definition: archetype_utility.gsc:2608
‪hasEnemy
‪function hasEnemy(behaviorTreeEntity)
Definition: archetype_utility.gsc:1803
‪DAMAGE_DIRECTION_FRONT
‪#define DAMAGE_DIRECTION_FRONT
Definition: blackboard.gsh:330
‪SPECIAL_DEATH_BALCONY_NORAIL
‪#define SPECIAL_DEATH_BALCONY_NORAIL
Definition: blackboard.gsh:339
‪ARRIVAL_STANCE
‪#define ARRIVAL_STANCE
Definition: blackboard.gsh:25
‪CORNER_PREDICTOR_STATUS_EXITING_COVER
‪#define CORNER_PREDICTOR_STATUS_EXITING_COVER
Definition: blackboard.gsh:304
‪flagEnemyUnAttackableService
‪function flagEnemyUnAttackableService(behaviorTreeEntity)
Definition: archetype_utility.gsc:1208
‪HITLOC_GROIN
‪#define HITLOC_GROIN
Definition: blackboard.gsh:406
‪HITLOC_RIGHT_ARM
‪#define HITLOC_RIGHT_ARM
Definition: blackboard.gsh:401
‪setPrimaryWeapon
‪function setPrimaryWeapon(weapon)
Definition: archetype_utility.gsc:2163
‪hasAmmo
‪function hasAmmo(behaviorTreeEntity)
Definition: archetype_utility.gsc:1776
‪RELATIVE_DIR_FRONT
‪#define RELATIVE_DIR_FRONT
Definition: blackboard.gsh:295
‪TRACKING_TURN_GIVE_UP_TIME
‪#define TRACKING_TURN_GIVE_UP_TIME
Definition: archetype_utility.gsc:981
‪BB_GetDamageTaken
‪function BB_GetDamageTaken()
Definition: archetype_utility.gsc:492
‪RegisterBehaviorScriptFunctions
‪function autoexec RegisterBehaviorScriptFunctions()
Definition: archetype_utility.gsc:29
‪BB_ActorGetDamageLocation
‪function BB_ActorGetDamageLocation()
Definition: archetype_utility.gsc:372
‪DAMAGE_HEAVY
‪#define DAMAGE_HEAVY
Definition: blackboard.gsh:290
‪BT_REGISTER_ACTION_SIMPLE
‪#define BT_REGISTER_ACTION_SIMPLE(name)
Definition: behavior.gsh:7
‪PATROL_DISABLED
‪#define PATROL_DISABLED
Definition: blackboard.gsh:81
‪RELATIVE_DIR_LEFT
‪#define RELATIVE_DIR_LEFT
Definition: blackboard.gsh:296
‪NODE_COVER_PILLAR
‪#define NODE_COVER_PILLAR(_node)
Definition: utility.gsh:8
‪NODE_COVER_LEFT
‪#define NODE_COVER_LEFT(_node)
Definition: utility.gsh:6
‪BHTN_RUNNING
‪#define BHTN_RUNNING
Definition: behavior_tree.gsh:9
‪HAS_ENEMY
‪#define HAS_ENEMY
Definition: blackboard.gsh:84
‪BB_REGISTER_ATTRIBUTE
‪#define BB_REGISTER_ATTRIBUTE(name, defaultValue, getter)
Definition: blackboard.gsh:1
‪BB_ActorGetTrackingTurnYaw
‪function BB_ActorGetTrackingTurnYaw()
Definition: archetype_utility.gsc:982
‪NEXT_CHARGE_MELEE_TIME
‪#define NEXT_CHARGE_MELEE_TIME
Definition: behavior.gsh:60
‪isStanceAllowedAtNode
‪function isStanceAllowedAtNode(stance, node)
Definition: archetype_utility.gsc:2094
‪BB_GetWeaponClass
‪function BB_GetWeaponClass()
Definition: archetype_utility.gsc:1018
‪isFrustrated
‪function isFrustrated(behaviorTreeEntity)
Definition: archetype_utility.gsc:1081
‪IS_HITLOC_HIPS
‪#define IS_HITLOC_HIPS(__sHitLoc)
Definition: blackboard.gsh:415
‪LOCOMOTION_ARRIVAL_DISTANCE
‪#define LOCOMOTION_ARRIVAL_DISTANCE
Definition: blackboard.gsh:66
‪BB_ActorGetEnemyYaw
‪function BB_ActorGetEnemyYaw()
Definition: archetype_utility.gsc:673
‪CORNER_PREDICTOR_STATUS_EXITING_EXPOSED
‪#define CORNER_PREDICTOR_STATUS_EXITING_EXPOSED
Definition: blackboard.gsh:305
‪ARCHETYPE_VEHICLE_RAPS
‪#define ARCHETYPE_VEHICLE_RAPS
Definition: archetype_utility.gsc:23
‪COVER_LEFT_OFFSET
‪#define COVER_LEFT_OFFSET
Definition: behavior.gsh:23
‪COVER_MODE_NONE
‪#define COVER_MODE_NONE
Definition: blackboard.gsh:108
‪GET_YAW
‪#define GET_YAW(__self, __org)
Definition: utility.gsh:26
‪DAMAGE_DIRECTION
‪#define DAMAGE_DIRECTION
Definition: blackboard.gsh:29
‪MELEE_YAW_THRESHOLD
‪#define MELEE_YAW_THRESHOLD
Definition: behavior.gsh:61
‪burnedKilled
‪function burnedKilled(behaviorTreeEntity)
Definition: archetype_utility.gsc:2589
‪DAMAGE_TAKEN
‪#define DAMAGE_TAKEN
Definition: blackboard.gsh:33
‪LOCOMOTION_MOVING_PAIN_DIST_LONG
‪#define LOCOMOTION_MOVING_PAIN_DIST_LONG
Definition: blackboard.gsh:321
‪setSecondaryWeapon
‪function setSecondaryWeapon(weapon)
Definition: archetype_utility.gsc:2172
‪BB_GetLocomotionFaceEnemyQuadrant
‪function BB_GetLocomotionFaceEnemyQuadrant()
Definition: archetype_utility.gsc:879
‪electrifiedKilled
‪function electrifiedKilled(behaviorTreeEntity)
Definition: archetype_utility.gsc:2564
‪HasAiAttribute
‪function HasAiAttribute(entity, attribute)
Definition: ai_interface.gsc:132
‪BB_GetCurrentCoverNodeType
‪function BB_GetCurrentCoverNodeType()
Definition: archetype_utility.gsc:316
‪HITLOC_HIPS
‪#define HITLOC_HIPS
Definition: blackboard.gsh:404
‪SetBlackBoardAttribute
‪function SetBlackBoardAttribute(entity, attributeName, attributeValue)
Definition: blackboard.gsc:56
‪COVER_PILLAR_RIGHT_OFFSET
‪#define COVER_PILLAR_RIGHT_OFFSET
Definition: behavior.gsh:28
‪LOCOMOTION_FACE_ENEMY_NONE
‪#define LOCOMOTION_FACE_ENEMY_NONE
Definition: blackboard.gsh:71
‪canSeeEnemyWrapper
‪function canSeeEnemyWrapper()
Definition: archetype_utility.gsc:1947
‪BB_GetCurrentLocationCoverNodeType
‪function BB_GetCurrentLocationCoverNodeType()
Definition: archetype_utility.gsc:331
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪HEAVY_DAMAGE_RATIO
‪#define HEAVY_DAMAGE_RATIO
Definition: blackboard.gsh:287
‪GetBlackBoardAttribute
‪function GetBlackBoardAttribute(entity, attributeName)
Definition: blackboard.gsc:32
‪LOCOMOTION_ARRIVAL_YAW
‪#define LOCOMOTION_ARRIVAL_YAW
Definition: blackboard.gsh:64
‪STANCE_PRONE_ON_FRONT
‪#define STANCE_PRONE_ON_FRONT
Definition: blackboard.gsh:277
‪BB_ActorHasEnemy
‪function BB_ActorHasEnemy()
Definition: archetype_utility.gsc:660
‪BB_GetStairsNumSkipSteps
‪function private BB_GetStairsNumSkipSteps()
Definition: archetype_utility.gsc:202
‪TACTICAL_WALK_SHORT_DIST_SQ
‪#define TACTICAL_WALK_SHORT_DIST_SQ
Definition: behavior.gsh:11
‪SQR
‪#define SQR(__var)
Definition: shared.gsh:293
‪GetAngleUsingDirection
‪function GetAngleUsingDirection(direction)
Definition: archetype_utility.gsc:767
‪GREEN
‪#define GREEN
Definition: shared.gsh:176
‪LOCOMOTION_FACE_ENEMY_QUADRANT_PREVIOUS
‪#define LOCOMOTION_FACE_ENEMY_QUADRANT_PREVIOUS
Definition: blackboard.gsh:69
‪RegisterUtilityBlackboardAttributes
‪function RegisterUtilityBlackboardAttributes()
Definition: archetype_utility.gsc:139
‪getAimPitchToEnemyFromNode
‪function getAimPitchToEnemyFromNode(behaviorTreeEntity, node, enemy)
‪Returns the pitch angles between a node and an enemy behaviorTreeEntity.
Definition: archetype_utility.gsc:2206
‪BB_GetCoverConcealed
‪function BB_GetCoverConcealed()
Definition: archetype_utility.gsc:321
‪shouldMutexMelee
‪function shouldMutexMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:2663
‪STAIR_SKIP_6
‪#define STAIR_SKIP_6
Definition: blackboard.gsh:362
‪STAIRCASE_STATE
‪#define STAIRCASE_STATE
Definition: blackboard.gsh:348
‪explosiveKilled
‪function explosiveKilled(behaviorTreeEntity)
Definition: archetype_utility.gsc:2488
‪MELEE_NEAR_RANGE_SQ
‪#define MELEE_NEAR_RANGE_SQ
Definition: behavior.gsh:57
‪STAIRCASE_NUM_TOTAL_STEPS
‪#define STAIRCASE_NUM_TOTAL_STEPS
Definition: blackboard.gsh:373
‪RED
‪#define RED
Definition: shared.gsh:175
‪shouldChooseSpecialProneDeath
‪function private shouldChooseSpecialProneDeath(behaviorTreeEntity)
Definition: archetype_utility.gsc:2912
‪COVER_RIGHT
‪#define COVER_RIGHT
Definition: blackboard.gsh:93
‪BB_ActorGetPerfectEnemyYaw
‪function BB_ActorGetPerfectEnemyYaw()
Definition: archetype_utility.gsc:687
‪isSafeFromGrenades
‪function isSafeFromGrenades(entity)
Definition: archetype_utility.gsc:1382
‪tryGoingToClosestNodeToEnemyBehavior
‪function tryGoingToClosestNodeToEnemyBehavior(behaviorTreeEntity)
Definition: archetype_utility.gsc:1283
‪togglePhalanxStance
‪function private togglePhalanxStance(entity)
Definition: archetype_utility.gsc:3127
‪STAIR_SKIP_3
‪#define STAIR_SKIP_3
Definition: blackboard.gsh:361
‪DAMAGE_LOCATION
‪#define DAMAGE_LOCATION
Definition: blackboard.gsh:28
‪CHARGE_RANGE_SQ_VS_PLAYER
‪#define CHARGE_RANGE_SQ_VS_PLAYER
Definition: behavior.gsh:53
‪STANCE
‪#define STANCE
Definition: blackboard.gsh:36
‪isInPhalanxStance
‪function private isInPhalanxStance(entity)
Definition: archetype_utility.gsc:3111
‪shouldChargeMelee
‪function shouldChargeMelee(entity)
Definition: archetype_utility.gsc:2796
‪COVER_PILLAR_LEFT_OFFSET
‪#define COVER_PILLAR_LEFT_OFFSET
Definition: behavior.gsh:27
‪STANCE_STAND
‪#define STANCE_STAND
Definition: blackboard.gsh:273
‪DESIRED_STANCE
‪#define DESIRED_STANCE
Definition: blackboard.gsh:18
‪SPECIAL_DEATH_NONE
‪#define SPECIAL_DEATH_NONE
Definition: blackboard.gsh:340
‪LOCOMOTION_FACE_ENEMY_LEFT
‪#define LOCOMOTION_FACE_ENEMY_LEFT
Definition: blackboard.gsh:73
‪has_behavior_attribute
‪function has_behavior_attribute(attribute)
Definition: ai_shared.gsc:198
‪useCurrentPosition
‪function useCurrentPosition(entity)
Definition: archetype_utility.gsc:3011
‪updateFrustrationLevel
‪function updateFrustrationLevel(entity)
Definition: archetype_utility.gsc:1114
‪LOCOMOTION_MOTION_ANGLE
‪#define LOCOMOTION_MOTION_ANGLE
Definition: blackboard.gsh:60
‪recentlySawEnemy
‪function recentlySawEnemy(behaviorTreeEntity)
Definition: archetype_utility.gsc:1442
‪NODE_EXPOSED
‪#define NODE_EXPOSED(_node)
Definition: utility.gsh:11
‪BB_GetDamageWeapon
‪function BB_GetDamageWeapon()
Definition: archetype_utility.gsc:467
‪MELEE_RANGE_SQ
‪#define MELEE_RANGE_SQ
Definition: behavior.gsh:54
‪REACT_YAW
‪#define REACT_YAW
Definition: blackboard.gsh:89
‪ENABLE_BLACKBOARD_DEBUG_TRACKING
‪#define ENABLE_BLACKBOARD_DEBUG_TRACKING(self)
Definition: blackboard.gsh:7
‪shouldChooseSpecialPain
‪function private shouldChooseSpecialPain(behaviorTreeEntity)
Definition: archetype_utility.gsc:2892
‪PERFECT_ENEMY_YAW
‪#define PERFECT_ENEMY_YAW
Definition: blackboard.gsh:88
‪LOCOMOTION_EXIT_YAW
‪#define LOCOMOTION_EXIT_YAW
Definition: blackboard.gsh:63
‪LOCOMOTION_TURN_YAW
‪#define LOCOMOTION_TURN_YAW
Definition: blackboard.gsh:61
‪COVER_TYPE
‪#define COVER_TYPE
Definition: blackboard.gsh:54
‪AGGRESSIVE_BOOST_TIME
‪#define AGGRESSIVE_BOOST_TIME
Definition: archetype_utility.gsc:1103
‪NODE_COVER_RIGHT
‪#define NODE_COVER_RIGHT(_node)
Definition: utility.gsh:7
‪RegisterAIvsAIMeleeBehaviorFunctions
‪function RegisterAIvsAIMeleeBehaviorFunctions()
Definition: archetype_aivsaimelee.gsc:64
‪hasCloseEnemyToMelee
‪function hasCloseEnemyToMelee(entity)
Definition: archetype_utility.gsc:2761
‪AST_AWARENESS
‪#define AST_AWARENESS
Definition: blackboard.gsh:343
‪balconyDeath
‪function balconyDeath(behaviorTreeEntity)
Definition: archetype_utility.gsc:2997
‪setNextFindBestCoverTime
‪function setNextFindBestCoverTime(behaviorTreeEntity, node)
Definition: archetype_utility.gsc:1512
‪dropRiotshield
‪function dropRiotshield(behaviorTreeEntity)
Definition: archetype_utility.gsc:2543
‪RELATIVE_DIR_RIGHT
‪#define RELATIVE_DIR_RIGHT
Definition: blackboard.gsh:297
‪BB_GetLocomotionFaceEnemyQuadrantPrevious
‪function BB_GetLocomotionFaceEnemyQuadrantPrevious()
Definition: archetype_utility.gsc:292
‪stealthReactCondition
‪function private stealthReactCondition(entity)
Definition: archetype_utility.gsc:2403
‪ISNODEDONTRIGHT
‪#define ISNODEDONTRIGHT(__node)
Definition: utility.gsh:2
‪LOCOMOTION_FACE_ENEMY_FRONT
‪#define LOCOMOTION_FACE_ENEMY_FRONT
Definition: blackboard.gsh:72
‪hasLowAmmo
‪function hasLowAmmo(behaviorTreeEntity)
Definition: archetype_utility.gsc:1784
‪MELEE_YAW_THRESHOLDNEAR
‪#define MELEE_YAW_THRESHOLDNEAR
Definition: behavior.gsh:62
‪SPECIAL_DEATH
‪#define SPECIAL_DEATH
Definition: blackboard.gsh:337
‪STR
‪#define STR(__var)
Definition: shared.gsh:297
‪shouldTacticalWalk
‪function shouldTacticalWalk(behaviorTreeEntity)
Definition: archetype_utility.gsc:2232
‪PREVIOUS_COVER_DIRECTION
‪#define PREVIOUS_COVER_DIRECTION
Definition: blackboard.gsh:47
‪AST_AWARENESS_PREVIOUS
‪#define AST_AWARENESS_PREVIOUS
Definition: blackboard.gsh:344
‪STANCE_PRONE_ON_BACK
‪#define STANCE_PRONE_ON_BACK
Definition: blackboard.gsh:276
‪COVER_CROUCH_OFFSET
‪#define COVER_CROUCH_OFFSET
Definition: behavior.gsh:25
‪trackCoverParamsService
‪function trackCoverParamsService(behaviorTreeEntity)
Definition: archetype_utility.gsc:1527
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪shouldNormalMelee
‪function shouldNormalMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:2701
‪MIN_EXITYAW_DISTANCE_SQ
‪#define MIN_EXITYAW_DISTANCE_SQ
Definition: blackboard.gsh:310
‪NODE_SUPPORTS_STANCE_CROUCH
‪#define NODE_SUPPORTS_STANCE_CROUCH(__node)
Definition: utility.gsh:21
‪BB_GetDamageWeaponClass
‪function BB_GetDamageWeaponClass()
Definition: archetype_utility.gsc:447
‪shouldStopMoving
‪function shouldStopMoving(behaviorTreeEntity)
Definition: archetype_utility.gsc:2142
‪LOCOMOTION_INPLACE_PAIN
‪#define LOCOMOTION_INPLACE_PAIN
Definition: blackboard.gsh:327
‪stealthIdleTerminate
‪function private stealthIdleTerminate(behaviorTreeEntity)
Definition: archetype_utility.gsc:2441
‪CORNER_PREDICTOR_STATUS_STRAIGHT_LINE_TO_GOAL
‪#define CORNER_PREDICTOR_STATUS_STRAIGHT_LINE_TO_GOAL
Definition: blackboard.gsh:303
‪setupExplosionAnimScale
‪function private setupExplosionAnimScale(entity, asmStateName)
Definition: archetype_utility.gsc:2918
‪LOCOMOTION_MOVING_PAIN_MED
‪#define LOCOMOTION_MOVING_PAIN_MED
Definition: blackboard.gsh:324
‪LOCOMOTION_FACE_ENEMY_RIGHT
‪#define LOCOMOTION_FACE_ENEMY_RIGHT
Definition: blackboard.gsh:74
‪IS_HITLOC_RIGHT_ARM
‪#define IS_HITLOC_RIGHT_ARM(__sHitLoc)
Definition: blackboard.gsh:416
‪FIRE_MODE
‪#define FIRE_MODE
Definition: blackboard.gsh:40
‪LOCOMOTION_FACE_ENEMY_BACK
‪#define LOCOMOTION_FACE_ENEMY_BACK
Definition: blackboard.gsh:75
‪shouldStealth
‪function shouldStealth(behaviorTreeEntity)
Definition: archetype_utility.gsc:2296
‪ARRAY_ADD
‪#define ARRAY_ADD(__array, __item)
Definition: shared.gsh:304
‪isLastKnownEnemyPositionApproachable
‪function isLastKnownEnemyPositionApproachable(behaviorTreeEntity)
Definition: archetype_utility.gsc:1222
‪COVER_FRONT_DIRECTION
‪#define COVER_FRONT_DIRECTION
Definition: blackboard.gsh:50
‪locomotionShouldPatrol
‪function locomotionShouldPatrol(behaviorTreeEntity)
Definition: archetype_utility.gsc:2461
‪tryStoppingService
‪function tryStoppingService(behaviorTreeEntity)
Definition: archetype_utility.gsc:2120
‪cleanupMelee
‪function private cleanupMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:2854
‪CORNER_PREDICTOR_STATUS_SUCCESS
‪#define CORNER_PREDICTOR_STATUS_SUCCESS
Definition: blackboard.gsh:301
‪COVER_CROUCH
‪#define COVER_CROUCH
Definition: blackboard.gsh:92
‪GIB_LOCATION
‪#define GIB_LOCATION
Definition: blackboard.gsh:141
‪calculateNodeOffsetPosition
‪function calculateNodeOffsetPosition(node, nodeOffset)
Definition: archetype_utility.gsc:2042
‪COVER_CORNER_VALID_YAW_RANGE_MIN
‪#define COVER_CORNER_VALID_YAW_RANGE_MIN
Definition: behavior.gsh:20
‪DAMAGE_DIRECTION_BACK
‪#define DAMAGE_DIRECTION_BACK
Definition: blackboard.gsh:332
‪RELATIVE_DIR_BACK
‪#define RELATIVE_DIR_BACK
Definition: blackboard.gsh:298
‪ISNODEDONTLEFT
‪#define ISNODEDONTLEFT(__node)
Definition: utility.gsh:3
‪STAIRCASE_EXIT_TYPE
‪#define STAIRCASE_EXIT_TYPE
Definition: blackboard.gsh:352
‪releaseClaimNode
‪function releaseClaimNode(behaviorTreeEntity)
Definition: archetype_utility.gsc:2188
‪hasCloseEnemyToMeleeWithRange
‪function hasCloseEnemyToMeleeWithRange(entity, melee_range_sq)
Definition: archetype_utility.gsc:2767
‪TRAVERSAL_TYPE
‪#define TRAVERSAL_TYPE
Definition: blackboard.gsh:116
‪BB_GetDamageDirection
‪function BB_GetDamageDirection()
Definition: archetype_utility.gsc:344
‪cleanupChargeMeleeAttack
‪function cleanupChargeMeleeAttack(behaviorTreeEntity)
Definition: archetype_utility.gsc:2874
‪getCoverType
‪function getCoverType(node)
Definition: archetype_utility.gsc:1898
‪SPECIAL_DEATH_BALCONY
‪#define SPECIAL_DEATH_BALCONY
Definition: blackboard.gsh:338
‪LOCOMOTION_MOVING_PAIN_LONG
‪#define LOCOMOTION_MOVING_PAIN_LONG
Definition: blackboard.gsh:325
‪ENEMY_YAW
‪#define ENEMY_YAW
Definition: blackboard.gsh:87
‪array
‪function filter array
Definition: array_shared.csc:16
‪STANCE_PRONE
‪#define STANCE_PRONE
Definition: blackboard.gsh:275
‪keepClaimNode
‪function keepClaimNode(behaviorTreeEntity)
Definition: archetype_utility.gsc:2181
‪MIN_FRUSTRATION
‪#define MIN_FRUSTRATION
Definition: archetype_utility.gsc:1087
‪NODE_SUPPORTS_STANCE_STAND
‪#define NODE_SUPPORTS_STANCE_STAND(__node)
Definition: utility.gsh:20
‪MELEE_DISTANCE
‪#define MELEE_DISTANCE
Definition: blackboard.gsh:35
‪GetAiAttribute
‪function GetAiAttribute(entity, attribute)
Definition: ai_interface.gsc:118
‪ClearAIOverrideDamageCallbacks
‪function ClearAIOverrideDamageCallbacks(entity)
Definition: archetype_utility.gsc:604
‪COVER_NONE
‪#define COVER_NONE
Definition: blackboard.gsh:91
‪COVER_EXPOSED
‪#define COVER_EXPOSED
Definition: blackboard.gsh:96
‪LOCOMOTION_FACE_ENEMY_QUADRANT
‪#define LOCOMOTION_FACE_ENEMY_QUADRANT
Definition: blackboard.gsh:68
‪COVER_PILLAR
‪#define COVER_PILLAR
Definition: blackboard.gsh:97
‪prepareForExposedMelee
‪function private prepareForExposedMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:1052
‪BB_GetPreviousCoverNodeType
‪function BB_GetPreviousCoverNodeType()
Definition: archetype_utility.gsc:975
‪PATROL
‪#define PATROL
Definition: blackboard.gsh:79
‪COVER_CONCEALED
‪#define COVER_CONCEALED
Definition: blackboard.gsh:101
‪BB_ActorGetReactYaw
‪function BB_ActorGetReactYaw()
Definition: archetype_utility.gsc:702
‪IS_HITLOC_HEAD
‪#define IS_HITLOC_HEAD(__sHitLoc)
Definition: blackboard.gsh:413
‪DAMAGE_LIGHT
‪#define DAMAGE_LIGHT
Definition: blackboard.gsh:291
‪DAMAGE_DIRECTION_LEFT
‪#define DAMAGE_DIRECTION_LEFT
Definition: blackboard.gsh:331
‪BHTN_SUCCESS
‪#define BHTN_SUCCESS
Definition: behavior_tree.gsh:8
‪MAKE_ARRAY
‪#define MAKE_ARRAY(__array)
Definition: shared.gsh:303
‪shouldChooseSpecialPronePain
‪function private shouldChooseSpecialPronePain(behaviorTreeEntity)
Definition: archetype_utility.gsc:2885
‪HITLOC_LEFT_ARM
‪#define HITLOC_LEFT_ARM
Definition: blackboard.gsh:402
‪DAMAGE_WEAPON
‪#define DAMAGE_WEAPON
Definition: blackboard.gsh:32
‪BSM_REGISTER_CONDITION
‪#define BSM_REGISTER_CONDITION(name, scriptFunction)
Definition: behavior_state_machine.gsh:14
‪EXPOSED_TYPE
‪#define EXPOSED_TYPE
Definition: blackboard.gsh:58
‪COVER_STAND_OFFSET
‪#define COVER_STAND_OFFSET
Definition: behavior.gsh:26
‪PREVIOUS_COVER_MODE
‪#define PREVIOUS_COVER_MODE
Definition: blackboard.gsh:42
‪COVER_TYPE_CONCEALED
‪#define COVER_TYPE_CONCEALED
Definition: blackboard.gsh:102
‪BB_GetAwarenessPrevious
‪function private BB_GetAwarenessPrevious()
Definition: archetype_utility.gsc:241
‪LOCOMOTION_PAIN_TYPE
‪#define LOCOMOTION_PAIN_TYPE
Definition: blackboard.gsh:122
‪COVER_DIRECTION
‪#define COVER_DIRECTION
Definition: blackboard.gsh:46
‪NODE_GUARD
‪#define NODE_GUARD(_node)
Definition: utility.gsh:12
‪HITLOC_HEAD
‪#define HITLOC_HEAD
Definition: blackboard.gsh:381
‪BLEND_MELEE_RANGE_SQ
‪#define BLEND_MELEE_RANGE_SQ
Definition: behavior.gsh:55
‪GET_YAW_TO_ORIGIN180
‪#define GET_YAW_TO_ORIGIN180(__self, __org)
Definition: utility.gsh:27
‪meleeAcquireMutex
‪function meleeAcquireMutex(behaviorTreeEntity)
Definition: archetype_utility.gsc:2620
‪STAIRCASE_STEP_SKIP_NUM
‪#define STAIRCASE_STEP_SKIP_NUM
Definition: blackboard.gsh:359
‪getAimYawToEnemyFromNode
‪function getAimYawToEnemyFromNode(behaviorTreeEntity, node, enemy)
‪Returns the yaw angles between a node and an enemy behaviorTreeEntity.
Definition: archetype_utility.gsc:2198
‪MELEE_ENEMY_DISTANCE_PREDICTION_TIME
‪#define MELEE_ENEMY_DISTANCE_PREDICTION_TIME
Definition: behavior.gsh:63
‪tryRunningDirectlyToEnemyBehavior
‪function tryRunningDirectlyToEnemyBehavior(behaviorTreeEntity)
Definition: archetype_utility.gsc:1314
‪shouldAttackInChargeMelee
‪function private shouldAttackInChargeMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:2829
‪STAIRCASE_DIRECTION
‪#define STAIRCASE_DIRECTION
Definition: blackboard.gsh:369
‪STAIR_SKIP_8
‪#define STAIR_SKIP_8
Definition: blackboard.gsh:363
‪COVER_ALERT_MODE
‪#define COVER_ALERT_MODE
Definition: blackboard.gsh:113
‪COVER_CORNER_VALID_YAW_RANGE_MAX
‪#define COVER_CORNER_VALID_YAW_RANGE_MAX
Definition: behavior.gsh:19
‪BB_GetLocomotionExitYaw
‪function BB_GetLocomotionExitYaw(blackboard, yaw)
Definition: archetype_utility.gsc:792
‪tryAdvancingOnLastKnownPositionBehavior
‪function tryAdvancingOnLastKnownPositionBehavior(behaviorTreeEntity)
Definition: archetype_utility.gsc:1249
‪HITLOC_CHEST
‪#define HITLOC_CHEST
Definition: blackboard.gsh:403
‪NODE_CONCEALED
‪#define NODE_CONCEALED(_node)
Definition: utility.gsh:15
‪ENEMY
‪#define ENEMY
Definition: blackboard.gsh:83
‪TRACKING_TURN_PERFECT_INFO_DIST
‪#define TRACKING_TURN_PERFECT_INFO_DIST
Definition: archetype_utility.gsc:980
‪isCoverConcealed
‪function isCoverConcealed(node)
Definition: archetype_utility.gsc:1928
‪BB_ActorGetFatalDamageLocation
‪function BB_ActorGetFatalDamageLocation()
Definition: archetype_utility.gsc:734
‪YAW
‪#define YAW
Definition: shared.gsh:168
‪WEAPON_CLASS
‪#define WEAPON_CLASS
Definition: blackboard.gsh:38
‪_dropRiotShield
‪function private _dropRiotShield(riotshieldInfo)
Definition: archetype_utility.gsc:2498
‪JUKE_DIRECTION
‪#define JUKE_DIRECTION
Definition: blackboard.gsh:133
‪BB_GetLocomotionPainType
‪function BB_GetLocomotionPainType()
Definition: archetype_utility.gsc:918
‪MELEE_ENEMY_TYPE
‪#define MELEE_ENEMY_TYPE
Definition: blackboard.gsh:409
‪MELEE_NEAR_RANGE
‪#define MELEE_NEAR_RANGE
Definition: behavior.gsh:56
‪COVER_TYPE_UNCONCEALED
‪#define COVER_TYPE_UNCONCEALED
Definition: blackboard.gsh:103
‪attachRiotshield
‪function attachRiotshield(entity, riotshieldWeapon, riotshieldModel, riotshieldTag)
Definition: archetype_utility.gsc:2522
‪PATROL_ENABLED
‪#define PATROL_ENABLED
Definition: blackboard.gsh:80
‪shouldAttackObject
‪function shouldAttackObject(entity)
Definition: archetype_utility.gsc:3181
‪hasWeaponMalfunctioned
‪function hasWeaponMalfunctioned(behaviorTreeEntity)
Definition: archetype_utility.gsc:1368
‪stealthReactStart
‪function private stealthReactStart(behaviorTreeEntity)
Definition: archetype_utility.gsc:2417
‪DAMAGE_WEAPON_CLASS
‪#define DAMAGE_WEAPON_CLASS
Definition: blackboard.gsh:30
‪STANCE_CROUCH
‪#define STANCE_CROUCH
Definition: blackboard.gsh:274
‪isAtAttackObject
‪function isAtAttackObject(entity)
Definition: archetype_utility.gsc:3157
‪RELATIVE_DIR_NONE
‪#define RELATIVE_DIR_NONE
Definition: blackboard.gsh:294
‪DEFAULT_WEAPON
‪#define DEFAULT_WEAPON
Definition: blackboard.gsh:284
‪tookFlashbangDamage
‪function private tookFlashbangDamage(entity)
Definition: archetype_utility.gsc:3142
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪shouldChooseBetterCover
‪function shouldChooseBetterCover(behaviorTreeEntity)
Definition: archetype_utility.gsc:1567
‪chooseBetterCoverServiceCodeVersion
‪function chooseBetterCoverServiceCodeVersion(behaviorTreeEntity)
Definition: archetype_utility.gsc:1673
‪BB_ActorIsPatroling
‪function BB_ActorIsPatroling()
Definition: archetype_utility.gsc:647
‪cleanupChargeMelee
‪function private cleanupChargeMelee(behaviorTreeEntity)
Definition: archetype_utility.gsc:2862
‪getBestCoverNodeIfAvailable
‪function getBestCoverNodeIfAvailable(behaviorTreeEntity)
Definition: archetype_utility.gsc:1822
‪BB_GetLookaheadAngle
‪function BB_GetLookaheadAngle()
Definition: archetype_utility.gsc:970
‪ORANGE
‪#define ORANGE
Definition: shared.gsh:179
‪NO_ENEMY
‪#define NO_ENEMY
Definition: blackboard.gsh:85
‪COVER_STAND
‪#define COVER_STAND
Definition: blackboard.gsh:95
‪MAX_FRUSTRATION
‪#define MAX_FRUSTRATION
Definition: archetype_utility.gsc:1086
‪getHighestNodeStance
‪function getHighestNodeStance(node)
Definition: archetype_utility.gsc:2059
‪COVER_LEFT
‪#define COVER_LEFT
Definition: blackboard.gsh:94
‪FATAL_DAMAGE_LOCATION
‪#define FATAL_DAMAGE_LOCATION
Definition: blackboard.gsh:27
‪get_behavior_attribute
‪function get_behavior_attribute(attribute)
Definition: ai_shared.gsc:184
‪HITLOC_LEGS
‪#define HITLOC_LEGS
Definition: blackboard.gsh:405
‪NEAR_COVER_NODE_SQ
‪#define NEAR_COVER_NODE_SQ
Definition: archetype_utility.gsc:250
‪meleeReleaseMutex
‪function meleeReleaseMutex(behaviorTreeEntity)
Definition: archetype_utility.gsc:2639
‪stealthReactTerminate
‪function private stealthReactTerminate(behaviorTreeEntity)
Definition: archetype_utility.gsc:2429
‪CONTEXT
‪#define CONTEXT
Definition: blackboard.gsh:16
‪isInPhalanx
‪function private isInPhalanx(entity)
Definition: archetype_utility.gsc:3106
‪INVALID_EXIT_YAW
‪#define INVALID_EXIT_YAW
Definition: blackboard.gsh:311
‪chooseBestCoverNodeASAP
‪function chooseBestCoverNodeASAP(behaviorTreeEntity)
Definition: archetype_utility.gsc:1546
‪NODE_SUPPORTS_STANCE_PRONE
‪#define NODE_SUPPORTS_STANCE_PRONE(__node)
Definition: utility.gsh:22
‪postShootLaserAndGlintOff
‪function postShootLaserAndGlintOff(ai)
Definition: archetype_utility.gsc:3090
‪get_closest_player
‪function get_closest_player(org, str_team)
Definition: util_shared.gsc:1338
‪notStandingCondition
‪function notStandingCondition(behaviorTreeEntity)
Definition: archetype_utility.gsc:1025
‪DAMAGE_MOD
‪#define DAMAGE_MOD
Definition: blackboard.gsh:31
‪BB_GetYawToCoverNode
‪function private BB_GetYawToCoverNode()
Definition: archetype_utility.gsc:252
‪IS_HITLOC_CHEST
‪#define IS_HITLOC_CHEST(__sHitLoc)
Definition: blackboard.gsh:414
‪NEAR_COVER_NODE_WIDE_SQ
‪#define NEAR_COVER_NODE_WIDE_SQ
Definition: archetype_utility.gsc:251
‪NODE_COVER_CROUCH
‪#define NODE_COVER_CROUCH(_node)
Definition: utility.gsh:10
‪ThrowWeapon
‪function ThrowWeapon(weapon, positionTag, scavenger)
Definition: shared.gsc:196
‪CURRENT_LOCATION_COVER_TYPE
‪#define CURRENT_LOCATION_COVER_TYPE
Definition: blackboard.gsh:55
‪SHOULD_MELEE_CHECK_TIME
‪#define SHOULD_MELEE_CHECK_TIME
Definition: archetype_utility.gsc:2706
‪getSecondBestCoverNodeIfAvailable
‪function getSecondBestCoverNodeIfAvailable(behaviorTreeEntity)
Definition: archetype_utility.gsc:1851