20 static const int TARGET_ENDANGERED_TIMEOUT_S = 10;
21 static const float ENDANGERING_TARGET_SCORE_MULTIPLIER = 1.05;
24 protected static const float ASSIGNED_TARGETS_SCORE_INCREMENT = 0.5;
25 protected static const float ENDANGERING_TARGETS_SCORE_INCREMENT = 15.0;
28 static const float TARGET_MAX_LAST_SEEN_VISIBLE = 0.5;
29 protected static const float TARGET_MAX_LAST_SEEN_DIRECT_ATTACK = 1.6;
30 protected static const float TARGET_MAX_LAST_SEEN_DIRECT_ATTACK_CLOSE = 4.5;
31 static const float TARGET_MIN_LAST_SEEN_INDIRECT_ATTACK = 2.0;
32 static const float TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK = 7.0;
33 static const float TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_MG = 14.0;
34 static const float TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_CLOSE = 20.0;
36 static const float TARGET_MAX_LAST_SEEN = 11.0;
37 protected static const float TARGET_MIN_INDIRECT_TRACE_FRACTION_MIN = 0.5;
38 protected static const float TARGET_MAX_DISTANCE_INFANTRY = 9999.0;
39 protected static const float TARGET_MAX_DISTANCE_VEHICLE = 700.0;
40 protected static const float TARGET_MAX_DISTANCE_DISARMED = 0.0;
41 protected static const float TARGET_MAX_TIME_SINCE_ENDANGERED = 5.0;
42 protected static const float TARGET_SCORE_RETREAT = 75.0;
43 static const float TARGET_SCORE_HIGH_PRIORITY_ATTACK = 98.5;
45 protected static ref array<EWeaponType> s_aWeaponBlacklistFragGrenades = {
EWeaponType.WT_FRAGGRENADE};
48 protected const float PERCEPTION_FACTOR_SAFE = 1.0;
49 protected const float PERCEPTION_FACTOR_VIGILANT = 2.5;
50 protected const float PERCEPTION_FACTOR_ALERTED = 2.5;
51 protected const float PERCEPTION_FACTOR_THREATENED = 0.4;
53 protected const float PERCEPTION_FACTOR_EQUIPMENT_BINOCULARS = 3.0;
54 protected const float PERCEPTION_FACTOR_EQUIPMENT_NONE = 1.0;
57 static const float CLOSE_RANGE_COMBAT_DISTANCE = 35.0;
58 static const float CLOSE_RANGE_COMBAT_DISTANCE_SQ = CLOSE_RANGE_COMBAT_DISTANCE * CLOSE_RANGE_COMBAT_DISTANCE;
61 static const float LONG_RANGE_COMBAT_DISTANCE = 280.0;
63 protected const float FRAG_GRENADE_MAX_THREAT = 0.6;
65 protected SCR_ChimeraAIAgent
m_Agent;
68 protected BaseWeaponManagerComponent m_WpnManager;
69 protected SCR_CompartmentAccessComponent m_CompartmentAccess;
71 protected PerceptionComponent m_Perception;
72 protected SCR_AIInfoComponent
m_AIInfo;
73 protected SCR_AIUtilityComponent
m_Utility;
76 protected IEntity m_CurrentVehicle;
77 protected bool m_bCurrentVehicleEvac;
78 protected SCR_BaseCompartmentManagerComponent m_CurrentVehicleCompartmentManager;
79 protected BaseCompartmentSlot m_CurrentCompartmentSlot;
80 protected TurretControllerComponent m_CurrentTurretController;
82 [
Attribute(
"50", UIWidgets.ComboBox,
"AI skill in combat",
"", ParamEnumArray.FromEnum(EAISkill) )]
83 protected EAISkill m_eAISkillDefault;
88 protected bool m_bFriendlyAimLastResult;
90 protected ref Shape m_FriendlyAimShape;
94 ref AIWeaponTargetSelector m_WeaponTargetSelector =
new AIWeaponTargetSelector();
95 private ref BaseTarget m_SelectedTarget;
97 protected bool m_SelectedTargetVisible;
98 protected vector m_SelectedTargetDestinationPos;
100 protected ref BaseTarget m_SelectedRetreatTarget;
101 protected ref array<IEntity> m_aAssignedTargets = {};
104 protected ResourceName m_SelectedWeaponResource;
107 protected BaseWeaponComponent m_SelectedWeaponComp;
108 protected BaseMagazineComponent m_SelectedMagazineComp;
109 protected int m_iSelectedMuzzle;
110 protected float m_fSelectedWeaponMinDist;
111 protected float m_fSelectedWeaponMaxDist;
112 protected bool m_bSelectedWeaponDirectDamage;
114 protected BaseCompartmentSlot m_WeaponEvaluationCompartment;
117 protected float m_fFireRateCoef = 1;
121 protected bool m_bIsFireRatePersistent =
false;
124 protected float m_fNextWeaponTargetEvaluation_ms = 0;
125 protected const float WEAPON_TARGET_UPDATE_PERIOD_MS = 500;
130 protected float m_fDismountTurretTimer;
131 protected static const float DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S = 100;
132 protected static const float TURRET_TARGET_EXCESS_ANGLE_THRESHOLD_DEG = 3.0;
133 protected const float DISMOUNT_TURRET_TIMER_MS = 1200;
134 protected static ref array<EVehicleType> s_aForbidDismountTurretsOfVehicleTypes = {
EVehicleType.APC };
135 protected const float SECTOR_DANGER_TRESHOLD = 0.4;
138 protected float m_fEquipmentPerceptionFactor = 1.0;
141 protected EGadgetType m_eCurrentGadgetType = -1;
142 protected bool m_bGadgetFocus =
false;
147 SCR_AISuppressGroupClusterBehavior behavior = SCR_AISuppressGroupClusterBehavior.Cast(
m_Utility.FindActionOfType(SCR_AISuppressGroupClusterBehavior));
162 behavior =
new SCR_AISuppressGroupClusterBehavior(
m_Utility, null, null, 0, 1, SCR_AIActionBase.PRIORITY_LEVEL_NORMAL, state);
169 void SetGroupFireRateCoef(
float coef = 1,
bool overridePersistent =
false)
172 if (m_bIsFireRatePersistent && !overridePersistent)
176 SetFireRateCoef(coef,
false);
181 void SetFireRateCoef(
float coef = 1,
bool persistent =
false)
183 m_fFireRateCoef = coef;
184 m_bIsFireRatePersistent = persistent;
189 float GetFireRateCoef()
191 return m_fFireRateCoef;
196 EAISkill GetAISkill()
202 EAISkill GetAISkillDefault()
204 return m_eAISkillDefault;
210 void SetAISkill(EAISkill skill)
213 AddDebugMessage(
string.Format(
"SetAISkill: %1",
typename.EnumToString(EAISkill, skill)));
230 UpdatePerceptionFactor(m_Perception,
m_Utility.m_ThreatSystem);
234 float GetPerceptionFactor()
244 AddDebugMessage(
"ResetAISkill");
253 BaseWeaponManagerComponent wpnManger = GetCurrentWeaponManager();
255 return wpnManger.GetCurrentWeapon();
261 BaseWeaponManagerComponent GetCurrentWeaponManager()
263 if (m_CurrentTurretController)
264 return m_CurrentTurretController.GetWeaponManager();
271 EWeaponType GetCurrentWeaponType(
bool overrideWithMuzzle =
false)
275 return SCR_AIWeaponHandling.GetWeaponType(currentWeapon, overrideWithMuzzle);
282 BaseTarget GetCurrentTarget()
284 return m_SelectedTarget;
289 BaseTarget GetRetreatTarget()
291 return m_SelectedRetreatTarget;
296 BaseTarget GetLastSeenEnemy()
298 return m_Perception.GetLastSeenTarget(
ETargetCategory.ENEMY,
float.MAX);
304 BaseTarget GetEndangeringEnemy()
306 array<BaseTarget> targets = {};
309 foreach (BaseTarget tgt : targets)
311 if (tgt.IsEndangering())
323 bool knownAsEnemy = m_Perception.GetTargetPerceptionObject(ent,
ETargetCategory.ENEMY);
324 bool knownAsDetected = m_Perception.GetTargetPerceptionObject(ent,
ETargetCategory.DETECTED);
325 return knownAsEnemy || knownAsDetected;
336 void EvaluateWeaponAndTarget(out
bool outWeaponEvent, out
bool outSelectedTargetChanged,
337 out BaseTarget outPrevTarget, out BaseTarget outCurrentTarget,
338 out
bool outRetreatTargetChanged, out
bool outCompartmentChanged)
340 float worldTime =
GetGame().GetWorld().GetWorldTime();
341 if (worldTime < m_fNextWeaponTargetEvaluation_ms)
343 outWeaponEvent =
false;
344 outSelectedTargetChanged =
false;
348 m_fNextWeaponTargetEvaluation_ms = worldTime + WEAPON_TARGET_UPDATE_PERIOD_MS;
350 SCR_ChimeraAIAgent myAgent =
m_Agent;
352 myAgent = GetAiAgent();
354 float agentThreat =
m_Utility.m_ThreatSystem.GetThreatMeasure();
356 AIGroup myGroup = myAgent.GetParentGroup();
357 SCR_AIGroupInfoComponent groupInfoComp;
359 groupInfoComp = SCR_AIGroupInfoComponent.Cast(myGroup.FindComponent(SCR_AIGroupInfoComponent));
361 BaseTarget newTarget = null;
362 bool weaponEvent =
false;
363 bool selectedTargetChanged =
false;
364 bool retreatTargetChanged =
false;
365 bool compartmentChanged =
false;
369 array<EWeaponType> weaponBlacklist;
372 if (agentThreat > FRAG_GRENADE_MAX_THREAT || !groupInfoComp.IsGrenadeThrowAllowed(myAgent))
373 weaponBlacklist = s_aWeaponBlacklistFragGrenades;
379 array<IEntity> assignedTargets;
383 assignedTargets = m_aAssignedTargets;
385 bool selectedWpnTarget = m_WeaponTargetSelector.SelectWeaponAndTarget(assignedTargets,
386 ASSIGNED_TARGETS_SCORE_INCREMENT, ENDANGERING_TARGETS_SCORE_INCREMENT,
387 useCompartmentWeapons, weaponTypesBlacklist: weaponBlacklist);
389 m_eUnitTypesCanAttack = m_WeaponTargetSelector.GetUnitTypesCanAttack();
390 if (selectedWpnTarget)
392 BaseWeaponComponent newWeaponComp;
393 BaseMagazineComponent newMagazineComp;
396 newTarget = m_WeaponTargetSelector.GetSelectedTarget();
397 m_WeaponTargetSelector.GetSelectedWeapon(newWeaponComp, newMuzzleId, newMagazineComp);
398 m_WeaponTargetSelector.GetSelectedWeaponProperties(m_fSelectedWeaponMinDist, m_fSelectedWeaponMaxDist, m_bSelectedWeaponDirectDamage);
401 weaponEvent = newWeaponComp != m_SelectedWeaponComp ||
402 newMuzzleId != m_iSelectedMuzzle ||
403 newMagazineComp != m_SelectedMagazineComp;
405 bool weaponOrMuzzleChanged = newWeaponComp != m_SelectedWeaponComp ||
406 newMuzzleId != m_iSelectedMuzzle;
408 if (weaponOrMuzzleChanged)
410 ref array<BaseMuzzleComponent> muzzles = {};
411 newWeaponComp.GetMuzzlesList(muzzles);
412 if (newMuzzleId >= muzzles.Count() || newMuzzleId < 0)
413 m_SelectedWeaponResource =
m_ConfigComponent.GetTreeNameForWeaponType(newWeaponComp.GetWeaponType(),0);
415 m_SelectedWeaponResource =
m_ConfigComponent.GetTreeNameForWeaponType(newWeaponComp.GetWeaponType(),muzzles[newMuzzleId].GetMuzzleType());
419 EWeaponType weaponType = newWeaponComp.GetWeaponType();
420 if (groupInfoComp && weaponType ==
EWeaponType.WT_FRAGGRENADE)
424 groupInfoComp.OnAgentSelectedGrenade(myAgent);
429 m_SelectedWeaponComp = newWeaponComp;
430 m_iSelectedMuzzle = newMuzzleId;
431 m_SelectedMagazineComp = newMagazineComp;
434 BaseTarget prevTarget = m_SelectedTarget;
435 if (newTarget != m_SelectedTarget)
438 AddDebugMessage(
string.Format(
"Target has changed. New: %1, Previous: %2", newTarget, m_SelectedTarget));
440 m_SelectedTarget = newTarget;
441 selectedTargetChanged =
true;
445 BaseTarget targetCantAttack;
446 float targetCantAttackScore;
447 m_WeaponTargetSelector.GetMostRelevantTargetCantAttack(targetCantAttack, targetCantAttackScore);
448 if (targetCantAttackScore < TARGET_SCORE_RETREAT)
449 targetCantAttack = null;
450 if (targetCantAttack != m_SelectedRetreatTarget)
452 m_SelectedRetreatTarget = targetCantAttack;
453 retreatTargetChanged =
true;
457 BaseCompartmentSlot currentCompartment = m_CompartmentAccess.GetCompartment();
458 if (currentCompartment != m_WeaponEvaluationCompartment)
460 compartmentChanged =
true;
461 m_WeaponEvaluationCompartment = currentCompartment;
465 if (selectedTargetChanged)
467 m_SelectedTargetVisible =
false;
468 m_SelectedTargetDestinationPos = vector.Zero;
473 bool visible = IsTargetVisible(newTarget);
474 IEntity targetEntity = newTarget.GetTargetEntity();
476 if (visible != m_SelectedTargetVisible)
478 m_SelectedTargetVisible = visible;
482 if (!visible && targetEntity)
483 m_SelectedTargetDestinationPos = targetEntity.
GetOrigin();
487 outWeaponEvent = weaponEvent;
488 outSelectedTargetChanged = selectedTargetChanged;
489 outRetreatTargetChanged = retreatTargetChanged;
490 outCompartmentChanged = compartmentChanged;
491 outCurrentTarget = newTarget;
492 outPrevTarget = prevTarget;
497 vector GetTargetDestinationPos()
499 return m_SelectedTargetDestinationPos;
503 SCR_AIInfoComponent GetAIInfoComponent()
513 bool EvaluateLowAmmo(BaseWeaponComponent weaponComp,
int muzzleId)
517 array<BaseMuzzleComponent> muzzles = {};
518 weaponComp.GetMuzzlesList(muzzles);
519 if (muzzleId >= muzzles.Count() || muzzleId < 0)
522 BaseMuzzleComponent muzzleComp = muzzles[muzzleId];
527 if (muzzleComp.IsDisposable())
531 int lowMagThreshold = GetWeaponLowMagThreshold(weaponComp);
533 return magCount < lowMagThreshold;
537 int GetWeaponLowMagThreshold(BaseWeaponComponent weapon)
539 EWeaponType wpType = SCR_AIWeaponHandling.GetWeaponType(weapon,
true);
540 SCR_AIWeaponTypeHandlingConfig config =
m_Utility.m_ConfigComponent.GetWeaponTypeHandlingConfig(wpType);
542 return SCR_AIWeaponTypeHandlingConfig.DEFAULT_LOW_MAG_THRESHOLD;
544 return config.m_iLowMagCountThreshold;
550 void Update(
float timeSliceMs)
553 if (m_CurrentTurretController)
554 EvaluateDismountTurret(timeSliceMs);
564 bool DismountTurretCondition(inout vector targetPos,
bool targetPosProvided, out
float threatPriority)
567 if (!m_CurrentTurretController)
571 if (m_SelectedTarget)
574 TurretComponent turretComp = m_CurrentTurretController.GetTurretComponent();
579 array<BaseCompartmentSlot> compartments = {};
580 m_CurrentVehicleCompartmentManager.GetCompartments(compartments);
581 foreach (BaseCompartmentSlot slot : compartments)
583 if (PilotCompartmentSlot.Cast(slot) && slot.GetOccupant())
590 if (vehicle && s_aForbidDismountTurretsOfVehicleTypes.Find(vehicle.m_eVehicleType) != -1)
594 if (!targetPosProvided)
596 BaseTarget target = m_Perception.GetClosestTarget(
ETargetCategory.DETECTED, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S);
599 targetPos = target.GetLastDetectedPosition();
600 threatPriority = SCR_AILookAction.PRIO_UNKNOWN_TARGET;
604 target = m_Perception.GetClosestTarget(
ETargetCategory.ENEMY, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S, DISMOUNT_TURRET_TARGET_LAST_SEEN_MAX_S);
607 targetPos = target.GetLastSeenPosition();
608 threatPriority = SCR_AILookAction.PRIO_ENEMY_TARGET;
615 int sectorMajor, sectorMinor;
616 m_Utility.m_SectorThreatFilter.GetActiveSectors(sectorMajor, sectorMinor);
619 if (sectorMajor == -1)
623 if (
m_Utility.m_SectorThreatFilter.GetSectorDanger(sectorMajor) < SECTOR_DANGER_TRESHOLD)
626 targetPos =
m_Utility.m_SectorThreatFilter.GetSectorPos(sectorMajor);
627 threatPriority = SCR_AILookAction.PRIO_DANGER_EVENT;
631 IEntity targetEntity = target.GetTargetEntity();
638 targetPos = targetPos + 0.5 * (bmin + bmax);
639 threatPriority = SCR_AILookAction.PRIO_ENEMY_TARGET;
645 vector angleExcess = turretComp.GetAimingAngleExcess(targetPos);
649 return angleExcess.Length() > TURRET_TARGET_EXCESS_ANGLE_THRESHOLD_DEG;
653 protected void EvaluateDismountTurret(
float timeSliceMs)
656 float dangerLookPriority;
657 bool mustDismount = DismountTurretCondition(targetPos,
false, dangerLookPriority);
661 m_fDismountTurretTimer = 0;
666 if (m_fDismountTurretTimer == -1.0)
669 m_fDismountTurretTimer += timeSliceMs;
671 if (m_fDismountTurretTimer > DISMOUNT_TURRET_TIMER_MS)
673 m_fDismountTurretTimer = -1.0;
675 TryAddDismountTurretActions(targetPos, dangerLookPriority: dangerLookPriority);
686 void TryAddDismountTurretActions(vector targetPos,
bool addGetOut =
true,
bool addGetIn =
true,
float dangerLookPriority = 0)
688 BaseCompartmentSlot compartmentSlot = m_CurrentCompartmentSlot;
689 if (!compartmentSlot)
692 if (dangerLookPriority > 0)
693 m_Utility.m_LookAction.LookAt(targetPos, dangerLookPriority);
697 AIActionBase prevGetOutAction =
m_Utility.FindActionOfType(SCR_AIGetOutVehicle);
698 if (prevGetOutAction)
701 SCR_AIGetOutVehicle getOutAction =
new SCR_AIGetOutVehicle(
m_Utility, null, compartmentSlot.GetOwner(), priority: SCR_AIActionBase.PRIORITY_BEHAVIOR_DISMOUNT_TURRET);
707 AIActionBase prevGetInAction =
m_Utility.FindActionOfType(SCR_AIGetInVehicle);
708 if (!prevGetInAction)
710 SCR_AIGetInVehicle getInAction =
new SCR_AIGetInVehicle(
m_Utility, null, compartmentSlot.
GetVehicle(), compartmentSlot,
ECompartmentType.TURRET, SCR_AIActionBase.PRIORITY_BEHAVIOR_DISMOUNT_TURRET_GET_IN);
717 protected void Event_OnInventoryChanged(
IEntity item, BaseInventoryStorageComponent storageOwner)
724 protected void Event_OnTimerAfterInventoryChanged()
735 protected void Event_OnCompartmentEntered(
IEntity vehicle, BaseCompartmentManagerComponent manager,
int mgrID,
int slotID )
737 m_CurrentCompartmentSlot = manager.FindCompartment(slotID, mgrID);
738 IEntity compartmentEntity = m_CurrentCompartmentSlot.GetOwner();
739 m_CurrentTurretController = TurretControllerComponent.Cast(compartmentEntity.
FindComponent(TurretControllerComponent));
740 m_CurrentVehicle = m_CurrentCompartmentSlot.
GetVehicle();
743 if (m_CurrentVehicle)
744 m_CurrentVehicleCompartmentManager = SCR_BaseCompartmentManagerComponent.Cast(m_CurrentVehicle.
FindComponent(SCR_BaseCompartmentManagerComponent));
746 m_CurrentVehicleCompartmentManager = null;
755 protected void Event_OnCompartmentLeft(
IEntity vehicle, BaseCompartmentManagerComponent manager,
int mgrID,
int slotID )
757 m_CurrentVehicle = null;
758 m_bCurrentVehicleEvac =
false;
759 m_CurrentCompartmentSlot = null;
760 m_CurrentTurretController = null;
764 protected void Event_OnGadgetStateChanged(
IEntity gadget,
bool isInHand,
bool isOnGround)
768 SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(gadget.
FindComponent(SCR_GadgetComponent));
770 m_eCurrentGadgetType = gadgetComp.GetType();
772 m_eCurrentGadgetType = -1;
775 m_eCurrentGadgetType = -1;
777 RecalculateEquipmentPerceptionFactor();
781 protected void Event_OnGadgetFocusStateChanged(
IEntity gadget,
bool isFocused)
783 m_bGadgetFocus = isFocused;
784 RecalculateEquipmentPerceptionFactor();
788 protected void Event_OnDamage(BaseDamageContext damageContext)
790 if (damageContext.damageType !=
EDamageType.FIRE || !
m_Utility || !m_CurrentVehicle || m_bCurrentVehicleEvac)
794 m_bCurrentVehicleEvac =
true;
796 SCR_AIGetOutVehicle behaviorGetOut =
new SCR_AIGetOutVehicle(
m_Utility, null, m_CurrentVehicle, priority: SCR_AIActionBase.PRIORITY_BEHAVIOR_GET_OUT_VEHICLE_HIGH_PRIORITY);
799 SCR_AIMoveFromDangerBehavior behaviorMoveFromDanger =
new SCR_AIMoveFromDangerBehavior(
m_Utility, null, m_CurrentVehicle.
GetOrigin(), m_CurrentVehicle);
800 m_Utility.AddAction(behaviorMoveFromDanger);
804 protected void Event_OnDamageEffectAdded(notnull SCR_DamageEffect dmgEffect)
809 SCR_AIActionBase currentAction = SCR_AIActionBase.Cast(
m_Utility.GetCurrentAction());
813 float priorityLevelClamped = currentAction.GetRestrictedPriorityLevel();
815 if (!
m_Utility.m_AIInfo.HasUnitState(EUnitState.UNCONSCIOUS) &&
m_Utility.m_AIInfo.HasRole(EUnitRole.MEDIC))
817 if (!
m_Utility.HasActionOfType(SCR_AIHealBehavior))
820 SCR_AIHealBehavior behavior =
new SCR_AIHealBehavior(
m_Utility, null,
m_Utility.m_OwnerEntity,
true, priorityLevel: priorityLevelClamped);
827 AIGroup myGroup =
m_Agent.GetParentGroup();
831 AICommunicationComponent comms = myGroup.GetCommunicationComponent();
834 SCR_AIMessage_Wounded msg = SCR_AIMessage_Wounded.Create(
m_Utility.m_OwnerEntity);
837 msg.m_sSentFromBt =
"SCR_AICombatComponent.Event_OnDamageEffectAdded";
840 msg.SetReceiver(myGroup);
841 comms.RequestBroadcast(msg, myGroup);
860 bool IsFriendlyInAim()
862 IEntity friendlyEntInAim = m_Perception.GetFriendlyInLineOfFire();
864 if (friendlyEntInAim && DiagMenu.GetBool(
SCR_DebugMenuID.DEBUGUI_AI_SHOW_FRIENDLY_IN_AIM))
867 m_FriendlyAimShape = null;
869 m_bFriendlyAimLastResult = friendlyEntInAim != null;
871 return m_bFriendlyAimLastResult;
878 bool IsTargetVisible(notnull BaseTarget target)
884 float lastSeenMax = Math.Max(TARGET_MAX_LAST_SEEN_VISIBLE, m_Perception.GetUpdateInterval()) + 0.02;
885 bool visible = target.GetTimeSinceSeen() < lastSeenMax;
895 m_aAssignedTargets.Clear();
898 m_aAssignedTargets.Copy(assignedTargets);
899 else if (clusterState)
905 void ResetAssignedTargets()
907 m_aAssignedTargets.Clear();
913 void SetExpectedEnemyType(
EAIUnitType expectedEnemyType)
915 m_eExpectedEnemyType = expectedEnemyType;
920 void ResetExpectedEnemyType()
922 m_eExpectedEnemyType =
EAIUnitType.UnitType_Infantry;
932 void GetSelectedWeaponAndMagazine(out BaseWeaponComponent outWeaponComp, out
int outMuzzleId, out BaseMagazineComponent outMagazineComp)
934 if (m_SelectedWeaponComp)
936 outWeaponComp = m_SelectedWeaponComp;
937 outMagazineComp = m_SelectedMagazineComp;
938 outMuzzleId = m_iSelectedMuzzle;
942 outWeaponComp = null;
944 outMagazineComp = null;
951 void GetSelectedWeapon(out BaseWeaponComponent outWeaponComp, out
int outMuzzleId)
953 if (m_SelectedWeaponComp)
955 outWeaponComp = m_SelectedWeaponComp;
956 outMuzzleId = m_iSelectedMuzzle;
960 outWeaponComp = null;
969 if (m_SelectedWeaponComp)
970 return m_SelectedWeaponComp.GetWeaponType();
979 void GetSelectedWeaponProperties(out
float outMinDistance, out
float outMaxDistance, out
bool outDirectDamage)
981 outMinDistance = m_fSelectedWeaponMinDist;
982 outMaxDistance = m_fSelectedWeaponMaxDist;
983 outDirectDamage = m_bSelectedWeaponDirectDamage;
988 bool GetSelectedWeaponDirectDamage()
990 return m_bSelectedWeaponDirectDamage;
995 float GetSelectedWeaponMinDist()
997 return m_fSelectedWeaponMinDist;
1002 float GetSelectedWeaponMaxDist()
1004 return m_fSelectedWeaponMaxDist;
1009 ResourceName GetSelectedWeaponResource()
1011 return m_SelectedWeaponResource;
1018 return m_eUnitTypesCanAttack;
1027 void EvaluateExpectedWeapon(out BaseWeaponComponent outWeaponComp, out
int outMuzzleId, out BaseMagazineComponent outMagazineComp)
1030 bool success = m_WeaponTargetSelector.SelectWeaponAgainstUnitType(m_eExpectedEnemyType, useCompartmentWeapons);
1034 BaseWeaponComponent weaponComp;
1036 BaseMagazineComponent magazineComp;
1038 m_WeaponTargetSelector.GetSelectedWeapon(weaponComp, muzzleId, magazineComp);
1040 outWeaponComp = weaponComp;
1041 outMuzzleId = muzzleId;
1042 outMagazineComp = magazineComp;
1046 outWeaponComp = null;
1048 outMagazineComp = null;
1055 void EvaluateSuppressionWeapon(
EAIUnitType targetUnitType,
float distanceToTarget, out BaseWeaponComponent outWeaponComp, out
int outMuzzleId, out BaseMagazineComponent outMagazineComp)
1058 bool success = m_WeaponTargetSelector.SelectWeaponAgainstUnitTypeAndDistance(targetUnitType, distanceToTarget,
false, useCompartmentWeapons,
1059 weaponTypesWhitelist: null,
1060 weaponTypesBlacklist: s_aWeaponBlacklistFragGrenades,
1065 BaseWeaponComponent weaponComp;
1067 BaseMagazineComponent magazineComp;
1069 m_WeaponTargetSelector.GetSelectedWeapon(weaponComp, muzzleId, magazineComp);
1071 outWeaponComp = weaponComp;
1072 outMuzzleId = muzzleId;
1073 outMagazineComp = magazineComp;
1077 outWeaponComp = null;
1079 outMagazineComp = null;
1088 return m_WeaponTargetSelector.HasWeaponOfType(weaponType,
false);
1095 BaseWeaponComponent FindWeaponOfType(
EWeaponType weaponType)
1097 return m_WeaponTargetSelector.FindWeaponOfType(weaponType,
false);
1104 int GetMagazineCount(
typename magazineWell,
bool countMagazineInWeapon =
false)
1106 int count = m_WeaponTargetSelector.GetMagazineCount(magazineWell,
false);
1107 return count - 1 + countMagazineInWeapon;
1113 super.OnPostInit(owner);
1122 ChimeraCharacter character = ChimeraCharacter.Cast(owner);
1141 m_CompartmentAccess = SCR_CompartmentAccessComponent.Cast(character.GetCompartmentAccessComponent());
1142 if (m_CompartmentAccess)
1149 m_Perception = PerceptionComponent.Cast(owner.
FindComponent(PerceptionComponent));
1151 BaseWorld world =
GetGame().GetWorld();
1154 float worldTime = world.GetWorldTime();
1155 m_fNextWeaponTargetEvaluation_ms = worldTime + Math.RandomFloat(0, WEAPON_TARGET_UPDATE_PERIOD_MS);
1160 InitWeaponTargetSelector(owner);
1166 m_DamageManager.GetOnDamageEffectAdded().Insert(Event_OnDamageEffectAdded);
1170 AIControlComponent ctrl = AIControlComponent.Cast(owner.
FindComponent(AIControlComponent));
1173 SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(ctrl.GetAIAgent());
1177 m_ConfigComponent = SCR_AIConfigComponent.Cast(agent.FindComponent(SCR_AIConfigComponent));
1178 m_Utility = SCR_AIUtilityComponent.Cast(agent.FindComponent(SCR_AIUtilityComponent));
1186 if (m_CompartmentAccess)
1200 m_DamageManager.GetOnDamageEffectAdded().Remove(Event_OnDamageEffectAdded);
1206 protected void InitWeaponTargetSelector(
IEntity owner)
1208 m_WeaponTargetSelector.Init(owner);
1211 SetTargetSelectionProperties(
false);
1214 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Infantry, 100.0, -0.1);
1215 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleUnarmored, 99.0, -0.08);
1216 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleMedium, 150.0, -0.15);
1217 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_VehicleHeavy, 200.0, -0.15);
1218 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Aircraft, 90.0, -0.015);
1219 m_WeaponTargetSelector.SetTargetScoreConstants(
EAIUnitType.UnitType_Fortification, 40.0, -0.1);
1223 void SetTargetSelectionProperties(
bool closeCombat)
1228 m_WeaponTargetSelector.SetSelectionProperties(TARGET_MAX_LAST_SEEN_DIRECT_ATTACK_CLOSE, TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_CLOSE, TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK_CLOSE,
1229 TARGET_MIN_INDIRECT_TRACE_FRACTION_MIN, TARGET_MAX_DISTANCE_INFANTRY, TARGET_MAX_DISTANCE_VEHICLE, TARGET_MAX_TIME_SINCE_ENDANGERED, TARGET_MAX_DISTANCE_DISARMED);
1233 m_WeaponTargetSelector.SetSelectionProperties(TARGET_MAX_LAST_SEEN_DIRECT_ATTACK, TARGET_MAX_LAST_SEEN_INDIRECT_ATTACK, TARGET_MAX_LAST_SEEN,
1234 TARGET_MIN_INDIRECT_TRACE_FRACTION_MIN, TARGET_MAX_DISTANCE_INFANTRY, TARGET_MAX_DISTANCE_VEHICLE, TARGET_MAX_TIME_SINCE_ENDANGERED, TARGET_MAX_DISTANCE_DISARMED);
1241 void UpdatePerceptionFactor(PerceptionComponent perceptionComp, SCR_AIThreatSystem threatSystem)
1243 EAIThreatState threatState = threatSystem.GetState();
1244 float perceptionFactor;
1245 switch (threatState)
1247 case EAIThreatState.SAFE:
1248 perceptionFactor = PERCEPTION_FACTOR_SAFE;
break;
1249 case EAIThreatState.VIGILANT:
1250 perceptionFactor = PERCEPTION_FACTOR_VIGILANT;
break;
1251 case EAIThreatState.ALERTED:
1252 perceptionFactor = PERCEPTION_FACTOR_ALERTED;
break;
1253 case EAIThreatState.THREATENED:
1254 perceptionFactor = PERCEPTION_FACTOR_THREATENED;
break;
1257 perceptionFactor *= m_fEquipmentPerceptionFactor;
1260 perceptionComp.SetPerceptionFactor(perceptionFactor);
1264 protected void RecalculateEquipmentPerceptionFactor()
1266 if (m_eCurrentGadgetType == EGadgetType.BINOCULARS && m_bGadgetFocus)
1267 m_fEquipmentPerceptionFactor = PERCEPTION_FACTOR_EQUIPMENT_BINOCULARS;
1269 m_fEquipmentPerceptionFactor = PERCEPTION_FACTOR_EQUIPMENT_NONE;
1274 void ~SCR_AICombatComponent()
1276 GetGame().GetCallqueue().Remove(Event_OnTimerAfterInventoryChanged);
1281 void DebugPrintToWidget(TextWidget w)
1283 string str =
string.Format(
"\n%1", m_SelectedTarget.ToString());
1284 if (m_SelectedTarget)
1285 str = str +
string.Format(
"\n%1", m_SelectedTarget.GetTimeSinceSeen());
1293 SCR_ChimeraAIAgent GetAiAgent()
1298 AIControlComponent controlComp = AIControlComponent.Cast(
GetOwner().
FindComponent(AIControlComponent));
1299 m_Agent = SCR_ChimeraAIAgent.Cast(controlComp.GetAIAgent());
1307 BaseTarget FindTargetByEntity(
IEntity ent)
1309 BaseTarget tgt = m_Perception.FindTargetPerceptionObject(ent);
1314 AddDebugMessage(
string.Format(
"FindTargetByEntity: did not find target: %1", ent),
LogLevel.WARNING);
1315 Print(
string.Format(
"FindTargetByEntity: did not find target: %1", ent),
LogLevel.WARNING);
1324 void UpdateLastSeenPosition(
IEntity entity, notnull SCR_AITargetInfo targetInfo)
1326 BaseTarget tgt = m_Perception.FindTargetPerceptionObject(entity);
1330 if (targetInfo.m_fTimestamp > tgt.GetTimeLastSeen())
1331 tgt.UpdateLastSeenPosition(targetInfo.m_vWorldPos, targetInfo.m_fTimestamp);
1338 void UpdateLastSeenPosition(notnull BaseTarget tgt, notnull SCR_AITargetInfo targetInfo)
1340 if (targetInfo.m_fTimestamp > tgt.GetTimeLastSeen())
1341 tgt.UpdateLastSeenPosition(targetInfo.m_vWorldPos, targetInfo.m_fTimestamp);
1346 [
Obsolete(
"Outdated functionality which is not used anywhere")]
1347 bool IsActionAllowed(
int action) {
return true; }
1349 [
Obsolete(
"Outdated functionality which is not used anywhere")]
1350 int GetAllowedActions() {
return 0; }
1352 [
Obsolete(
"Outdated method, does not affect anything in AI")]
1353 private void SetActionAllowed(
int action,
bool isAllowed) {}
1355 [
Obsolete(
"Use Combat Modes instead")]
1356 void SetHoldFire(
bool isHoldFire) {}
1358 [
Obsolete(
"Outdated functionality which is not used anywhere")]
1359 int GetCombatType() {
return 0; }
1361 [
Obsolete(
"Use Combat Modes instead")]
1362 void SetCombatType(
int combatType) {}
1365 void SetDefaultCombatType(
int combatType) {}
1368 void ResetCombatType() {}
1372 protected void AddDebugMessage(
string str,
LogLevel logLevel =
LogLevel.NORMAL)
1374 AIControlComponent controlComp = AIControlComponent.Cast(
GetOwner().
FindComponent(AIControlComponent));
1375 AIAgent agent = controlComp.GetAIAgent();
1378 SCR_AIInfoBaseComponent infoComp = SCR_AIInfoBaseComponent.Cast(agent.FindComponent(SCR_AIInfoBaseComponent));
1379 infoComp.AddDebugMessage(str, msgType:
EAIDebugMsgType.COMBAT, logLevel);
ArmaReforgerScripted GetGame()
enum SCR_EAIActivityCause m_Utility
SCR_ChimeraAIAgent m_Agent
SCR_AICombatComponentClass EXPERT
SCR_AICombatComponentClass VETERAN
SCR_AICombatComponentClass NOOB
SCR_AICombatComponentClass ROOKIE
void SCR_AIGroup(IEntitySource src, IEntity parent)
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
SCR_AITargetClusterState m_TargetClusterState
void SCR_AITargetClusterState(SCR_AIGroupTargetCluster cluster)
DamageManagerComponent m_DamageManager
SCR_AIInfoComponent m_AIInfo
SCR_AIConfigComponent m_ConfigComponent
SCR_InventoryStorageManagerComponent m_InventoryManager
SCR_CharacterPerceivableComponentClass m_CharacterController
float m_fPerceptionFactor
enum EVehicleType IEntity
proto external int SetEventMask(notnull IEntity owner, int mask)
proto external GenericComponent FindComponent(typename typeName)
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external void GetBounds(out vector mins, out vector maxs)
SCR_AIGroupUtilityComponent GetGroupUtilityComponent()
EAIGroupCombatMode GetCombatModeActual()
Returns actual combat mode. See comment to EvaluateCombatMode method.
bool HasUnitState(EUnitState state)
SCR_AITargetClusterState GetClusterState()
ScriptInvoker GetOnCompartmentEntered(bool createNew=true)
ScriptInvoker GetOnCompartmentLeft(bool createNew=true)
proto external GenericEntity GetOwner()
Get owner entity.
void EOnInit(IEntity owner)
enum EPhysicsLayerPresets Vehicle
proto external AIGroup GetParentGroup()
proto external void SetPerceptionFactor(float value)
Sets perception factor - how good this AI can recognize enemy, independent of enemy state....
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
@ NONE
When Shape is created and not initialized yet.
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
proto native vector Vector(float x, float y, float z)
proto external BaseWeaponComponent GetCurrentWeapon()