Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AISuppressBehavior.c
Go to the documentation of this file.
1
4
5class SCR_AISuppressBehavior : SCR_AIBehaviorBase
6{
7 ref SCR_BTParamRef<SCR_AISuppressionVolumeBase> m_SuppressionVolume = new SCR_BTParamRef<SCR_AISuppressionVolumeBase>("SuppressionVolume");
8 ref SCR_BTParam<float> m_fSuppressionDuration_s = new SCR_BTParam<float>("SuppressionDuration_s");
9 ref SCR_BTParam<float> m_fFireRate = new SCR_BTParam<float>("FireRate");
10
11 //-------------------------------------------------------------------------------------------------------------------------------
12 void SCR_AISuppressBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, SCR_AISuppressionVolumeBase suppressionVolume, float suppressionDuration, float fireRate, float priorityLevel = PRIORITY_LEVEL_NORMAL)
13 {
14 m_SuppressionVolume.Init(this, suppressionVolume);
15 m_fSuppressionDuration_s.Init(this, suppressionDuration);
16 m_fFireRate.Init(this, fireRate);
17
18 SetPriority(PRIORITY_BEHAVIOR_SUPPRESS);
19 m_fPriorityLevel.m_Value = priorityLevel;
20 m_sBehaviorTree = "{447C5FFBE68FF9FE}AI/BehaviorTrees/Chimera/Soldier/SuppressBehavior.bt";
21 m_bAllowLook = false;
22
23 // Use combat movement but only on foot
24 if (utility)
25 m_bUseCombatMove = !utility.m_AIInfo.HasUnitState(EUnitState.IN_VEHICLE);
26 }
27
28 //---------------------------------------------------------------------------------------------------------------------------------
29 override void OnActionSelected()
30 {
31 super.OnActionSelected();
32 EnableFriendlyFireCheck(true);
33 }
34
35 //---------------------------------------------------------------------------------------------------------------------------------
36 override void OnActionDeselected()
37 {
38 super.OnActionDeselected();
39 EnableFriendlyFireCheck(false);
40 }
41
42 //---------------------------------------------------------------------------------------------------------------------------------
43 void EnableFriendlyFireCheck(bool enable)
44 {
45 if (m_Utility && m_Utility.m_PerceptionComponent)
46 m_Utility.m_PerceptionComponent.SetFriendlyFireCheck(enable);
47 }
48
49 //---------------------------------------------------------------------------------------------------------------------------------
50 override int GetCause()
51 {
52 return SCR_EAIBehaviorCause.COMBAT;
53 }
54};
55
56class SCR_AISuppressGroupClusterBehavior : SCR_AISuppressBehavior
57{
58 protected const int VOLUME_UPDATE_INTERVAL_MS = 1*500;
59 protected const float FIRE_RATE_SCALING_MAX_DISTANCE = 600; // Max distance for fire rate scaling
60
61 protected const float THREAT_MAX_INCREASE = 0.25; // Max increase of group threat potential per tick
62 protected const float THREAT_MAX_DECREASE = 0.15; // Max decrease of group threat per tick while in decrease period
63 protected const float THREAT_POTENTIAL_DECAY = 0.6; // How much per tick group threat potential is decaying while in decay period
64 protected const int THREAT_MAX_PEAK_DURATION_MS = 20*1000; // Max peak duration (time since threat reaching 100%), after this time we'll start decaying potential
65 protected const int THREAT_MAX_PEAK_REACTION_DURATION_MS = 15*1000; // How long we should react on reaching peak (intensification of fire rate while in peak threat)
66
68 protected SCR_AICombatComponent m_CombatComponent;
70 protected float m_fNextUpdate;
71 protected float m_fGroupThreat;
72 protected float m_fGroupThreatPotential;
73 protected bool m_bGroupThreatInPeak;
77
78 protected SCR_AITargetClusterState m_ClusterState; // Weak pointer to react on deletion
79 protected ref SCR_AISuppressionVolumeClusterBox m_Volume;
80
81 //-------------------------------------------------------------------------------------------------------------------------------
82 void SCR_AISuppressGroupClusterBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, SCR_AISuppressionVolumeBase suppressionVolume, float suppressionDuration, float fireRate, float priorityLevel = PRIORITY_LEVEL_NORMAL, SCR_AITargetClusterState clusterState = null)
83 {
84 m_ThreatSystem = m_Utility.m_ThreatSystem;
85 m_CombatComponent = utility.m_CombatComponent;
87 m_Agent = m_CombatComponent.GetAiAgent();
88
89 if (clusterState)
90 {
91 m_ClusterState = clusterState;
92 m_Volume = new SCR_AISuppressionVolumeClusterBox(vector.Zero, vector.Zero);
93 m_SuppressionVolume.m_Value = m_Volume;
94 }
95 else
96 {
97 Print("SCR_AISuppressGroupClusterBehavior failed, no cluster state provided", LogLevel.ERROR);
98 Fail();
99 }
100 }
101
102 //-------------------------------------------------------------------------------------------------------------------------------
106
107 //-------------------------------------------------------------------------------------------------------------------------------
108 protected float GetDistance(notnull SCR_AITargetClusterState clusterState)
109 {
110 if (!m_Utility || !m_Utility.m_OwnerEntity)
111 return 1;
112
113 return vector.Distance(m_Utility.m_OwnerEntity.GetOrigin(), clusterState.GetCenterPosition());
114 }
115
116 //-------------------------------------------------------------------------------------------------------------------------------
117 protected float GetFireRate(float distance, float timeSinceLastInfoS, float soldierThreat, float groupThreat, float peakReactionFactor)
118 {
119 float midDist = SCR_AICombatComponent.CLOSE_RANGE_COMBAT_DISTANCE + SCR_AICombatComponent.LONG_RANGE_COMBAT_DISTANCE / 2;
120
121 // Relation between group and soldier threat depends on distance
122 float soldierThreatFactor = Math.Clamp(Math.Map(distance, 0, FIRE_RATE_SCALING_MAX_DISTANCE, 0.7, 0.3), 0.3, 0.7);
123 float groupThreatFactor = 1 - soldierThreatFactor;
124
125 // Get base fire rate
126 float fireRate = 1.75 * (soldierThreat * soldierThreatFactor + groupThreat * groupThreatFactor);
127
128 // Apply peak factor
129 if (peakReactionFactor > 0)
130 {
131 float peakFireRate = fireRate * 1.2 * peakReactionFactor;
132 fireRate += Math.Max(0, Math.AbsFloat(fireRate - peakFireRate));
133 }
134
135 // Units at longer ranges fire slower for aiming, we're increasing fire rate because for suppression we don't need to be so accurate
136 if (distance > midDist)
137 fireRate *= Math.Map(distance, midDist, FIRE_RATE_SCALING_MAX_DISTANCE, 1, 1.25);
138
139 // If info is considered old, we scale down fire rate
140 if (timeSinceLastInfoS > SCR_AIGroupUtilityComponent.SUPPRESS_OLD_CLUSTER_INFO_AGE_S)
141 fireRate *= Math.Map(timeSinceLastInfoS, 0, SCR_AIGroupUtilityComponent.SUPPRESS_MAX_CLUSTER_INFO_AGE_S, 1, 0.3);
142
143 // Remove clamp!
144 return Math.Clamp(fireRate, 0.05, 2);
145 }
146
147
148 //-------------------------------------------------------------------------------------------------------------------------------
149 protected float GetGroupThreat()
150 {
151 AIGroup group = m_Agent.GetParentGroup();
152 if (group)
153 {
155 if (groupUtil)
156 return groupUtil.GetThreatMeasure();
157 }
158
159 return 0;
160 }
161
162 //-------------------------------------------------------------------------------------------------------------------------------
163 override float CustomEvaluate()
164 {
165 // Complete if no cluster to suppress
166 if (!m_ClusterState || !m_Volume)
167 {
168 Complete();
169 return 0;
170 }
171 float time = GetGame().GetWorld().GetWorldTime();
172 if (time > m_fNextUpdate)
173 {
174 // Update volume
175 m_Volume.SetClusterState(m_ClusterState);
176
177 BaseTarget target = m_CombatComponent.GetCurrentTarget();
178
179 float soldierThreat;
180 if (m_ThreatSystem)
181 soldierThreat = m_ThreatSystem.GetThreatMeasure();
182
183 float groupThreat = GetGroupThreat();
184 bool inDecay = m_bGroupThreatInPeak && time > m_fGroupThreatPeakTimeout;
185 float peakReactionFactor = 0;
186
187 // Check if we're in peak reaction
189 {
190 // Calculate peak reaction fire rate multiplier
191 float timeSincePeak = m_fGroupThreatPeakReactionTimeout - time;
192 float peakTime = THREAT_MAX_PEAK_REACTION_DURATION_MS / 2;
193 float diff = Math.AbsFloat(peakTime - timeSincePeak);
194 peakReactionFactor = Math.Map(diff, 0, peakTime, 1, 0);
195 }
196
197 // Don't increase potential while in decay period
198 if (!inDecay)
199 m_fGroupThreatPotential += groupThreat;
200
202 {
204 m_fGroupThreatPotential -= change;
205
206 // Are we in peak
207 if (m_fGroupThreat == 1)
208 {
209 // Start new peak
211 {
215 }
216
217 // Decay potential if we're in decay period
218 if (inDecay)
220 }
221 // We're not in peak, increase group threat
222 else
223 m_fGroupThreat = Math.Clamp(m_fGroupThreat + change, 0, 1);
224 }
225
226 // End of threat peak
228 m_bGroupThreatInPeak = false;
229
230 // Potential depleted, decrease group threat
233
235 float timeSinceLastInfo = m_ClusterState.GetTimeSinceLastNewInformation();
236 float fireRate = GetFireRate(distance, timeSinceLastInfo, soldierThreat, m_fGroupThreat, peakReactionFactor);
237
238 m_fFireRate.m_Value = fireRate;
240 }
241
242 return PRIORITY_BEHAVIOR_SUPPRESS;
243 }
244}
ArmaReforgerScripted GetGame()
Definition game.c:1398
ref SCR_BTParam< float > m_fPriorityLevel
enum EAIActionFailReason PRIORITY_LEVEL_NORMAL
override void OnActionDeselected()
ResourceName m_sBehaviorTree
override void OnActionSelected()
int GetCause()
void Fail(bool doNotCompleteWaypoint)
void SCR_AIActivityBase(SCR_AIGroupUtilityComponent utility, AIWaypoint relatedWaypoint)
enum SCR_EAIActivityCause m_Utility
void SCR_AIBehaviorBase(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity)
bool m_bUseCombatMove
SCR_EAIBehaviorCause
bool m_bAllowLook
void SCR_AITargetClusterState(SCR_AIGroupTargetCluster cluster)
float distance
float GetFireRate()
Get rate of fire (dps). If it is below fire damage threshold, no damage will be dealt.
Definition Math.c:13
ref SCR_AISuppressionVolumeClusterBox m_Volume
float GetDistance(notnull SCR_AITargetClusterState clusterState)
float GetFireRate(float distance, float timeSinceLastInfoS, float soldierThreat, float groupThreat, float peakReactionFactor)
void SCR_AISuppressGroupClusterBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, SCR_AISuppressionVolumeBase suppressionVolume, float suppressionDuration, float fireRate, float priorityLevel=PRIORITY_LEVEL_NORMAL, SCR_AITargetClusterState clusterState=null)
SCR_AITargetClusterState GetClusterState()
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14