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";}