Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_AIUpdateTargetAttackData.c
Go to the documentation of this file.
1 class SCR_AIUpdateTargetAttackData : AITaskScripted
2 {
3  // Inputs
4  protected static const string BASE_TARGET_PORT = "BaseTarget";
5  protected static const string WEAPON_IS_READY = "WeaponReady";
6 
7 
8  // Outputs
9  protected static const string PORT_LAST_SEEN_POSITION = "LastSeenPosition";
10  protected static const string PORT_VISIBLE = "Visible";
11  protected static const string PORT_FIRE_TREE_ID = "FireTreeId";
12  static const string PORT_AIMPOINT_TYPE_0 = "AimpointType0";
13  static const string PORT_AIMPOINT_TYPE_1 = "AimpointType1";
14 
15  // These IDs must match to actual trees in attack tree
16  protected const int FIRE_TREE_INVALID = -1; // No aiming or firing is allowed at all
17  protected const int FIRE_TREE_LOOK = 0; // Looking at target without firing
18  protected const int FIRE_TREE_BURST = 1;
19  protected const int FIRE_TREE_SINGLE = 2;
20  protected const int FIRE_TREE_SUPPRESSIVE = 3;
21  protected const int FIRE_TREE_MELEE = 4;
22 
23  protected const float MELEE_MAX_DISTANCE = 2.0;
24  protected const float BURST_FIRE_MAX_DISTANCE = 50.0;
25 
26  protected SCR_AICombatComponent m_CombatComponent;
27  protected CharacterControllerComponent m_CharacterController;
28  protected PerceptionComponent m_PerceptionComponent;
29  protected SCR_AIUtilityComponent m_UtilityComponent;
30 
31  // Flag for executing some logic only once at start
32  protected bool m_bFirstSimulate = true;
33 
34  protected bool m_bWeaponHasBurstOrAuto; // Cached on first run
35 
36 
37  //-----------------------------------------------------------------------------------------------------
38  override void OnInit(AIAgent owner)
39  {
40  m_UtilityComponent = SCR_AIUtilityComponent.Cast(owner.FindComponent(SCR_AIUtilityComponent));
41 
42  IEntity myEntity = owner.GetControlledEntity();
43  if (myEntity)
44  {
45  m_CombatComponent = SCR_AICombatComponent.Cast(myEntity.FindComponent(SCR_AICombatComponent));
46  m_PerceptionComponent = PerceptionComponent.Cast(myEntity.FindComponent(PerceptionComponent));
47  m_CharacterController = CharacterControllerComponent.Cast(myEntity.FindComponent(CharacterControllerComponent));
48  }
49 
50  m_bFirstSimulate = true;
51  }
52 
53  //-----------------------------------------------------------------------------------------------------
54  override void OnAbort(AIAgent owner, Node nodeCausingAbort)
55  {
56  m_bFirstSimulate = true;
57  }
58 
59  //-----------------------------------------------------------------------------------------------------
60  override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
61  {
62  BaseTarget target;
63  GetVariableIn(BASE_TARGET_PORT, target);
64 
65  bool weaponReady;
66  GetVariableIn(WEAPON_IS_READY, weaponReady);
67 
68  if (!target || !m_CombatComponent || !m_PerceptionComponent || !m_CharacterController || !m_UtilityComponent)
69  return ENodeResult.FAIL;
70 
71  if (m_bFirstSimulate)
72  {
73  BaseWeaponComponent selectedWeaponComp;
74  int selectedMuzzleId;
75  m_CombatComponent.GetSelectedWeapon(selectedWeaponComp, selectedMuzzleId);
76  m_bWeaponHasBurstOrAuto = WeaponHasBurstOrAutoMode(selectedWeaponComp, selectedMuzzleId);
77  }
78 
79  // Last seen pos
80  SetVariableOut(PORT_LAST_SEEN_POSITION, target.GetLastSeenPosition());
81 
82  // Visible?
83  bool visible = m_CombatComponent.IsTargetVisible(target);
84  SetVariableOut(PORT_VISIBLE, visible);
85 
86  // Which fire tree to use?
87  // This must be reevaluated periodically
88  int fireTreeId = ResolveFireTree(target, visible, weaponReady);
89  SetVariableOut(PORT_FIRE_TREE_ID, fireTreeId);
90 
91  // Which aimpoints to use?
92  // We run this only once, since it's not going to change much
93  if (m_bFirstSimulate)
94  {
95  EAimPointType aimpointType0;
96  EAimPointType aimpointType1;
97  ResolveAimpointTypes(target, aimpointType0, aimpointType1);
98  SetVariableOut(PORT_AIMPOINT_TYPE_0, aimpointType0);
99  SetVariableOut(PORT_AIMPOINT_TYPE_1, aimpointType1);
100  }
101 
102  // Reset m_bFirstSimulate flag
103  m_bFirstSimulate = false;
104 
105  return ENodeResult.SUCCESS;
106  }
107 
108  //-----------------------------------------------------------------------------------------------------
109  // Evaluates which fire tree should be used
110  int ResolveFireTree(BaseTarget target, bool visible, bool weaponReady)
111  {
112  // Is aiming forbidden by combat move?
113  SCR_AIBehaviorBase executedBehavior = SCR_AIBehaviorBase.Cast(m_UtilityComponent.GetExecutedAction());
114  if (executedBehavior && executedBehavior.m_bUseCombatMove && !m_UtilityComponent.m_CombatMoveState.m_bAimAtTarget)
115  return FIRE_TREE_INVALID;
116 
117  // Is weapon not ready?
118  if (!weaponReady)
119  return FIRE_TREE_LOOK;
120 
121  BaseWeaponComponent selectedWeaponComp;
122  int selectedMuzzleId;
123  m_CombatComponent.GetSelectedWeapon(selectedWeaponComp, selectedMuzzleId);
124 
125  bool directDamage
126  float weaponMinDist, weaponMaxDist;
127  m_CombatComponent.GetSelectedWeaponProperties(weaponMinDist, weaponMaxDist, directDamage);
128 
129  if (!selectedWeaponComp)
130  return FIRE_TREE_LOOK;
131 
132  EWeaponType weaponType = selectedWeaponComp.GetWeaponType();
133 
134  float targetDistance = target.GetDistance();
135 
136  // Use melee?
137  if (targetDistance < MELEE_MAX_DISTANCE &&
138  !m_CharacterController.CanFire() &&
139  m_CharacterController.GetStance() != ECharacterStance.PRONE)
140  {
141  return FIRE_TREE_MELEE;
142  }
143 
144  // Friendly in aim?
145  if (m_PerceptionComponent.GetFriendlyInLineOfFire())
146  {
147  return FIRE_TREE_LOOK;
148  }
149 
150 
151  // Not melee
152 
153  if (targetDistance < weaponMinDist || targetDistance > weaponMaxDist)
154  {
155  // Outside weapon usage range
156  // Look at target
157 
158  return FIRE_TREE_LOOK;
159  }
160 
161 
162  // Within weapon usage range
163 
164  if (visible)
165  {
166  // Visible
167  // If machinegun, always use burst at any range
168  // For regular weapons, use burst at short range if available, otherwise single
169  if (weaponType == EWeaponType.WT_MACHINEGUN)
170  return FIRE_TREE_BURST;
171  else if (targetDistance < BURST_FIRE_MAX_DISTANCE && m_bWeaponHasBurstOrAuto)
172  return FIRE_TREE_BURST;
173  else
174  return FIRE_TREE_SINGLE;
175 
176  }
177  else
178  {
179  // Invisible
180  // Use suppressive fire or don't fire at all
181 
182  // If weapon is configured to deal indirect damage, then use it for invisible target
183  // Otherwise regular weapons can also be used to fire at hidden target,
184  // except for rocket launchers, their ammo is too valuable
185  // Also ensure we don't do suppressive fire into a wall in front of us
186 
187  float lastSeenThreshold;
188  if (weaponType == EWeaponType.WT_MACHINEGUN)
189  lastSeenThreshold = SCR_AICombatComponent.TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_MG;
190  else
191  lastSeenThreshold = SCR_AICombatComponent.TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK;
192 
193  if ((!directDamage || weaponType != EWeaponType.WT_ROCKETLAUNCHER) &&
194  target.GetTimeSinceSeen() < lastSeenThreshold &&
195  target.GetTraceFraction() > 0.5)
196  return FIRE_TREE_SUPPRESSIVE;
197  else
198  return FIRE_TREE_LOOK;
199  }
200 
201  return FIRE_TREE_LOOK;
202  }
203 
204  //-----------------------------------------------------------------------------------------------------
205  static bool WeaponHasBurstOrAutoMode(notnull BaseWeaponComponent weaponComp, int muzzleId)
206  {
207  array<BaseMuzzleComponent> muzzles = {};
208  weaponComp.GetMuzzlesList(muzzles);
209 
210  if (!muzzles.IsIndexValid(muzzleId))
211  return false;
212 
213  BaseMuzzleComponent muzzle = muzzles[muzzleId];
214  if (!muzzle)
215  return false;
216 
217  array<BaseFireMode> fireModes = {};
218  muzzle.GetFireModesList(fireModes);
219  foreach (BaseFireMode mode : fireModes)
220  {
221  EWeaponFiremodeType modeType = mode.GetFiremodeType();
222  if (modeType == EWeaponFiremodeType.Burst || modeType == EWeaponFiremodeType.Auto)
223  return true;
224  }
225  return false;
226  }
227 
228  //-----------------------------------------------------------------------------------------------------
229  void ResolveAimpointTypes(notnull BaseTarget target, EAimPointType aimpointType0, EAimPointType aimpointType1)
230  {
231  IEntity targetEntity = target.GetTargetEntity();
232  if (!targetEntity)
233  {
234  aimpointType0 = -1;
235  aimpointType1 = -1;
236  return;
237  }
238 
239  ChimeraCharacter character = ChimeraCharacter.Cast(targetEntity);
240  if (character)
241  {
242  // Characters
243 
244  if (character.IsInVehicle())
245  {
246  // Aim at head
247  aimpointType0 = EAimPointType.WEAK;
248  aimpointType1 = EAimPointType.NORMAL;
249  return;
250  }
251 
252  aimpointType0 = EAimPointType.NORMAL;
253  aimpointType1 = EAimPointType.WEAK;
254  return;
255  }
256  else
257  {
258  // Vehicles and the rest
259 
260  EWeaponType weaponType = m_CombatComponent.GetSelectedWeaponType();
261 
262  if (weaponType == EWeaponType.WT_ROCKETLAUNCHER)
263  {
264  // Rocket launcher, aim at weak point
265  aimpointType0 = EAimPointType.WEAK;
266  aimpointType1 = EAimPointType.NORMAL;
267  return;
268  }
269 
270  aimpointType0 = EAimPointType.NORMAL;
271  aimpointType1 = EAimPointType.WEAK;
272  return;
273  }
274  }
275 
276  //-----------------------------------------------------------------------------------------------------
277  protected ref TStringArray s_aVarsIn = {
278  BASE_TARGET_PORT,
279  WEAPON_IS_READY
280  };
281  override TStringArray GetVariablesIn() { return s_aVarsIn; }
282 
283  protected ref TStringArray s_aVarsOut = {
284  PORT_VISIBLE,
285  PORT_LAST_SEEN_POSITION,
286  PORT_FIRE_TREE_ID,
287  PORT_AIMPOINT_TYPE_0,
288  PORT_AIMPOINT_TYPE_1
289  };
290  override TStringArray GetVariablesOut() { return s_aVarsOut; }
291 
292  override bool VisibleInPalette() { return true; }
293 
294  override string GetOnHoverDescription() { return "Special node which is used in attack behavior"; };
295 
296 }
ECharacterStance
ECharacterStance
Definition: ECharacterStance.c:12
s_aVarsOut
SCR_AIPickupInventoryItemsBehavior s_aVarsOut
Definition: SCR_AIGetCombatMoveRequestParameters.c:149
EWeaponFiremodeType
EWeaponFiremodeType
Definition: EWeaponFiremodeType.c:12
m_PerceptionComponent
PerceptionComponent m_PerceptionComponent
Definition: SCR_AIUtilityComponent.c:13
m_CharacterController
SCR_CharacterPerceivableComponentClass m_CharacterController
BaseTarget
Definition: BaseTarget.c:12
BaseFireMode
Definition: BaseFireMode.c:12
BaseWeaponComponent
Definition: BaseWeaponComponent.c:12
m_CombatComponent
SCR_AICombatComponent m_CombatComponent
Definition: SCR_AIUtilityComponent.c:12
SCR_AIUpdateTargetAttackData
Definition: SCR_AIUpdateTargetAttackData.c:1
EWeaponType
EWeaponType
Definition: EWeaponType.c:12
BaseMuzzleComponent
Definition: BaseMuzzleComponent.c:12
SCR_AIBehaviorBase
Definition: SCR_AIBehavior.c:1
EAimPointType
EAimPointType
Definition: EAimPointType.c:12