22 MOVEMENT_WHEN_FIRE = 8,
23 MOVEMENT_TO_LAST_SEEN = 16,
38 static const int TARGET_ENDANGERED_TIMEOUT_S = 10;
39 static const float ENDANGERING_TARGET_SCORE_MULTIPLIER = 1.05;
42 protected static const float ASSIGNED_TARGETS_SCORE_INCREMENT = 30.0;
43 protected static const float ENDANGERING_TARGETS_SCORE_INCREMENT = 15.0;
46 static const float TARGET_MAX_LAST_SEEN_VISIBLE = 0.5;
47 protected static const float TARGET_MAX_LAST_SEEN_DIRECT_ATTACK = 1.6;
48 static const float TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK = 6.0;
49 static const float TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_MG = 11.0;
50 static const float TARGET_MAX_LAST_SEEN = 45.0;
51 protected static const float TARGET_MIN_INDIRECT_TRACE_FRACTION_MIN = 0.5;
52 protected static const float TARGET_MAX_DISTANCE_INFANTRY = 500.0;
53 protected static const float TARGET_MAX_DISTANCE_VEHICLE = 700.0;
54 protected static const float TARGET_MAX_DISTANCE_DISARMED = 0.0;
55 protected static const float TARGET_MAX_TIME_SINCE_ENDANGERED = 5.0;
56 protected static const float TARGET_SCORE_RETREAT = 75.0;
57 static const float TARGET_SCORE_HIGH_PRIORITY_ATTACK = 98.5;
59 protected static ref array<EWeaponType> s_aWeaponBlacklistFragGrenades = {
EWeaponType.WT_FRAGGRENADE};
62 protected const float PERCEPTION_FACTOR_SAFE = 1.0;
63 protected const float PERCEPTION_FACTOR_VIGILANT = 2.5;
64 protected const float PERCEPTION_FACTOR_ALERTED = 2.5;
65 protected const float PERCEPTION_FACTOR_THREATENED = 0.4;
67 protected const float PERCEPTION_FACTOR_EQUIPMENT_BINOCULARS = 3.0;
68 protected const float PERCEPTION_FACTOR_EQUIPMENT_NONE = 1.0;
71 static const float LONG_RANGE_FIRE_DISTANCE = 200.0;
76 protected BaseWeaponManagerComponent m_WpnManager;
80 protected SCR_AIInfoComponent
m_AIInfo;
81 protected SCR_AIUtilityComponent m_Utility;
84 protected IEntity m_CurrentVehicle;
85 protected bool m_bCurrentVehicleEvac;
86 protected SCR_BaseCompartmentManagerComponent m_CurrentVehicleCompartmentManager;
87 protected BaseCompartmentSlot m_CurrentCompartmentSlot;
90 protected EAICombatActions m_iAllowedActions;
91 protected EAICombatType m_eCombatType = EAICombatType.NORMAL;
92 protected EAICombatType m_eDefaultCombatType = EAICombatType.NORMAL;
94 [
Attribute(
"50", UIWidgets.ComboBox,
"AI skill in combat",
"", ParamEnumArray.FromEnum(EAISkill) )]
95 protected EAISkill m_eAISkillDefault;
100 protected bool m_bFriendlyAimLastResult;
102 protected ref Shape m_FriendlyAimShape;
108 protected ref
BaseTarget m_SelectedRetreatTarget;
109 protected ref array<IEntity> m_aAssignedTargets = {};
112 protected ResourceName m_SelectedWeaponResource;
116 protected BaseMagazineComponent m_SelectedMagazineComp;
117 protected int m_iSelectedMuzzle;
118 protected float m_fSelectedWeaponMinDist;
119 protected float m_fSelectedWeaponMaxDist;
120 protected bool m_bSelectedWeaponDirectDamage;
122 protected BaseCompartmentSlot m_WeaponEvaluationCompartment;
125 protected float m_fNextWeaponTargetEvaluation_ms = 0;
126 protected const float WEAPON_TARGET_UPDATE_PERIOD_MS = 500;
132 protected float m_fDismountTurretTimer;
133 protected static const float DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S = 100;
134 protected static const float TURRET_TARGET_EXCESS_ANGLE_THRESHOLD_DEG = 3.0;
135 protected const float DISMOUNT_TURRET_TIMER_MS = 1200;
136 protected static ref array<EVehicleType> s_aForbidDismountTurretsOfVehicleTypes = { EVehicleType.APC };
139 protected float m_fEquipmentPerceptionFactor = 1.0;
142 protected EGadgetType m_eCurrentGadgetType = -1;
143 protected bool m_bGadgetFocus =
false;
147 EAISkill GetAISkill()
155 void SetAISkill(EAISkill skill)
158 AddDebugMessage(
string.Format(
"SetAISkill: %1",
typename.EnumToString(EAISkill, skill)));
175 UpdatePerceptionFactor(
m_Perception, m_Utility.m_ThreatSystem);
183 AddDebugMessage(
"ResetAISkill");
194 if (m_CurrentTurretController)
197 BaseWeaponManagerComponent turretWpnMgr = m_CurrentTurretController.GetWeaponManager();
199 currentWeapon = turretWpnMgr.GetCurrentWeapon();
201 else if (m_WpnManager)
204 currentWeapon = m_WpnManager.GetCurrentWeapon();
208 return currentWeapon.GetWeaponType();
217 return m_SelectedTarget;
224 return m_SelectedRetreatTarget;
239 array<BaseTarget> targets = {};
244 if (tgt.IsEndangering())
254 bool IsEnemyKnown(IEntity ent)
258 return knownAsEnemy || knownAsDetected;
269 void EvaluateWeaponAndTarget(out
bool outWeaponEvent, out
bool outSelectedTargetChanged,
271 out
bool outRetreatTargetChanged, out
bool outCompartmentChanged)
273 float worldTime =
GetGame().GetWorld().GetWorldTime();
274 if (worldTime < m_fNextWeaponTargetEvaluation_ms)
276 outWeaponEvent =
false;
277 outSelectedTargetChanged =
false;
281 m_fNextWeaponTargetEvaluation_ms = worldTime + WEAPON_TARGET_UPDATE_PERIOD_MS;
283 AIAgent myAgent = GetAiAgent();
284 AIGroup myGroup = myAgent.GetParentGroup();
285 SCR_AIGroupInfoComponent groupInfoComp;
287 groupInfoComp = SCR_AIGroupInfoComponent.Cast(myGroup.FindComponent(SCR_AIGroupInfoComponent));
290 bool weaponEvent =
false;
291 bool selectedTargetChanged =
false;
292 bool retreatTargetChanged =
false;
293 bool compartmentChanged =
false;
297 array<EWeaponType> weaponBlacklist;
300 if (!groupInfoComp.IsGrenadeThrowAllowed(myAgent))
301 weaponBlacklist = s_aWeaponBlacklistFragGrenades;
304 bool useCompartmentWeapons =
m_AIInfo.HasUnitState(EUnitState.IN_TURRET);
307 array<IEntity> assignedTargets;
311 assignedTargets = m_aAssignedTargets;
313 bool selectedWpnTarget = m_WeaponTargetSelector.SelectWeaponAndTarget(assignedTargets,
314 ASSIGNED_TARGETS_SCORE_INCREMENT, ENDANGERING_TARGETS_SCORE_INCREMENT,
315 useCompartmentWeapons, weaponTypesBlacklist: weaponBlacklist);
317 m_eUnitTypesCanAttack = m_WeaponTargetSelector.GetUnitTypesCanAttack();
318 if (selectedWpnTarget)
321 BaseMagazineComponent newMagazineComp;
324 newTarget = m_WeaponTargetSelector.GetSelectedTarget();
325 m_WeaponTargetSelector.GetSelectedWeapon(newWeaponComp, newMuzzleId, newMagazineComp);
326 m_WeaponTargetSelector.GetSelectedWeaponProperties(m_fSelectedWeaponMinDist, m_fSelectedWeaponMaxDist, m_bSelectedWeaponDirectDamage);
329 weaponEvent = newWeaponComp != m_SelectedWeaponComp ||
330 newMuzzleId != m_iSelectedMuzzle ||
331 newMagazineComp != m_SelectedMagazineComp;
333 bool weaponOrMuzzleChanged = newWeaponComp != m_SelectedWeaponComp ||
334 newMuzzleId != m_iSelectedMuzzle;
336 if (weaponOrMuzzleChanged)
338 ref array<BaseMuzzleComponent> muzzles = {};
339 newWeaponComp.GetMuzzlesList(muzzles);
340 if (newMuzzleId >= muzzles.Count() || newMuzzleId < 0)
341 m_SelectedWeaponResource =
m_ConfigComponent.GetTreeNameForWeaponType(newWeaponComp.GetWeaponType(),0);
343 m_SelectedWeaponResource =
m_ConfigComponent.GetTreeNameForWeaponType(newWeaponComp.GetWeaponType(),muzzles[newMuzzleId].GetMuzzleType());
347 EWeaponType weaponType = newWeaponComp.GetWeaponType();
348 if (groupInfoComp && weaponType ==
EWeaponType.WT_FRAGGRENADE)
352 groupInfoComp.OnAgentSelectedGrenade(myAgent);
357 m_SelectedWeaponComp = newWeaponComp;
358 m_iSelectedMuzzle = newMuzzleId;
359 m_SelectedMagazineComp = newMagazineComp;
363 if (newTarget != m_SelectedTarget)
366 AddDebugMessage(
string.Format(
"Target has changed. New: %1, Previous: %2", newTarget, m_SelectedTarget));
368 m_SelectedTarget = newTarget;
369 selectedTargetChanged =
true;
374 float targetCantAttackScore;
375 m_WeaponTargetSelector.GetMostRelevantTargetCantAttack(targetCantAttack, targetCantAttackScore);
376 if (targetCantAttackScore < TARGET_SCORE_RETREAT)
377 targetCantAttack =
null;
378 if (targetCantAttack != m_SelectedRetreatTarget)
380 m_SelectedRetreatTarget = targetCantAttack;
381 retreatTargetChanged =
true;
385 BaseCompartmentSlot currentCompartment = m_CompartmentAccess.GetCompartment();
386 if (currentCompartment != m_WeaponEvaluationCompartment)
388 compartmentChanged =
true;
389 m_WeaponEvaluationCompartment = currentCompartment;
392 outWeaponEvent = weaponEvent;
393 outSelectedTargetChanged = selectedTargetChanged;
394 outRetreatTargetChanged = retreatTargetChanged;
395 outCompartmentChanged = compartmentChanged;
396 outCurrentTarget = newTarget;
397 outPrevTarget = prevTarget;
401 SCR_AIInfoComponent GetAIInfoComponent()
415 array<BaseMuzzleComponent> muzzles = {};
416 weaponComp.GetMuzzlesList(muzzles);
417 if (muzzleId >= muzzles.Count() || muzzleId < 0)
425 if (muzzleComp.IsDisposable())
430 int lowMagThreshold = 0;
433 switch (weaponComp.GetWeaponType())
435 case EWeaponType.WT_RIFLE: lowMagThreshold = 3;
break;
436 case EWeaponType.WT_GRENADELAUNCHER: lowMagThreshold = 3;
break;
437 case EWeaponType.WT_SNIPERRIFLE: lowMagThreshold = 1;
break;
438 case EWeaponType.WT_ROCKETLAUNCHER: lowMagThreshold = 1;
break;
439 case EWeaponType.WT_MACHINEGUN: lowMagThreshold = 1;
break;
440 case EWeaponType.WT_HANDGUN: lowMagThreshold = 1;
break;
441 default: lowMagThreshold = 0;
444 return magCount < lowMagThreshold;
450 void Update(
float timeSliceMs)
453 if (m_CurrentTurretController)
454 EvaluateDismountTurret(timeSliceMs);
463 bool DismountTurretCondition(inout vector targetPos,
bool targetPosProvided)
466 if (!m_CurrentTurretController)
468 TurretComponent turretComp = m_CurrentTurretController.GetTurretComponent();
473 if (m_SelectedTarget)
477 array<BaseCompartmentSlot> compartments = {};
478 m_CurrentVehicleCompartmentManager.GetCompartments(compartments);
479 foreach (BaseCompartmentSlot slot : compartments)
487 Vehicle vehicle = Vehicle.Cast(m_CurrentVehicle);
488 if (vehicle && s_aForbidDismountTurretsOfVehicleTypes.Find(vehicle.m_eVehicleType) != -1)
492 if (!targetPosProvided)
496 targetPos = target.GetLastDetectedPosition();
499 target =
m_Perception.GetClosestTarget(
ETargetCategory.ENEMY, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S);
501 targetPos = target.GetLastSeenPosition();
509 IEntity targetEntity = target.GetTargetEntity();
515 targetEntity.GetBounds(bmin, bmax);
516 targetPos = targetPos + 0.5 * (bmin + bmax);
522 vector angleExcess = turretComp.GetAimingAngleExcess(targetPos);
526 return angleExcess.Length() > TURRET_TARGET_EXCESS_ANGLE_THRESHOLD_DEG;
530 protected void EvaluateDismountTurret(
float timeSliceMs)
533 bool mustDismount = DismountTurretCondition(targetPos,
false);
537 m_fDismountTurretTimer = 0;
542 if (m_fDismountTurretTimer == -1.0)
545 m_fDismountTurretTimer += timeSliceMs;
547 if (m_fDismountTurretTimer > DISMOUNT_TURRET_TIMER_MS)
549 m_fDismountTurretTimer = -1.0;
551 TryAddDismountTurretActions(targetPos);
562 void TryAddDismountTurretActions(vector targetPos,
bool addGetOut =
true,
bool addInvestigate =
true,
bool addGetIn =
true)
564 BaseCompartmentSlot compartmentSlot = m_CurrentCompartmentSlot;
565 if (!compartmentSlot)
571 if (prevGetOutAction)
575 m_Utility.AddAction(getOutAction);
581 if (!prevInvestigate)
584 m_Utility.AddAction(moveAndInvestigateAction);
591 if (!prevGetInAction)
594 m_Utility.AddAction(getInAction);
599 protected static const float DISTANCE_MAX = 22;
600 protected static const float DISTANCE_MIN = 6;
601 private static const float NEAR_PROXIMITY = 2;
603 protected const float m_StopDistance = 30 + Math.RandomFloat(0, 10);
608 vector FindNextCoverPosition()
610 if (!m_SelectedTarget)
613 vector ownerPos =
GetOwner().GetOrigin();
614 vector lastSeenPos = m_SelectedTarget.GetLastSeenPosition();
615 float distanceToTarget = vector.Distance(ownerPos, lastSeenPos);
617 if (m_StopDistance > distanceToTarget)
624 bool standardAttack =
true;
625 float nextCoverDistance;
630 if (!defendWp.IsWithinCompletionRadius(lastSeenPos) &&
631 !defendWp.IsWithinCompletionRadius(ownerPos))
633 direction = vector.Direction(ownerPos, defendWp.GetOrigin());
635 if (vector.Distance(defendWp.GetOrigin(), ownerPos) < DISTANCE_MIN)
636 nextCoverDistance = 0;
638 nextCoverDistance = DISTANCE_MIN;
640 standardAttack =
false;
646 nextCoverDistance = Math.RandomFloat(DISTANCE_MIN, DISTANCE_MAX);
649 if (nextCoverDistance > (distanceToTarget - DISTANCE_MIN))
650 nextCoverDistance = distanceToTarget - DISTANCE_MIN;
652 direction = vector.Direction(ownerPos, m_SelectedTarget.GetLastSeenPosition());
656 vector newPositionCenter =
direction * nextCoverDistance + ownerPos, newPosition;
659 newPosition = s_AIRandomGenerator.GenerateRandomPointInRadius(0, NEAR_PROXIMITY, newPositionCenter,
true);
660 newPosition[1] = newPositionCenter[1];
665 protected void Event_OnInventoryChanged(IEntity item, BaseInventoryStorageComponent storageOwner)
672 protected void Event_OnTimerAfterInventoryChanged()
683 protected void Event_OnCompartmentEntered( IEntity vehicle, BaseCompartmentManagerComponent manager,
int mgrID,
int slotID )
685 m_CurrentCompartmentSlot = manager.FindCompartment(slotID, mgrID);
686 IEntity compartmentEntity = m_CurrentCompartmentSlot.GetOwner();
688 m_CurrentVehicle = m_CurrentCompartmentSlot.GetVehicle();
689 m_CurrentVehicleCompartmentManager = SCR_BaseCompartmentManagerComponent.Cast(m_CurrentVehicle.FindComponent(SCR_BaseCompartmentManagerComponent));
698 protected void Event_OnCompartmentLeft( IEntity vehicle, BaseCompartmentManagerComponent manager,
int mgrID,
int slotID )
700 m_CurrentVehicle =
null;
701 m_bCurrentVehicleEvac =
false;
702 m_CurrentCompartmentSlot =
null;
703 m_CurrentTurretController =
null;
707 protected void Event_OnGadgetStateChanged(IEntity gadget,
bool isInHand,
bool isOnGround)
711 SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(gadget.FindComponent(SCR_GadgetComponent));
713 m_eCurrentGadgetType = gadgetComp.GetType();
715 m_eCurrentGadgetType = -1;
718 m_eCurrentGadgetType = -1;
720 RecalculateEquipmentPerceptionFactor();
724 protected void Event_OnGadgetFocusStateChanged(IEntity gadget,
bool isFocused)
726 m_bGadgetFocus = isFocused;
727 RecalculateEquipmentPerceptionFactor();
733 if (damageContext.damageType !=
EDamageType.FIRE || !m_Utility || !m_CurrentVehicle || m_bCurrentVehicleEvac)
737 m_bCurrentVehicleEvac =
true;
740 m_Utility.AddAction(behaviorGetOut);
743 m_Utility.AddAction(behaviorMoveFromDanger);
749 if (dType !=
EDamageType.BLEEDING || !m_Utility || !m_Utility.m_AIInfo)
755 float priorityLevelClamped = currentAction.GetRestrictedPriorityLevel();
757 if (m_Utility.m_AIInfo.HasRole(EUnitRole.MEDIC))
763 m_Utility.AddAction(behavior);
769 AIGroup myGroup =
m_Agent.GetParentGroup();
772 SCR_MailboxComponent myMailbox = SCR_MailboxComponent.Cast(
m_Agent.FindComponent(SCR_MailboxComponent));
774 myMailbox.RequestBroadcast(msg, myGroup);
784 bool IsActionAllowed(EAICombatActions action)
786 return (m_iAllowedActions & action);
791 EAICombatActions GetAllowedActions()
793 return m_iAllowedActions;
797 private void SetActionAllowed(EAICombatActions action,
bool isAllowed)
800 AddDebugMessage(
string.Format(
"SetActionAllowed: %1, %2",
typename.EnumToString(EAICombatActions, action), isAllowed));
803 if ((m_iAllowedActions & action) != isAllowed)
806 m_iAllowedActions = m_iAllowedActions | action;
808 m_iAllowedActions = m_iAllowedActions & ~action;
814 void SetHoldFire(
bool isHoldFire)
817 AddDebugMessage(
string.Format(
"SetHoldFire: %1", isHoldFire));
822 SetActionAllowed(EAICombatActions.HOLD_FIRE,
true);
823 SetActionAllowed(EAICombatActions.BURST_FIRE,
false);
824 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
false);
828 SetCombatType(m_eCombatType);
834 EAICombatType GetCombatType()
836 return m_eCombatType;
843 void SetCombatType(EAICombatType combatType)
846 AddDebugMessage(
string.Format(
"SetCombatType: %1",
typename.EnumToString(EAICombatType, combatType)));
851 case EAICombatType.NONE:
853 SetActionAllowed(EAICombatActions.HOLD_FIRE,
true);
854 SetActionAllowed(EAICombatActions.MOVEMENT_WHEN_FIRE,
false);
855 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
false);
856 SetActionAllowed(EAICombatActions.MOVEMENT_TO_LAST_SEEN,
false);
859 case EAICombatType.NORMAL:
861 SetActionAllowed(EAICombatActions.HOLD_FIRE,
false);
862 SetActionAllowed(EAICombatActions.MOVEMENT_WHEN_FIRE,
true);
863 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
false);
864 SetActionAllowed(EAICombatActions.MOVEMENT_TO_LAST_SEEN,
true);
867 case EAICombatType.SUPPRESSIVE:
869 SetActionAllowed(EAICombatActions.HOLD_FIRE,
false);
870 SetActionAllowed(EAICombatActions.MOVEMENT_WHEN_FIRE,
false);
871 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
true);
872 SetActionAllowed(EAICombatActions.MOVEMENT_TO_LAST_SEEN,
true);
875 case EAICombatType.RETREAT:
877 SetActionAllowed(EAICombatActions.HOLD_FIRE,
false);
878 SetActionAllowed(EAICombatActions.MOVEMENT_WHEN_FIRE,
true);
879 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
false);
880 SetActionAllowed(EAICombatActions.MOVEMENT_TO_LAST_SEEN,
false);
883 case EAICombatType.SINGLE_SHOT:
885 SetActionAllowed(EAICombatActions.HOLD_FIRE,
false);
886 SetActionAllowed(EAICombatActions.MOVEMENT_WHEN_FIRE,
false);
887 SetActionAllowed(EAICombatActions.SUPPRESSIVE_FIRE,
false);
888 SetActionAllowed(EAICombatActions.MOVEMENT_TO_LAST_SEEN,
false);
892 m_eCombatType = combatType;
902 void SetDefaultCombatType(EAICombatType combatType)
905 AddDebugMessage(
string.Format(
"SetDefaultCombatType: %1",
typename.EnumToString(EAICombatType, combatType)));
908 m_eDefaultCombatType = combatType;
913 void ResetCombatType()
916 AddDebugMessage(
"ResetCombatType");
919 SetCombatType(m_eDefaultCombatType);
924 bool IsFriendlyInAim()
926 IEntity friendlyEntInAim =
m_Perception.GetFriendlyInLineOfFire();
928 if (friendlyEntInAim && DiagMenu.GetBool(
SCR_DebugMenuID.DEBUGUI_AI_SHOW_FRIENDLY_IN_AIM))
929 m_FriendlyAimShape = Shape.CreateSphere(COLOR_RED, ShapeFlags.NOOUTLINE|ShapeFlags.NOZBUFFER|ShapeFlags.TRANSP, friendlyEntInAim.GetOrigin() + Vector(0, 2, 0), 0.1);
931 m_FriendlyAimShape =
null;
933 m_bFriendlyAimLastResult = friendlyEntInAim !=
null;
935 return m_bFriendlyAimLastResult;
942 bool IsTargetVisible(notnull
BaseTarget target)
948 float lastSeenMax = Math.Max(TARGET_MAX_LAST_SEEN_VISIBLE,
m_Perception.GetUpdateInterval()) + 0.02;
949 bool visible = target.GetTimeSinceSeen() < lastSeenMax;
959 m_aAssignedTargets.Clear();
962 m_aAssignedTargets.Copy(assignedTargets);
963 else if (clusterState)
969 void ResetAssignedTargets()
971 m_aAssignedTargets.Clear();
977 void SetExpectedEnemyType(
EAIUnitType expectedEnemyType)
979 m_eExpectedEnemyType = expectedEnemyType;
984 void ResetExpectedEnemyType()
986 m_eExpectedEnemyType =
EAIUnitType.UnitType_Infantry;
996 void GetSelectedWeaponAndMagazine(out
BaseWeaponComponent outWeaponComp, out
int outMuzzleId, out BaseMagazineComponent outMagazineComp)
998 if (m_SelectedWeaponComp)
1000 outWeaponComp = m_SelectedWeaponComp;
1001 outMagazineComp = m_SelectedMagazineComp;
1002 outMuzzleId = m_iSelectedMuzzle;
1006 outWeaponComp =
null;
1008 outMagazineComp =
null;
1017 if (m_SelectedWeaponComp)
1019 outWeaponComp = m_SelectedWeaponComp;
1020 outMuzzleId = m_iSelectedMuzzle;
1024 outWeaponComp =
null;
1033 if (m_SelectedWeaponComp)
1034 return m_SelectedWeaponComp.GetWeaponType();
1043 void GetSelectedWeaponProperties(out
float outMinDistance, out
float outMaxDistance, out
bool outDirectDamage)
1045 outMinDistance = m_fSelectedWeaponMinDist;
1046 outMaxDistance = m_fSelectedWeaponMaxDist;
1047 outDirectDamage = m_bSelectedWeaponDirectDamage;
1052 bool GetSelectedWeaponDirectDamage()
1054 return m_bSelectedWeaponDirectDamage;
1059 float GetSelectedWeaponMinDist()
1061 return m_fSelectedWeaponMinDist;
1066 float GetSelectedWeaponMaxDist()
1068 return m_fSelectedWeaponMaxDist;
1073 ResourceName GetSelectedWeaponResource()
1075 return m_SelectedWeaponResource;
1082 return m_eUnitTypesCanAttack;
1091 void EvaluateExpectedWeapon(out
BaseWeaponComponent outWeaponComp, out
int outMuzzleId, out BaseMagazineComponent outMagazineComp)
1093 bool useCompartmentWeapons =
m_AIInfo.HasUnitState(EUnitState.IN_TURRET);
1094 bool success = m_WeaponTargetSelector.SelectWeaponAgainstUnitType(m_eExpectedEnemyType, useCompartmentWeapons);
1100 BaseMagazineComponent magazineComp;
1102 m_WeaponTargetSelector.GetSelectedWeapon(weaponComp, muzzleId, magazineComp);
1104 outWeaponComp = weaponComp;
1105 outMuzzleId = muzzleId;
1106 outMagazineComp = magazineComp;
1110 outWeaponComp =
null;
1112 outMagazineComp =
null;
1121 return m_WeaponTargetSelector.HasWeaponOfType(weaponType,
false);
1130 return m_WeaponTargetSelector.FindWeaponOfType(weaponType,
false);
1137 int GetMagazineCount(
typename magazineWell,
bool countMagazineInWeapon =
false)
1139 int count = m_WeaponTargetSelector.GetMagazineCount(magazineWell,
false);
1140 return count - 1 + countMagazineInWeapon;
1146 super.OnPostInit(owner);
1147 SetEventMask(owner, EntityEvent.INIT);
1151 override void EOnInit(IEntity owner)
1155 ChimeraCharacter character = ChimeraCharacter.Cast(owner);
1175 if (m_CompartmentAccess)
1177 m_CompartmentAccess.GetOnCompartmentEntered().Insert(Event_OnCompartmentEntered);
1178 m_CompartmentAccess.GetOnCompartmentLeft().Insert(Event_OnCompartmentLeft);
1182 m_Perception = PerceptionComponent.Cast(owner.FindComponent(PerceptionComponent));
1184 BaseWorld world =
GetGame().GetWorld();
1187 float worldTime = world.GetWorldTime();
1188 m_fNextWeaponTargetEvaluation_ms = worldTime + Math.RandomFloat(0, WEAPON_TARGET_UPDATE_PERIOD_MS);
1191 SetCombatType(m_eDefaultCombatType);
1195 InitWeaponTargetSelector(owner);
1198 m_DamageManager = SCR_DamageManagerComponent.Cast(owner.FindComponent(SCR_DamageManagerComponent));
1201 m_DamageManager.GetOnDamageOverTimeAdded().Insert(Event_OnDamageOverTimeAdded);
1205 AIControlComponent ctrl = AIControlComponent.Cast(owner.FindComponent(AIControlComponent));
1212 m_ConfigComponent = SCR_AIConfigComponent.Cast(agent.FindComponent(SCR_AIConfigComponent));
1213 m_Utility = SCR_AIUtilityComponent.Cast(agent.FindComponent(SCR_AIUtilityComponent));
1219 override void OnDelete(IEntity owner)
1221 if (m_CompartmentAccess)
1223 m_CompartmentAccess.GetOnCompartmentEntered().Remove(Event_OnCompartmentEntered);
1224 m_CompartmentAccess.GetOnCompartmentLeft().Remove(Event_OnCompartmentLeft);
1235 m_DamageManager.GetOnDamageOverTimeAdded().Remove(Event_OnDamageOverTimeAdded);
1241 protected void InitWeaponTargetSelector(IEntity owner)
1243 m_WeaponTargetSelector.Init(owner);
1246 m_WeaponTargetSelector.SetSelectionProperties(TARGET_MAX_LAST_SEEN_DIRECT_ATTACK, TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK, TARGET_MAX_LAST_SEEN, TARGET_MIN_INDIRECT_TRACE_FRACTION_MIN,
1247 TARGET_MAX_DISTANCE_INFANTRY, TARGET_MAX_DISTANCE_VEHICLE, TARGET_MAX_TIME_SINCE_ENDANGERED, TARGET_MAX_DISTANCE_DISARMED);
1249 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Infantry, 100.0, -0.1);
1250 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleUnarmored, 99.0, -0.08);
1251 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleMedium, 150.0, -0.15);
1252 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleHeavy, 200.0, -0.15);
1253 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Aircraft, 90.0, -0.015);
1254 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Fortification, 40.0, -0.1);
1261 void UpdatePerceptionFactor(PerceptionComponent perceptionComp,
SCR_AIThreatSystem threatSystem)
1263 EAIThreatState threatState = threatSystem.GetState();
1264 float perceptionFactor;
1265 switch (threatState)
1267 case EAIThreatState.SAFE:
1268 perceptionFactor = PERCEPTION_FACTOR_SAFE;
break;
1269 case EAIThreatState.VIGILANT:
1270 perceptionFactor = PERCEPTION_FACTOR_VIGILANT;
break;
1271 case EAIThreatState.ALERTED:
1272 perceptionFactor = PERCEPTION_FACTOR_ALERTED;
break;
1273 case EAIThreatState.THREATENED:
1274 perceptionFactor = PERCEPTION_FACTOR_THREATENED;
break;
1277 perceptionFactor *= m_fEquipmentPerceptionFactor;
1280 perceptionComp.SetPerceptionFactor(perceptionFactor);
1284 protected void RecalculateEquipmentPerceptionFactor()
1286 if (m_eCurrentGadgetType == EGadgetType.BINOCULARS && m_bGadgetFocus)
1287 m_fEquipmentPerceptionFactor = PERCEPTION_FACTOR_EQUIPMENT_BINOCULARS;
1289 m_fEquipmentPerceptionFactor = PERCEPTION_FACTOR_EQUIPMENT_NONE;
1294 void ~SCR_AICombatComponent()
1296 GetGame().GetCallqueue().Remove(Event_OnTimerAfterInventoryChanged);
1301 void DebugPrintToWidget(TextWidget w)
1303 string str =
string.Format(
"\n%1", m_SelectedTarget.ToString());
1304 if (m_SelectedTarget)
1305 str = str +
string.Format(
"\n%1", m_SelectedTarget.GetTimeSinceSeen());
1318 AIControlComponent controlComp = AIControlComponent.Cast(
GetOwner().FindComponent(AIControlComponent));
1334 AddDebugMessage(
string.Format(
"FindTargetByEntity: did not find target: %1", ent), LogLevel.WARNING);
1335 Print(
string.Format(
"FindTargetByEntity: did not find target: %1", ent), LogLevel.WARNING);
1344 void UpdateLastSeenPosition(IEntity entity, notnull SCR_AITargetInfo targetInfo)
1350 if (targetInfo.m_fTimestamp > tgt.GetTimeLastSeen())
1351 tgt.UpdateLastSeenPosition(targetInfo.m_vWorldPos, targetInfo.m_fTimestamp);
1358 void UpdateLastSeenPosition(notnull
BaseTarget tgt, notnull SCR_AITargetInfo targetInfo)
1360 if (targetInfo.m_fTimestamp > tgt.GetTimeLastSeen())
1361 tgt.UpdateLastSeenPosition(targetInfo.m_vWorldPos, targetInfo.m_fTimestamp);
1366 protected void AddDebugMessage(
string str, LogLevel logLevel = LogLevel.NORMAL)
1368 AIControlComponent controlComp = AIControlComponent.Cast(
GetOwner().FindComponent(AIControlComponent));
1369 AIAgent agent = controlComp.GetAIAgent();
1372 SCR_AIInfoBaseComponent infoComp = SCR_AIInfoBaseComponent.Cast(agent.FindComponent(SCR_AIInfoBaseComponent));
1373 infoComp.AddDebugMessage(str, msgType:
EAIDebugMsgType.COMBAT, logLevel);