Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_AIDangerReaction_WeaponFired.c
Go to the documentation of this file.
3 {
4  protected static const float PROJECTILE_FLYBY_RADIUS = 13;
5  protected static const float PROJECTILE_FLYBY_RADIUS_SQ = PROJECTILE_FLYBY_RADIUS * PROJECTILE_FLYBY_RADIUS;
6  protected static const float AI_WEAPONFIRED_REACTION_DISTANCE = 500;
7 
8  override bool PerformReaction(notnull SCR_AIUtilityComponent utility, notnull SCR_AIThreatSystem threatSystem, AIDangerEvent dangerEvent)
9  {
10  IEntity shooter = dangerEvent.GetObject();
11 
12  if (!shooter)
13  return false;
14 
15  // Get root entity of shooter, in case it is turret in vehicle hierarchy
16  IEntity shooterRoot = shooter.GetRootParent();
17 
18  SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(utility.GetOwner());
19  if (!agent || !agent.IsEnemy(shooterRoot))
20  return false;
21 
22  vector min, max;
23  shooter.GetBounds(min, max);
24  vector lookPosition = shooter.GetOrigin() + (min + max) * 0.5;
25 
26  vector myOrigin = utility.m_OwnerEntity.GetOrigin();
27  float distance = vector.Distance(myOrigin, shooter.GetOrigin());
28 
29  bool flyby = IsFlyby(myOrigin, distance, shooter);
30 
31  if (flyby)
32  threatSystem.ThreatProjectileFlyby(dangerEvent.GetCount());
33  else
34  threatSystem.ThreatShotFired(distance, dangerEvent.GetCount());
35 
36  // Look at shooting position. Even though we add an observe behavior, we can't guarantee that
37  // some other behavior doesn't override observe behavior, in which case we might want to look at shooter in parallel.
38  utility.m_LookAction.LookAt(lookPosition, utility.m_LookAction.PRIO_DANGER_EVENT, 3.0);
39 
40  // Notify our group
41  // ! Only if we are a leader
42  AIGroup myGroup = AIGroup.Cast(utility.GetOwner().GetParentGroup());
43  if (myGroup && myGroup.GetLeaderAgent() == agent)
44  NotifyGroup(myGroup, shooterRoot, lookPosition);
45 
46  // Ignore if we have selected a target
47  // Ignore if target is too far
48  if (utility.m_CombatComponent.GetCurrentTarget() != null ||
49  distance > AI_WEAPONFIRED_REACTION_DISTANCE)
50  return false;
51 
52  // Check if we must dismount the turret
53  vector turretDismountCheckPosition = lookPosition;
54  bool mustDismountTurret = utility.m_CombatComponent.DismountTurretCondition(turretDismountCheckPosition, true);
55  if (mustDismountTurret)
56  {
57  utility.m_CombatComponent.TryAddDismountTurretActions(turretDismountCheckPosition);
58  }
59 
60  // Stare at gunshot origin
61  bool addObserveBehavior = false;
64  if (investigateBehavior && investigateBehavior.GetActionState() == EAIActionState.RUNNING)
65  {
66  if (SCR_AIObserveUnknownFireBehavior.IsNewPositionMoreRelevant(myOrigin, investigateBehavior.m_vPosition.m_Value, lookPosition))
67  addObserveBehavior = true;
68  }
69  else if (oldObserveBehavior)
70  {
71  if (SCR_AIObserveUnknownFireBehavior.IsNewPositionMoreRelevant(myOrigin, oldObserveBehavior.m_vPosition.m_Value, lookPosition))
72  addObserveBehavior = true;
73  }
74  else if (!oldObserveBehavior)
75  addObserveBehavior = true;
76 
77  if (addObserveBehavior)
78  {
79  // !!! It's important that priority of this is higher than priority of move and investigate,
80  // !!! So first we look at gunshot origin, then investigate it
81  SCR_AIObserveUnknownFireBehavior observeBehavior = new SCR_AIObserveUnknownFireBehavior(utility, null, posWorld: lookPosition, useMovement: flyby);
82  utility.AddAction(observeBehavior);
83  }
84  else if (oldObserveBehavior && flyby)
85  {
86  // Notify the existing observe behavior, make it execute movement from now on.
87  // Otherwise if first behavior was created without movement, and then a bullet flies by,
88  // the AI does not move.
89  oldObserveBehavior.SetUseMovement(true);
90  }
91 
92  return true;
93  }
94 
95  void NotifyGroup(AIGroup group, IEntity shooter, vector posWorld)
96  {
97  SCR_AIGroupUtilityComponent groupUtilityComp = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
98  if (groupUtilityComp)
99  {
100  PerceptionManager pm = GetGame().GetPerceptionManager();
101  if (pm)
102  {
103  float timestamp = pm.GetTime();
104  groupUtilityComp.m_Perception.AddOrUpdateGunshot(shooter, posWorld, timestamp);
105  }
106  }
107  }
108 
109  bool IsFlyby(vector myPos, float distanceToShooter, IEntity shooter)
110  {
111  // !!! Important for turrets - WeaponMgr is on turret entity, not vehicle root
112  BaseWeaponManagerComponent weaponMgr = BaseWeaponManagerComponent.Cast(shooter.FindComponent(BaseWeaponManagerComponent));
113  if (!weaponMgr)
114  return false;
115 
116  vector muzzleTransform[4];
117  weaponMgr.GetCurrentMuzzleTransform(muzzleTransform); // todo Ideally this should come from danger event, together with muzzle dir.
118  vector muzzlePos = muzzleTransform[3];
119  bool flyby = false;
120  if ( distanceToShooter > PROJECTILE_FLYBY_RADIUS &&
121  Math3D.IntersectionPointCylinder(myPos, muzzleTransform[3], muzzleTransform[2], PROJECTILE_FLYBY_RADIUS) )
122  {
123  // Within cylinder, but far enough, react as if projectile flew by
124  return true;
125  }
126 
127  return false;
128  }
129 };
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_AIObserveUnknownFireBehavior
Definition: SCR_AIObserveUnknownFireBehavior.c:8
SCR_AIDangerReaction
Definition: SCR_AIDangerReaction.c:4
SCR_ChimeraAIAgent
Definition: SCR_ChimeraAIAgent.c:5
distance
float distance
Definition: SCR_DestructibleTreeV2.c:29
SCR_AIDangerReaction_WeaponFired
Definition: SCR_AIDangerReaction_WeaponFired.c:2
EAIActionState
EAIActionState
Definition: EAIActionState.c:12
SCR_AIMoveAndInvestigateBehavior
Definition: SCR_AIMoveBehavior.c:53
SCR_AIThreatSystem
Definition: SCR_AIThreatSystem.c:17
BaseContainerProps
SCR_AIGoalReaction_Follow BaseContainerProps
Handles insects that are supposed to be spawned around selected prefabs defined in prefab names array...
Definition: SCR_AIGoalReaction.c:468