11 static const string PORT_ERROR_OFFSET =
"ErrorOffset";
12 static const string PORT_BASE_TARGET =
"BaseTargetIn";
13 static const string PORT_AIM_POINT =
"AimPoint";
14 static const string PORT_TOLERANCE =
"AimingTolerance";
15 static const string PORT_AIMPOINT_TYPE_0 =
"AimpointType0";
16 static const string PORT_AIMPOINT_TYPE_1 =
"AimpointType1";
17 static const float CLOSE_RANGE_THRESHOLD = 15.0;
18 static const float LONG_RANGE_THRESHOLD = 200.0;
19 static const float AIMING_ERROR_SCALE = 1.0;
20 static const float AIMING_ERROR_FACTOR_MIN = 0.4;
21 static const float AIMING_ERROR_CLOSE_RANGE_FACTOR_MIN = 0.05;
22 static const float AIMING_ERROR_FACTOR_MAX = 1.4;
23 static const float MAXIMAL_TOLERANCE = 10.0;
24 static const float MINIMAL_TOLERANCE = 0.003;
26 protected SCR_AICombatComponent m_CombatComponent;
35 [
Attribute(
"0", UIWidgets.ComboBox,
"AimPoint type for fixed option",
"", ParamEnumArray.FromEnum(
EAimPointType) )]
38 [
Attribute(
"0.03", UIWidgets.EditBox,
"Default PrecisionXY")]
39 protected float m_fDefaultPrecisionXY;
41 private int m_iTorsoCount = 0;
44 override void OnInit(AIAgent owner)
46 IEntity ent = owner.GetControlledEntity();
48 m_CombatComponent = SCR_AICombatComponent.Cast(ent.FindComponent(SCR_AICombatComponent));
53 protected static ref TStringArray s_aVarsOut = {
58 override array<string> GetVariablesOut()
64 protected static ref TStringArray s_aVarsIn = {
69 override array<string> GetVariablesIn()
75 override ENodeResult EOnTaskSimulate(AIAgent owner,
float dt)
79 return ENodeResult.FAIL;
81 IEntity entity = owner.GetControlledEntity();
83 return ENodeResult.FAIL;
91 GetVariableIn(PORT_BASE_TARGET, target);
97 return ENodeResult.FAIL;
101 IEntity targetEntity = target.GetTargetEntity();
105 return ENodeResult.FAIL;
111 if (!GetVariableIn(PORT_AIMPOINT_TYPE_0, aimpointType0))
113 if (!GetVariableIn(PORT_AIMPOINT_TYPE_1, aimpointType1))
115 aimpointTypes[0] = aimpointType0;
116 aimpointTypes[1] = aimpointType1;
117 aimpointTypes[2] = m_eAimPointType;
120 AimPoint aimPoint = GetAimPoint(target, aimpointTypes);
126 return ENodeResult.FAIL;
133 m_aDebugShapes.Insert(Shape.CreateSphere(COLOR_YELLOW_A, ShapeFlags.NOZBUFFER | ShapeFlags.TRANSP, aimPoint.GetPosition(),aimPoint.GetDimension()));
137 vector offsetX, offsetY;
138 float angularSize,
distance, tolerance;
139 GetTargetAngularBounds(entity, aimPoint, offsetX, offsetY, angularSize,
distance);
142 float distanceFactor = GetDistanceFactor(
distance);
143 float offsetWeaponFactor = GetOffsetWeaponTypeFactor(weaponType);
146 offsetX = GetRandomFactor(currentSkill, 0) * offsetX * AIMING_ERROR_SCALE * distanceFactor * offsetWeaponFactor;
147 offsetY = GetRandomFactor(currentSkill, 0) * offsetY * AIMING_ERROR_SCALE * distanceFactor * offsetWeaponFactor;
149 tolerance = GetTolerance(entity, targetEntity, angularSize,
distance, weaponType);
151 SetVariableOut(PORT_ERROR_OFFSET, offsetX + offsetY);
152 SetVariableOut(PORT_AIM_POINT, aimPoint);
153 SetVariableOut(PORT_TOLERANCE, tolerance);
159 return ENodeResult.SUCCESS;
164 ClearVariable(PORT_ERROR_OFFSET);
165 ClearVariable(PORT_AIM_POINT);
166 ClearVariable(PORT_TOLERANCE);
171 void GetTargetAngularBounds(IEntity shooter,
AimPoint targetAimpoint, out vector sizeVectorX, out vector sizeVectorY, out
float angularSize, out
float distance)
174 vector shooterCenter, joinNorm, join, min, max;
175 float dimension = 2 * targetAimpoint.GetDimension();
176 shooter.GetWorldBounds(min,max);
179 shooterCenter = (min + max) * 0.5;
180 join = targetAimpoint.GetPosition() - shooterCenter;
182 angularSize = Math.Atan2(dimension,
distance) * Math.RAD2DEG;
184 joinNorm = join.Normalized();
185 sizeVectorX = (vector.Up * joinNorm).Normalized();
186 sizeVectorY = (joinNorm * sizeVectorX).Normalized();
188 sizeVectorX *= dimension;
189 sizeVectorY *= dimension;
192 if (DiagMenu.GetBool(
SCR_DebugMenuID.DEBUGUI_AI_SHOW_TARGET_PROJECTED_SIZE))
194 m_aDebugShapes.Insert(Shape.CreateArrow(shooterCenter, shooterCenter + sizeVectorX, 0.1, COLOR_BLUE, ShapeFlags.NOZBUFFER));
195 m_aDebugShapes.Insert(Shape.CreateArrow(shooterCenter, shooterCenter + sizeVectorY, 0.1, COLOR_RED, ShapeFlags.NOZBUFFER));
196 m_aDebugShapes.Insert(Shape.CreateArrow(shooterCenter, shooterCenter + joinNorm * dimension, 0.1, COLOR_YELLOW, ShapeFlags.NOZBUFFER));
203 float GetDistanceFactor(
float distance)
205 if (
distance < CLOSE_RANGE_THRESHOLD)
206 return Math.Map(
distance, 0, CLOSE_RANGE_THRESHOLD, AIMING_ERROR_CLOSE_RANGE_FACTOR_MIN, AIMING_ERROR_FACTOR_MIN);
208 float distanceCl = Math.Clamp((
distance - CLOSE_RANGE_THRESHOLD) / LONG_RANGE_THRESHOLD, 0, 1);
209 return Math.Lerp(AIMING_ERROR_FACTOR_MIN, AIMING_ERROR_FACTOR_MAX, distanceCl);
214 float GetRandomFactor(EAISkill skill,
float mu)
219 case EAISkill.ROOKIE :
224 case EAISkill.REGULAR :
229 case EAISkill.VETERAN :
234 case EAISkill.EXPERT :
239 case EAISkill.CYLON :
245 return Math.RandomGaussFloat(sigma,mu);
251 switch (aimingPreference)
255 switch(currentSelection)
267 if (m_iTorsoCount < 2)
287 return m_eAimPointType;
290 return currentSelection;
295 EAISkill GetSkillFromThreat(EAISkill inSkill, EAIThreatState threat)
299 case EAIThreatState.THREATENED :
303 case EAISkill.ROOKIE :
305 return EAISkill.ROOKIE;
307 case EAISkill.REGULAR :
309 return EAISkill.ROOKIE;
311 case EAISkill.VETERAN :
313 return EAISkill.REGULAR;
315 case EAISkill.EXPERT :
317 return EAISkill.VETERAN;
319 case EAISkill.CYLON :
321 return EAISkill.CYLON;
326 case EAIThreatState.ALERTED :
330 case EAISkill.ROOKIE :
332 return EAISkill.REGULAR;
334 case EAISkill.REGULAR :
336 return EAISkill.VETERAN;
338 case EAISkill.VETERAN :
340 return EAISkill.EXPERT;
342 case EAISkill.EXPERT :
344 return EAISkill.CYLON;
346 case EAISkill.CYLON :
348 return EAISkill.CYLON;
359 return EAISkill.NONE;
364 float GetTolerance(IEntity observer, IEntity target,
float angularSize,
float distance,
EWeaponType weaponType)
367 bool setMaxTolerance;
370 if (
distance < CLOSE_RANGE_THRESHOLD)
371 return MAXIMAL_TOLERANCE;
373 tolerance = angularSize / 2;
375 tolerance *= GetAngularSpeedFactor(observer, target, setMaxTolerance);
378 tolerance = MAXIMAL_TOLERANCE;
382 tolerance *= GetWeaponTypeFactor(weaponType);
384 return Math.Clamp(tolerance, MINIMAL_TOLERANCE, MAXIMAL_TOLERANCE);
388 float GetAngularSpeedFactor(IEntity observer, IEntity enemy, out
bool setBigTolerance)
390 IEntity parent = enemy.GetParent();
394 parent = enemy.GetParent();
398 Physics ph = enemy.GetPhysics();
401 vector positionVector = enemy.GetOrigin() - observer.GetOrigin();
402 vector angularVelocity = positionVector * ph.GetVelocity() / positionVector.LengthSq();
403 float angularSpeed = angularVelocity.Length();
405 if (angularSpeed < 0.07)
407 else if (angularSpeed < 0.17)
410 setBigTolerance =
true;
415 float GetSuppressionFactor(EAIThreatState threat, out
bool setBigTolerance)
419 case EAIThreatState.THREATENED :
421 setBigTolerance =
true;
425 case EAIThreatState.ALERTED :
478 float GetOffsetWeaponTypeFactor(
EWeaponType weaponType)
489 PerceivableComponent targetPerceivable = target.GetPerceivableComponent();
490 if (!targetPerceivable)
493 array<ref AimPoint> aimPoints = {};
496 for (
int i = 0; i < 3; i++)
499 if (aimpointType == -1)
502 targetPerceivable.GetAimpointsOfType(aimPoints, aimpointType);
503 if (!aimPoints.IsEmpty())
507 int index = aimPoints.GetRandomIndex();
510 return aimPoints[
index];
516 override bool VisibleInPalette() {
return true;}
519 protected override string GetOnHoverDescription() {
return "Get aiming error position from the center of the target";}