Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_AIDangerReaction_GrenadeLanding.c
Go to the documentation of this file.
3 {
4  static const float GRENADE_AVOID_RADIUS = 13; // Max distance for agent to react. Must be same as in behavior tree!
5  static const float GRENADE_AVOID_RADIUS_MIN = 2; // Distance below which the reaction will be almost instantaneous (GRENADE_AVOID_REACT_MIN_TIME_MS)
6 
7  static const float GRENADE_AVOID_REACT_MIN_TIME_MS = 50; // Minimal possible delay time for grenate reaction in ms
8  static const float GRENADE_AVOID_DIST_REACT_TIME_MS = 2000; // Worst possible reaction time based on distance (GRENADE_AVOID_RADIUS)
9 
10  static const float GRENADE_AVOID_VIS_REACT_TIME_MS = 1100; // Worst possible reaction time based on grenade visiblity (behind the agent's back)
11 
12  static const float GRENADE_AVOID_DIST_CURVE_PARAM = GRENADE_AVOID_DIST_REACT_TIME_MS / Math.Pow(GRENADE_AVOID_RADIUS - GRENADE_AVOID_RADIUS_MIN, 2); // Constant for quadratic curve
13 
14  //-------------------------------------------------------------------------------------------
15  // Returns grenade visibility factor as float in range 0-1 based on agent body direction in relation to grenade
16  float GetGrenadeVisibilityFactor(GenericEntity entity, vector grenadePos)
17  {
18  vector agentTransform[3];
19  entity.GetTransform(agentTransform);
20  vector agentDir = agentTransform[2];
21 
22  vector dirToGrenade = vector.Direction(entity.GetOrigin(), grenadePos);
23  dirToGrenade.Normalize();
24 
25  float angle = vector.Dot(dirToGrenade, agentDir);
26 
27  return Math.Map(angle, -1, 1, 0, 1);
28  }
29 
30  //-------------------------------------------------------------------------------------------
31  // Returns reaction time in ms based on agent threat level
32  float GetThreatLevelReactionTime(notnull SCR_AIThreatSystem threatSystem)
33  {
34  EAIThreatState threatState = threatSystem.GetState();
35 
36  switch (threatState)
37  {
38  case EAIThreatState.SAFE:
39  {
40  return 900;
41  }
42  break;
43  case EAIThreatState.VIGILANT:
44  {
45  return 200;
46  }
47  break;
48  case EAIThreatState.ALERTED:
49  {
50  return 100;
51  }
52  break;
53  case EAIThreatState.THREATENED:
54  {
55  return 370;
56  }
57  break;
58  }
59 
60  return 1.0;
61  }
62 
63  //-------------------------------------------------------------------------------------------
64  // Returns reaction time in ms based on agent sq distance to grenade
65  float GetDistanceSQReactionTime(float distanceToGrenade)
66  {
67  // Quadratic curve from min to max distance
68  return GRENADE_AVOID_DIST_CURVE_PARAM * (
69  distanceToGrenade * distanceToGrenade -
70  2 * GRENADE_AVOID_RADIUS_MIN * distanceToGrenade +
71  GRENADE_AVOID_RADIUS_MIN * GRENADE_AVOID_RADIUS_MIN
72  );
73  }
74 
75  //-----------------------------------------------------------------------------------------------------
76  // Return utility owner faction
77  Faction GetOwnerFaction(SCR_AIUtilityComponent utility)
78  {
79  SCR_ChimeraCharacter ownerCharacter = SCR_ChimeraCharacter.Cast(utility.m_OwnerEntity);
80  if (!ownerCharacter)
81  return null;
82 
83  return ownerCharacter.GetFaction();
84  }
85 
86  //-----------------------------------------------------------------------------------------------------
87  // Return character of grenade instigator
88  SCR_ChimeraCharacter GetShooterCharacter(notnull IEntity grenadeObject)
89  {
90  GrenadeMoveComponent grenadeComp = GrenadeMoveComponent.Cast(grenadeObject.FindComponent(GrenadeMoveComponent));
91  if (!grenadeComp)
92  return null;
93 
94  Instigator shooterInst = grenadeComp.GetInstigator();
95  if (!shooterInst)
96  return null;
97 
98  return SCR_ChimeraCharacter.Cast(shooterInst.GetInstigatorEntity());
99  }
100 
101  //-----------------------------------------------------------------------------------------------------
102  // Adds grenade instigator position to group perception for potentatial investigation later
103  void AddToGroupPerception(SCR_AIUtilityComponent utility, IEntity shooter, vector observePosition)
104  {
105  AIGroup group = AIGroup.Cast(utility.GetOwner().GetParentGroup());
106  if (!group)
107  return;
108 
109  SCR_AIGroupUtilityComponent groupUtilityComp = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
110  if (!groupUtilityComp)
111  return;
112 
113  PerceptionManager perceptionMan = GetGame().GetPerceptionManager();
114  if (!perceptionMan)
115  return;
116 
117  groupUtilityComp.m_Perception.AddOrUpdateGunshot(shooter, observePosition, perceptionMan.GetTime());
118  }
119 
120  //-------------------------------------------------------------------------------------------
121  override bool PerformReaction(notnull SCR_AIUtilityComponent utility, notnull SCR_AIThreatSystem threatSystem, AIDangerEvent dangerEvent)
122  {
123  IEntity grenadeObject = dangerEvent.GetObject();
124  if (grenadeObject)
125  {
126  vector grenadePos = grenadeObject.GetOrigin();
127  vector agentPos = utility.GetOrigin();
128  float distanceToGrenade = vector.Distance(utility.GetOrigin(), grenadePos);
129  if (distanceToGrenade < GRENADE_AVOID_RADIUS)
130  {
131  vector observePosition = vector.Zero;
132  SCR_ChimeraCharacter shooter = GetShooterCharacter(grenadeObject);
133  Faction ownerFaction = GetOwnerFaction(utility);
134 
135  // Filter out friendlies
136  if (ownerFaction && shooter && !ownerFaction.IsFactionFriendly(shooter.GetFaction()))
137  AddToGroupPerception(utility, shooter, shooter.GetOrigin());
138 
139  float reactionDelay = GRENADE_AVOID_REACT_MIN_TIME_MS;
140 
141  if (distanceToGrenade > GRENADE_AVOID_RADIUS_MIN)
142  {
143  float visibilityFactor = GetGrenadeVisibilityFactor(utility.m_OwnerEntity, grenadePos);
144  float visbilityReactionTime = GRENADE_AVOID_VIS_REACT_TIME_MS * (1 - visibilityFactor);
145  float threatLevelReactionTime = GetThreatLevelReactionTime(threatSystem);
146  float distanceReactionTime = GetDistanceSQReactionTime(distanceToGrenade);
147 
148  reactionDelay += visbilityReactionTime + threatLevelReactionTime + distanceReactionTime;
149 
150  #ifdef AI_DEBUG
151  AddDebugMessage(utility, string.Format("Delayed grenade reaction (visFact: %1 visReactTime: %2ms ThreatLvlTime: %3ms distReactTime %4ms distanceToGrenade %5)", visibilityFactor, visbilityReactionTime, threatLevelReactionTime, distanceReactionTime, distanceToGrenade));
152  #endif
153  } else {
154  #ifdef AI_DEBUG
155  AddDebugMessage(utility, string.Format("Grenade distance below min treshold, quick reaction (distanceToGrenade: %1)", distanceToGrenade));
156  #endif
157  }
158 
159  SCR_AIMoveFromDangerBehavior behavior = new SCR_AIMoveFromGrenadeBehavior(utility, null, vector.Zero, grenadeObject, reactionDelay, observePosition);
160  utility.AddAction(behavior);
161  return true;
162  }
163  }
164  return false;
165  }
166 };
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
Instigator
Definition: Instigator.c:6
SCR_AIDangerReaction
Definition: SCR_AIDangerReaction.c:4
SCR_AIMoveFromGrenadeBehavior
void SCR_AIMoveFromGrenadeBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, vector dangerPos, IEntity dangerEntity, float behaviorDelay, vector observePosition)
Definition: SCR_AIMoveFromDanger.c:96
GrenadeMoveComponent
Definition: GrenadeMoveComponent.c:12
SCR_AIDangerReaction_GrenadeLanding
Definition: SCR_AIDangerReaction_GrenadeLanding.c:2
Faction
Definition: Faction.c:12
SCR_AIMoveFromDangerBehavior
Definition: SCR_AIMoveFromDanger.c:4
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