4 static const float GRENADE_AVOID_RADIUS = 13;
5 static const float GRENADE_AVOID_RADIUS_MIN = 2;
7 static const float GRENADE_AVOID_REACT_MIN_TIME_MS = 50;
8 static const float GRENADE_AVOID_DIST_REACT_TIME_MS = 2000;
10 static const float GRENADE_AVOID_VIS_REACT_TIME_MS = 1100;
12 static const float GRENADE_AVOID_DIST_CURVE_PARAM = GRENADE_AVOID_DIST_REACT_TIME_MS / Math.Pow(GRENADE_AVOID_RADIUS - GRENADE_AVOID_RADIUS_MIN, 2);
16 float GetGrenadeVisibilityFactor(
GenericEntity entity, vector grenadePos)
18 vector agentTransform[3];
19 entity.GetTransform(agentTransform);
20 vector agentDir = agentTransform[2];
22 vector dirToGrenade = vector.Direction(entity.GetOrigin(), grenadePos);
23 dirToGrenade.Normalize();
25 float angle = vector.Dot(dirToGrenade, agentDir);
27 return Math.Map(angle, -1, 1, 0, 1);
34 EAIThreatState threatState = threatSystem.GetState();
38 case EAIThreatState.SAFE:
43 case EAIThreatState.VIGILANT:
48 case EAIThreatState.ALERTED:
53 case EAIThreatState.THREATENED:
65 float GetDistanceSQReactionTime(
float distanceToGrenade)
68 return GRENADE_AVOID_DIST_CURVE_PARAM * (
69 distanceToGrenade * distanceToGrenade -
70 2 * GRENADE_AVOID_RADIUS_MIN * distanceToGrenade +
71 GRENADE_AVOID_RADIUS_MIN * GRENADE_AVOID_RADIUS_MIN
77 Faction GetOwnerFaction(SCR_AIUtilityComponent utility)
79 SCR_ChimeraCharacter ownerCharacter = SCR_ChimeraCharacter.Cast(utility.m_OwnerEntity);
83 return ownerCharacter.GetFaction();
88 SCR_ChimeraCharacter GetShooterCharacter(notnull IEntity grenadeObject)
94 Instigator shooterInst = grenadeComp.GetInstigator();
98 return SCR_ChimeraCharacter.Cast(shooterInst.GetInstigatorEntity());
103 void AddToGroupPerception(SCR_AIUtilityComponent utility, IEntity shooter, vector observePosition)
105 AIGroup group = AIGroup.Cast(utility.GetOwner().GetParentGroup());
109 SCR_AIGroupUtilityComponent groupUtilityComp = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
110 if (!groupUtilityComp)
113 PerceptionManager perceptionMan =
GetGame().GetPerceptionManager();
117 groupUtilityComp.m_Perception.AddOrUpdateGunshot(shooter, observePosition, perceptionMan.GetTime());
121 override bool PerformReaction(notnull SCR_AIUtilityComponent utility, notnull
SCR_AIThreatSystem threatSystem, AIDangerEvent dangerEvent)
123 IEntity grenadeObject = dangerEvent.GetObject();
126 vector grenadePos = grenadeObject.GetOrigin();
127 vector agentPos = utility.GetOrigin();
128 float distanceToGrenade = vector.Distance(utility.GetOrigin(), grenadePos);
129 if (distanceToGrenade < GRENADE_AVOID_RADIUS)
131 vector observePosition = vector.Zero;
132 SCR_ChimeraCharacter shooter = GetShooterCharacter(grenadeObject);
133 Faction ownerFaction = GetOwnerFaction(utility);
136 if (ownerFaction && shooter && !ownerFaction.IsFactionFriendly(shooter.GetFaction()))
137 AddToGroupPerception(utility, shooter, shooter.GetOrigin());
139 float reactionDelay = GRENADE_AVOID_REACT_MIN_TIME_MS;
141 if (distanceToGrenade > GRENADE_AVOID_RADIUS_MIN)
143 float visibilityFactor = GetGrenadeVisibilityFactor(utility.m_OwnerEntity, grenadePos);
144 float visbilityReactionTime = GRENADE_AVOID_VIS_REACT_TIME_MS * (1 - visibilityFactor);
145 float threatLevelReactionTime = GetThreatLevelReactionTime(threatSystem);
146 float distanceReactionTime = GetDistanceSQReactionTime(distanceToGrenade);
148 reactionDelay += visbilityReactionTime + threatLevelReactionTime + distanceReactionTime;
151 AddDebugMessage(utility,
string.Format(
"Delayed grenade reaction (visFact: %1 visReactTime: %2ms ThreatLvlTime: %3ms distReactTime %4ms distanceToGrenade %5)", visibilityFactor, visbilityReactionTime, threatLevelReactionTime, distanceReactionTime, distanceToGrenade));
155 AddDebugMessage(utility,
string.Format(
"Grenade distance below min treshold, quick reaction (distanceToGrenade: %1)", distanceToGrenade));
160 utility.AddAction(behavior);