12 vector m_vClusterCenterPos;
22 m_vClusterCenterPos =
m_Cluster.m_State.GetCenterPosition();
23 m_fWeight = vector.DistanceSq(targetPos, m_vClusterCenterPos);
30 vector GetCenterPosition()
32 return m_vClusterCenterPos;
40 static const float MAX_CLOSE_DISTANCE_WEIGHT = 256;
58 SCR_AIInfoComponent infoComp = agent.m_InfoComponent;
60 if (infoComp.HasRole(EUnitRole.MEDIC))
63 if (infoComp.HasRole(EUnitRole.MACHINEGUNNER))
66 if (infoComp.HasUnitState(EUnitState.WOUNDED))
80 msg.m_RelatedGroupActivity = activity;
89 static const int MAX_DISTANCE_TO_TARGET_POS_SQ = 40*40;
90 static const int MAX_SMOKE_POSITION_COUNT = 3;
91 static const int SMOKE_WALL_GAPS_SIZE = 5;
96 SCR_AIInfoComponent infoComp = agent.m_InfoComponent;
98 return agent && infoComp.GetAIState() == EUnitAIState.AVAILABLE &&
99 !infoComp.HasUnitState(EUnitState.IN_TURRET) && !infoComp.HasUnitState(EUnitState.IN_VEHICLE) &&
100 !infoComp.HasUnitState(EUnitState.UNCONSCIOUS);
104 protected void GetConsideredAgents(SCR_AIGroupUtilityComponent groupUtility, vector targetPosition, array<AIAgent> avoidAgents, array<AIAgent> excludeAgents,
105 notnull array<ref SCR_AIActivitySmokeCoverFeatureAgent> outConsideredAgents, out
int combatReadyAgentsCount)
107 combatReadyAgentsCount = 0;
109 foreach (SCR_AIInfoComponent infoComp: groupUtility.m_aInfoComponents)
112 if (!agent || excludeAgents.Contains(agent))
116 if (!IsAgentAvailable(agent))
120 combatReadyAgentsCount++;
122 IEntity controlledEntity = agent.GetControlledEntity();
124 if (!controlledEntity || !infoComp.HasRole(EUnitRole.HAS_SMOKE_GRENADE))
128 float distanceToTargetSq = vector.DistanceSq(targetPosition, controlledEntity.GetOrigin());
129 if (distanceToTargetSq > MAX_DISTANCE_TO_TARGET_POS_SQ)
137 protected void GetClusterBasedSmokePositions(array<ref SCR_AIGroupTargetCluster> targetClusters, vector targetPosition,
int maxSmokePositions, out array<vector> smokePositions)
139 int clustersCount = targetClusters.Count();
141 array<ref SCR_AIActivitySmokeCoverFeatureCluster> clusters = {};
146 if (clustersCount > maxSmokePositions)
149 float maxClustersCount = Math.Min(maxSmokePositions, clustersCount);
151 vector lastDirection;
154 for (
int i = 0; i < maxClustersCount; i++)
157 vector clusterPos = cluster.GetCenterPosition();
159 lastDirection = vector.Direction(targetPosition, clusterPos).Normalized();
160 smokePositions.Insert(targetPosition + (lastDirection * (5 + (maxClustersCount * 3))));
163 int smokesLeft = maxSmokePositions - maxClustersCount;
170 if (maxClustersCount == 1)
174 vector pos = smokePositions[0];
175 vector relDir = (lastDirection * vector.Up).Normalized();
177 for (
int i = 0; i < smokesLeft; i++)
183 vector relVector = relDir *
distance;
186 smokePositions.Insert(pos + relVector);
188 smokePositions.Insert(pos - relVector);
195 int maxPositions = Math.Min(maxClustersCount / 2, smokesLeft);
197 for (
int i = 0; i < maxPositions; i++)
199 vector pos1 = smokePositions[i];
200 vector pos2 = smokePositions[i + 1];
201 vector
direction = vector.Direction(pos1, pos2).Normalized();
202 float distance = vector.Distance(pos1, pos2);
211 notnull SCR_AIGroupUtilityComponent groupUtility,
212 vector targetPosition,
214 notnull array<AIAgent> avoidAgents,
215 notnull array<AIAgent> excludeAgents,
220 int combatReadyAgentsCount;
222 array<ref SCR_AIActivitySmokeCoverFeatureAgent> consideredAgents = {};
224 GetConsideredAgents(groupUtility, targetPosition, excludeAgents, avoidAgents, consideredAgents, combatReadyAgentsCount);
226 int consideredAgentsCount = consideredAgents.Count();
229 if (!consideredAgentsCount)
234 int maxSmokePositions = Math.Min(Math.Floor(combatReadyAgentsCount / 2), Math.Min(MAX_SMOKE_POSITION_COUNT, consideredAgentsCount));
237 if (maxSmokePositions <= 0)
241 if (consideredAgentsCount > maxSmokePositions)
242 consideredAgents.Sort();
244 array<vector> smokePositions = {};
249 array<ref SCR_AIGroupTargetCluster> targetClusters = groupUtility.m_Perception.m_aTargetClusters;
253 GetClusterBasedSmokePositions(targetClusters, targetPosition, maxSmokePositions, smokePositions);
257 float angle = Math.RandomFloat(0, 360);
258 for (
int i = 0; i < maxSmokePositions; i++)
260 vector
direction = {Math.Cos(angle * Math.DEG2RAD), 0, Math.Sin(angle * Math.DEG2RAD)};
262 float distance = 1 + maxSmokePositions + Math.RandomFloat(0, maxSmokePositions * 1.5);
265 angle += (360 / maxSmokePositions);
273 smokePositions.Insert(targetPosition);
275 AICommunicationComponent comms = groupUtility.m_Owner.GetCommunicationComponent();
279 int smokePositionsCount = smokePositions.Count();
282 for (
int i = 0; i < smokePositionsCount; i++)
285 float delay = 0.3 + Math.RandomFloat(0, 1.5);
286 consideredAgents[i].SendMessage(comms, contextActivity, smokePositions[i], delay);
295 SCR_AIGroupUtilityComponent groupUtility = activity.m_Utility;
301 GetActivityTargetPosition(activity),
302 GetActivityProperties(activity),
303 GetActivityAvoidedAgents(activity),
304 GetActivityExcludedAgents(activity),
347 if (healActivity.m_EntityToHeal.m_Value)
348 return healActivity.m_EntityToHeal.m_Value.GetOrigin();
364 ChimeraCharacter character = ChimeraCharacter.Cast(healActivity.m_MedicEntity.m_Value);
368 CharacterControllerComponent charCtrl = character.GetCharacterController();
372 AIControlComponent aiCtrl = charCtrl.GetAIControlComponent();
376 return {aiCtrl.GetAIAgent()};
384 ChimeraCharacter character = ChimeraCharacter.Cast(healActivity.m_EntityToHeal.m_Value);
388 CharacterControllerComponent charCtrl = character.GetCharacterController();
392 AIControlComponent aiCtrl = charCtrl.GetAIControlComponent();
396 return {aiCtrl.GetAIAgent()};