Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIGetFireTimes.c
Go to the documentation of this file.
7
8class SCR_AIGetFireTimes: AITaskScripted
9{
10 static const string PORT_FIRE_TIME = "FireTime";
11 static const string PORT_STABILIZATION_TIME = "StabilizationTime";
12 static const string PORT_REJECT_TIME = "RejectAimingTime";
13 static const string PORT_SHOT_SPAN = "ShotSpan";
14
15 protected static string TARGET_ENTITY_PORT = "TargetEntity";
16 protected static string TARGET_POSITION_PORT = "TargetPosition";
17 protected static string FIRE_RATE_COEF_PORT = "FireRateCoef";
18
19 static const float MIN_FIRE_RATE_COEF = 0.05;
20 static const float MAX_FIRE_RATE_COEF = 2;
21
22 [Attribute("0", uiwidget: UIWidgets.ComboBox, "Fire pattern used to calculate fire times", "", ParamEnumArray.FromEnum(EAIFirePattern))]
24
25 // Component refs
26 protected SCR_AICombatComponent m_CombatComponent;
27 protected SCR_AIConfigComponent m_ConfigComponent;
28
29 // Weapon config
31 protected float m_fShotSpan = 0.09;
32 protected int m_fBurstSize = 1;
33
34 // Weapon refs for detecting relevant changes
39
40 // Is node valid for simulation
41 protected bool m_bValid;
42
43 //------------------------------------------------------------------------------------------------
44 override void OnInit(AIAgent owner)
45 {
46 SCR_AIUtilityComponent utility = SCR_AIUtilityComponent.Cast(owner.FindComponent(SCR_AIUtilityComponent));
47 if (!utility)
48 return;
49
50 m_CombatComponent = utility.m_CombatComponent;
51 m_ConfigComponent = utility.m_ConfigComponent;
52
54 return;
55
56 // Mark valid to simulate
57 m_bValid = true;
58 }
59
60 //------------------------------------------------------------------------------------------------
61 protected static ref TStringArray s_aVarsOut = {
63 PORT_STABILIZATION_TIME,
64 PORT_REJECT_TIME,
65 PORT_SHOT_SPAN
66 };
67 override array<string> GetVariablesOut() { return s_aVarsOut; }
68
69 //------------------------------------------------------------------------------------------------
70 protected static ref TStringArray s_aVarsIn = {
71 TARGET_ENTITY_PORT,
72 TARGET_POSITION_PORT,
73 FIRE_RATE_COEF_PORT
74 };
75 override TStringArray GetVariablesIn() { return s_aVarsIn; }
76
77 //------------------------------------------------------------------------------------------------
78 // Returns currently used fire rate factor
80 {
81 // Get our internal fire rate coef
82 float fireRateCoef;
83 if (!GetVariableIn(FIRE_RATE_COEF_PORT, fireRateCoef))
84 fireRateCoef = 1;
85
86 // If fire rate is overriden in agent combat component (external API), we use user value, not our intenal one
87 float agentFRC = m_CombatComponent.GetFireRateCoef();
88 if (agentFRC != 1)
89 fireRateCoef = agentFRC;
90
91 return 1 - Math.Clamp(fireRateCoef, MIN_FIRE_RATE_COEF, MAX_FIRE_RATE_COEF);
92 }
93
94 //------------------------------------------------------------------------------------------------
95 override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
96 {
97 // Get agent's character entity
98 IEntity ownerEntity = owner.GetControlledEntity();
99
100 // Get current weapon
101 BaseWeaponComponent weapon = m_CombatComponent.GetCurrentWeapon();
102 if (!weapon || !ownerEntity || !m_bValid)
103 return ENodeResult.FAIL;
104
105 // Get current muzzle and fire rate
106 BaseMuzzleComponent muzzle = weapon.GetCurrentMuzzle();
107 if (!muzzle)
108 return ENodeResult.FAIL;
109
110 BaseFireMode fireMode = muzzle.GetCurrentFireMode();
111 if (!fireMode)
112 return ENodeResult.FAIL;
113
114 // Update config if something relevant changed
115 if (weapon != m_LastWeapon || muzzle != m_LastMuzzle || fireMode != m_LastFireMode)
116 {
117 // Update weapon type
118 m_eLastWeaponType = SCR_AIWeaponHandling.GetWeaponType(weapon, true);
119
120 // Update weapon config
121 m_WeaponConfig = m_ConfigComponent.GetWeaponTypeHandlingConfig(m_eLastWeaponType);
122
123 // Weapon data
124 m_fShotSpan = fireMode.GetShotSpan();
125 m_fBurstSize = fireMode.GetBurstSize();
126
127 // Update cache
128 m_LastWeapon = weapon;
129 m_LastMuzzle = muzzle;
130 m_LastFireMode = fireMode;
131 }
132
133 // Get fire pattern
135
136 // Get target pos
137 vector targetPos;
138 IEntity targetEntity;
139 if (GetVariableIn(TARGET_ENTITY_PORT, targetEntity))
140 targetPos = targetEntity.GetOrigin();
141 else
142 GetVariableIn(TARGET_POSITION_PORT, targetPos);
143
144 // We assume mid range to target
145 float distToTarget = 250;
146 // Get real distance if available
147 if (targetPos != vector.Zero)
148 distToTarget = vector.Distance(ownerEntity.GetOrigin(), targetPos);
149
150 // Get config values
151 float stabilizationTime = m_WeaponConfig.m_fBaseStabilizationTime;
152 float rejectionTime = m_WeaponConfig.m_fBaseRejectionTime;
153
154 // CQC Factor
155 float cqcFactor;
156 if (distToTarget < SCR_AICombatComponent.CLOSE_RANGE_COMBAT_DISTANCE)
157 cqcFactor = Math.Map(distToTarget, 5, SCR_AICombatComponent.CLOSE_RANGE_COMBAT_DISTANCE, 1, 0);
158
159 // Use weapon burst size as default
160 float burstSize = m_fBurstSize;
161
162 // Burst or suppress fire
163 if (pattern == EAIFirePattern.Burst || pattern == EAIFirePattern.Suppress)
164 {
165 // Override weapon burst size
166 if (burstSize <= 1)
167 {
168 // It's a machine gun!
169 if (m_eLastWeaponType == EWeaponType.WT_MACHINEGUN)
170 {
171 float range = 2.6;
172 float base = 1.75;
173
174 // Suppressive fire for mg
175 if (pattern == EAIFirePattern.Suppress)
176 {
177 range = 3.5;
178 base = 2.2;
179 }
180
181 stabilizationTime += Math.RandomGaussFloat(0.236, 0);
182 burstSize = base + Math.Pow(Math.RandomFloat(0, range) - 0.4, 2);
183 }
184 else
185 {
186 float range = 1.77;
187
188 // Suppressive fire for rifles
189 if (pattern == EAIFirePattern.Suppress)
190 range = 1.96;
191
192 burstSize = 0.75 + Math.Pow(Math.RandomFloat(0, range) - 0.3, 3);
193 }
194 }
195 }
196 // SemiAuto/Single fire - default
197 else
198 {
199 burstSize = Math.RandomFloat(0.1, m_fShotSpan * 1.9);
200 stabilizationTime += Math.RandomGaussFloat(0.236, 0);
201 }
202
203 // Apply CQC factor to burst size
204 burstSize -= Math.RandomGaussFloat(0.32, 0) * cqcFactor;
205
206 if (stabilizationTime > 0)
207 stabilizationTime -= Math.RandomFloat(stabilizationTime / 3, stabilizationTime) * cqcFactor * 0.85;
208 else
209 stabilizationTime = 0;
210
211 // Ger fire time
212 float fireTime = m_fShotSpan * burstSize;
213
214 // Get Agent/Group fire rate factor
215 float fireRateFactor = GetFireRateFactor();
216
217 // Apply fire rate
218 fireTime += (fireTime / 2.5) * fireRateFactor;
219 stabilizationTime += (stabilizationTime * 1.05) * fireRateFactor;
220
221 // Fire rate factor in MG stabilization
222 if (m_eLastWeaponType == EWeaponType.WT_MACHINEGUN)
223 stabilizationTime += Math.AbsFloat(Math.RandomGaussFloat(0.12, 0)) * fireRateFactor;
224
225 // Stabilization range factor
226 vector stabTimeRandRange = Vector(0.1, 0, 0.7);
227
228 // Mid or long range
229 if (distToTarget > SCR_AICombatComponent.CLOSE_RANGE_COMBAT_DISTANCE)
230 {
231 // Add factors of mid range
232 stabTimeRandRange += Vector(0.5, 0, 0.7);
233
234 // Add factors of long range
235 if (distToTarget > SCR_AICombatComponent.LONG_RANGE_COMBAT_DISTANCE)
236 stabTimeRandRange += Vector(0.7, 0, 1.5);
237 }
238
239 // Distance is main factor in stabilization time
240 stabilizationTime *= Math.RandomFloat(stabTimeRandRange[0], stabTimeRandRange[2]);
241
242 // Make sure it's always some time
243 stabilizationTime = Math.Max(stabilizationTime, 0.05);
244
246 SetVariableOut(PORT_STABILIZATION_TIME, stabilizationTime);
247 SetVariableOut(PORT_REJECT_TIME, rejectionTime);
248 SetVariableOut(PORT_SHOT_SPAN, m_fShotSpan);
249
250 return ENodeResult.SUCCESS;
251 }
252
253 //------------------------------------------------------------------------------------------------
254 static override bool VisibleInPalette() {return true;}
255
256 //------------------------------------------------------------------------------------------------
257 protected static override string GetOnHoverDescription() {return "Get all time constants for fire - it is weapon dependent";}
258};
259
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
BaseMuzzleComponent m_LastMuzzle
BaseWeaponComponent m_LastWeapon
float GetFireRateFactor()
enum EAIFirePattern PORT_FIRE_TIME
bool m_bValid
BaseFireMode m_LastFireMode
int m_fBurstSize
ref SCR_AIWeaponTypeHandlingConfig m_WeaponConfig
EAIFirePattern m_iFirePattern
EWeaponType m_eLastWeaponType
float m_fShotSpan
EAIFirePattern
@ Burst
@ Single
@ Suppress
SCR_AIPickupInventoryItemsBehavior s_aVarsOut
ref TStringArray s_aVarsIn
SCR_AICombatComponent m_CombatComponent
SCR_AIConfigComponent m_ConfigComponent
proto external vector GetOrigin()
Definition Math.c:13
proto void SetVariableOut(string name, void val)
TStringArray GetVariablesIn()
Definition Node.c:27
proto bool GetVariableIn(string name, out void val)
bool VisibleInPalette()
string GetOnHoverDescription()
Definition Node.c:30
TStringArray GetVariablesOut()
Definition Node.c:28
ENodeResult
Definition ENodeResult.c:13
SCR_FieldOfViewSettings Attribute
array< string > TStringArray
Definition Types.c:385
proto native vector Vector(float x, float y, float z)
EWeaponType
Definition EWeaponType.c:13