Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIDangerReaction_GrenadeLanding.c
Go to the documentation of this file.
3{
4 static const float GRENADE_AVOID_RADIUS = 13; // Max distance for agent to react. Must be same as in behavior tree!
5 static const float GRENADE_AVOID_RADIUS_MIN = 2; // Distance below which the reaction will be almost instantaneous (GRENADE_AVOID_REACT_MIN_TIME_MS)
6
7 static const float GRENADE_AVOID_REACT_MIN_TIME_MS = 50; // Minimal possible delay time for grenate reaction in ms
8 static const float GRENADE_AVOID_DIST_REACT_TIME_MS = 2000; // Worst possible reaction time based on distance (GRENADE_AVOID_RADIUS)
9
10 static const float GRENADE_AVOID_VIS_REACT_TIME_MS = 1100; // Worst possible reaction time based on grenade visiblity (behind the agent's back)
11
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); // Constant for quadratic curve
13
14 //-------------------------------------------------------------------------------------------
15 // Returns grenade visibility factor as float in range 0-1 based on agent body direction in relation to grenade
16 float GetGrenadeVisibilityFactor(GenericEntity entity, vector grenadePos)
17 {
18 vector agentTransform[3];
19 entity.GetTransform(agentTransform);
20 vector agentDir = agentTransform[2];
21
22 vector dirToGrenade = vector.Direction(entity.GetOrigin(), grenadePos);
23 dirToGrenade.Normalize();
24
25 float angle = vector.Dot(dirToGrenade, agentDir);
26
27 return Math.Map(angle, -1, 1, 0, 1);
28 }
29
30 //-------------------------------------------------------------------------------------------
31 // Returns reaction time in ms based on agent threat level
32 float GetThreatLevelReactionTime(notnull SCR_AIThreatSystem threatSystem)
33 {
34 EAIThreatState threatState = threatSystem.GetState();
35
36 switch (threatState)
37 {
38 case EAIThreatState.SAFE:
39 {
40 return 900;
41 }
42 break;
43 case EAIThreatState.VIGILANT:
44 {
45 return 200;
46 }
47 break;
48 case EAIThreatState.ALERTED:
49 {
50 return 100;
51 }
52 break;
53 case EAIThreatState.THREATENED:
54 {
55 return 370;
56 }
57 break;
58 }
59
60 return 1.0;
61 }
62
63 //-------------------------------------------------------------------------------------------
64 // Returns reaction time in ms based on agent sq distance to grenade
65 float GetDistanceSQReactionTime(float distanceToGrenade)
66 {
67 // Quadratic curve from min to max distance
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
72 );
73 }
74
75 //-----------------------------------------------------------------------------------------------------
76 // Return utility owner faction
77 Faction GetOwnerFaction(SCR_AIUtilityComponent utility)
78 {
79 SCR_ChimeraCharacter ownerCharacter = SCR_ChimeraCharacter.Cast(utility.m_OwnerEntity);
80 if (!ownerCharacter)
81 return null;
82
83 return ownerCharacter.GetFaction();
84 }
85
86 //-----------------------------------------------------------------------------------------------------
87 // Return character of grenade instigator
88 SCR_ChimeraCharacter GetShooterCharacter(notnull IEntity grenadeObject)
89 {
90 GrenadeMoveComponent grenadeComp = GrenadeMoveComponent.Cast(grenadeObject.FindComponent(GrenadeMoveComponent));
91 if (!grenadeComp)
92 return null;
93
94 Instigator shooterInst = grenadeComp.GetInstigator();
95 if (!shooterInst)
96 return null;
97
98 return SCR_ChimeraCharacter.Cast(shooterInst.GetInstigatorEntity());
99 }
100
101 //-----------------------------------------------------------------------------------------------------
102 // Adds grenade instigator position to group perception for potentatial investigation later
103 void AddToGroupPerception(SCR_AIUtilityComponent utility, IEntity shooter, vector observePosition, Faction faction)
104 {
105 AIGroup group = utility.GetOwner().GetParentGroup();
106 if (!group)
107 return;
108
109 SCR_AIGroupUtilityComponent groupUtilityComp = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
110 if (!groupUtilityComp)
111 return;
112
113 PerceptionManager perceptionMan = GetGame().GetPerceptionManager();
114 if (!perceptionMan)
115 return;
116
117 groupUtilityComp.m_Perception.AddOrUpdateGunshot(shooter, observePosition, faction, perceptionMan.GetTime(), true);
118 }
119
120 //-------------------------------------------------------------------------------------------
121 override bool PerformReaction(notnull SCR_AIUtilityComponent utility, notnull SCR_AIThreatSystem threatSystem, AIDangerEvent dangerEvent, int dangerEventCount)
122 {
123 IEntity grenadeObject = dangerEvent.GetObject();
124 if (grenadeObject)
125 {
126 vector grenadePos = grenadeObject.GetOrigin();
127 vector agentPos = utility.GetOrigin();
128 float distanceToGrenade = vector.Distance(utility.GetOrigin(), grenadePos);
129 if (distanceToGrenade < GRENADE_AVOID_RADIUS)
130 {
131 vector observePosition = vector.Zero;
132 SCR_ChimeraCharacter shooter = GetShooterCharacter(grenadeObject);
133 Faction ownerFaction = GetOwnerFaction(utility);
134 Faction shooterFaction = shooter.GetFaction();
135
136 // Filter out friendlies
137 if (ownerFaction && shooter && !ownerFaction.IsFactionFriendly(shooterFaction))
138 AddToGroupPerception(utility, shooter, shooter.GetOrigin(), shooterFaction);
139
140 float reactionDelay = GRENADE_AVOID_REACT_MIN_TIME_MS;
141
142 if (distanceToGrenade > GRENADE_AVOID_RADIUS_MIN)
143 {
144 float visibilityFactor = GetGrenadeVisibilityFactor(utility.m_OwnerEntity, grenadePos);
145 float visbilityReactionTime = GRENADE_AVOID_VIS_REACT_TIME_MS * (1 - visibilityFactor);
146 float threatLevelReactionTime = GetThreatLevelReactionTime(threatSystem);
147 float distanceReactionTime = GetDistanceSQReactionTime(distanceToGrenade);
148
149 reactionDelay += visbilityReactionTime + threatLevelReactionTime + distanceReactionTime;
150
151 #ifdef AI_DEBUG
152 AddDebugMessage(utility, string.Format("Delayed grenade reaction (visFact: %1 visReactTime: %2ms ThreatLvlTime: %3ms distReactTime %4ms distanceToGrenade %5)", visibilityFactor, visbilityReactionTime, threatLevelReactionTime, distanceReactionTime, distanceToGrenade));
153 #endif
154 } else {
155 #ifdef AI_DEBUG
156 AddDebugMessage(utility, string.Format("Grenade distance below min treshold, quick reaction (distanceToGrenade: %1)", distanceToGrenade));
157 #endif
158 }
159
160 SCR_AIMoveFromDangerBehavior behavior = new SCR_AIMoveFromGrenadeBehavior(utility, null, vector.Zero, grenadeObject, reactionDelay, observePosition);
161 utility.AddAction(behavior);
162 return true;
163 }
164 }
165 return false;
166 }
167};
ArmaReforgerScripted GetGame()
Definition game.c:1398
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
Event which gets broadcasted from danger-causing places to AI.
proto external vector GetOrigin()
proto external void GetTransform(out vector mat[])
Definition Math.c:13
void AddOrUpdateGunshot(notnull IEntity shooter, vector worldPos, Faction faction, float timestamp, bool endangering)
ref SCR_AIGroupPerception m_Perception