Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIDangerReaction_Vehicle.c
Go to the documentation of this file.
3{
4 #ifdef AI_DEBUG
5 protected ref array<ref Shape> m_aShapes = {};
6 #endif
7
8 //----------------------------------------------------------------------------------------------------------------------------------------------------------
9 override bool PerformReaction(notnull SCR_AIUtilityComponent utility, notnull SCR_AIThreatSystem threatSystem, AIDangerEvent dangerEvent, int dangerEventCount)
10 {
11 SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(utility.GetOwner());
12
13 IEntity vehicleEntity = dangerEvent.GetVictim();
14 if (!vehicleEntity)
15 return false;
16
17 /*
18 Disabled until vehicle front light tweaks
19
20 // Call driver behavior about incoming vehicle if active
21 SCR_AIIdleBehavior_Driver driverBehavior = SCR_AIIdleBehavior_Driver.Cast(utility.FindActionOfType(SCR_AIIdleBehavior_Driver));
22 if (driverBehavior)
23 driverBehavior.OnVehicleApproaching();
24 */
25
26 // Ignore if we already have an action to move from that vehicle
27 if (SCR_AIMoveFromDangerBehavior.ExistsBehaviorForEntity(utility, vehicleEntity))
28 return false;
29
30 SCR_BaseCompartmentManagerComponent compManager = SCR_BaseCompartmentManagerComponent.Cast(vehicleEntity.FindComponent(SCR_BaseCompartmentManagerComponent));
31 if (!compManager)
32 return false;
33
34 array<IEntity> occupants = {};
35 compManager.GetOccupantsOfType(occupants, ECompartmentType.PILOT);
36
37 // Ignore if no driver
38 if (occupants.Count() == 0)
39 return false;
40
41 // Different functionality if we are in vehicle
42 if (utility.m_AIInfo.HasUnitState(EUnitState.PILOT))
43 {
44
45 IEntity myVehicle = utility.m_OwnerEntity.GetRootParent();
46
47 bool incomingCollision = VehicleIntersectsMyPath(myVehicle, vehicleEntity);
48
49 if (incomingCollision)
50 {
51 if (!SCR_AIMoveFromDangerBehavior.ExistsBehaviorForEntity(utility, vehicleEntity))
52 {
54 utility, null, vehicleEntity.GetOrigin(), vehicleEntity);
55 utility.AddAction(behavior);
56 }
57 }
58
59 return true;
60 }
61 else if (!utility.m_AIInfo.HasUnitState(EUnitState.IN_VEHICLE))
62 {
63 // On foot
64 // Ignore if the behavior would fail immediately after start
65 if (!SCR_AIMoveFromIncomingVehicleBehavior.ExecuteBehaviorCondition(utility, vehicleEntity))
66 return false;
67
68 SCR_AIMoveFromDangerBehavior behavior = new SCR_AIMoveFromIncomingVehicleBehavior(utility, null, vector.Zero, dangerEntity: vehicleEntity);
69 utility.AddAction(behavior);
70
71 return true;
72 }
73
74 return false;
75 }
76
77 //----------------------------------------------------------------------------------------------------------------------------------------------------------
78 protected bool VehicleIntersectsMyPath(notnull IEntity myVehicle, notnull IEntity otherVehicle)
79 {
80 Physics myPhysics = myVehicle.GetPhysics();
81 Physics otherPhysics = otherVehicle.GetPhysics();
82
83 // Without physics, how can we know?
84 if (!myPhysics || !otherPhysics)
85 return false;
86
87 vector myVelWorld = myPhysics.GetVelocity();
88 vector otherVelWorld = otherPhysics.GetVelocity();
89
90 // otherVehicle velocity relative to myVehicle
91 vector relVelWorld = otherVelWorld - myVelWorld;
92
93 vector myBbMinLocal;
94 vector myBbMaxLocal;
95 myVehicle.GetBounds(myBbMinLocal, myBbMaxLocal);
96 vector myBbCenterLocal = 0.5 * (myBbMinLocal + myBbMaxLocal);
97 vector myBbCenterWorld = myVehicle.CoordToParent(myBbCenterLocal);
98
99 vector otherBbMinOtherLocal; // In other vehicle local space
100 vector otherBbMaxOtherLocal;
101 otherVehicle.GetBounds(otherBbMinOtherLocal, otherBbMaxOtherLocal);
102 vector otherBbCenterOtherLocal = 0.5 * (otherBbMinOtherLocal + otherBbMaxOtherLocal);
103 vector otherBbCenterWorld = otherVehicle.CoordToParent(otherBbCenterOtherLocal);
104
105 // Estimate vehicle 'radiuses' based on widths of BB
106 float myR = 0.5*(myBbMaxLocal[0] - myBbMinLocal[0]);
107 float otherR = 0.5*(otherBbMaxOtherLocal[1] - otherBbMinOtherLocal[1]);
108
109 float intersectionTime;
110 bool intersectionTestResult = MovingPointSphereIntersectionTest(otherBbCenterWorld - myBbCenterWorld, relVelWorld, myR + otherR, intersectionTime);
111
112 const float maxTimeToCollision_s = 10.0;
113 bool testResult = intersectionTestResult && (intersectionTime < maxTimeToCollision_s);
114
115 /*
116 #ifdef AI_DEBUG
117 m_aShapes.Clear();
118
119 int mySphereColor = Color.GREEN;
120 if (testResult)
121 mySphereColor = Color.RED;
122 Shape shapeMySphere = Shape.CreateSphere(mySphereColor, ShapeFlags.VISIBLE | ShapeFlags.WIREFRAME, myBbCenterWorld, otherR);
123 m_aShapes.Insert(shapeMySphere);
124
125 Shape shapeMySphereCombined = Shape.CreateSphere(mySphereColor, ShapeFlags.VISIBLE | ShapeFlags.WIREFRAME, myBbCenterWorld, myR + otherR);
126 m_aShapes.Insert(shapeMySphereCombined);
127
128 vector velLineEnd = otherBbCenterWorld + maxTimeToCollision_s*otherVelWorld;
129 Shape shapeOtherVel = Shape.Create(ShapeType.LINE, Color.RED, ShapeFlags.DEFAULT, otherBbCenterWorld, velLineEnd);
130 m_aShapes.Insert(shapeOtherVel);
131
132 vector velLineEndSize = Vector(0.15, 0.15, 0.15);
133 Shape shapeOtherVelEnd = Shape.Create(ShapeType.BBOX, Color.RED, ShapeFlags.DEFAULT, velLineEnd - velLineEndSize, velLineEnd + velLineEndSize);
134 m_aShapes.Insert(shapeOtherVelEnd);
135
136 if (testResult)
137 {
138 vector impactPosWorld = otherBbCenterWorld + intersectionTime * otherVelWorld;
139 vector impactPosSize = Vector (0.5, 0.5, 0.5);
140 Shape shapeImpactPos = Shape.Create(ShapeType.BBOX, Color.RED, ShapeFlags.DEFAULT, impactPosWorld - impactPosSize, impactPosWorld + impactPosSize);
141 m_aShapes.Insert(shapeImpactPos);
142 }
143 #endif
144 */
145
146 return testResult;
147 }
148
149 //----------------------------------------------------------------------------------------------------------------------------------------------------------
159 */
160 protected static bool MovingPointSphereIntersectionTest(vector p, vector v, float r, out float outT)
161 {
162 // This is a quadratic equation, it has up to two roots. First check if it has roots at all.
163
164 float px = p[0];
165 float py = p[1];
166 float pz = p[2];
167 float vx = v[0];
168 float vy = v[1];
169 float vz = v[2];
170
171 float vx2 = vx*vx;
172 float vy2 = vy*vy;
173 float vz2 = vz*vz;
174 float vLen2 = vx2 + vy2 + vz2;
175
176 if (vLen2 == 0)
177 {
178 outT = 0;
179 return false;
180 }
181
182 // Calculate D
183 float _a = px*vy - py*vx;
184 float _b = px*vz - pz*vx;
185 float _c = py*vz - pz*vy;
186
187 float D = r*r*vLen2 - (_a*_a) - (_b*_b) - (_c*_c);
188
189 // No solutions in real numbers
190 if (D < 0)
191 {
192 outT = 0;
193 return false;
194 }
195
196 float tBase = -(px*vx + py*vy + pz*vz)/vLen2;
197
198 if (D == 0)
199 {
200 // One intersection
201 if (tBase >= 0)
202 {
203 outT = tBase;
204 return true;
205 }
206 else
207 {
208 outT = 0;
209 return false;
210 }
211 }
212
213 float sqrtD = Math.Sqrt(D);
214 float t0 = tBase + sqrtD/vLen2;
215 float t1 = tBase - sqrtD/vLen2;
216
217 // Two solutions, we need only positive one, but smallest if there are two positives
218 if (t0 < 0 && t1 < 0)
219 {
220 // Both intersections are in the past
221 outT = 0;
222 return false;
223 }
224 else if (t0 >= 0 && t1 >= 0)
225 {
226 // Both are positive (in future), return smallest one
227 outT = Math.Min(t0, t1);
228 return true;
229 }
230 else
231 {
232 // One is positive and another isn't, return the positive one
233 if (t0 > t1)
234 outT = t0;
235 else
236 outT = t1;
237 return true;
238 }
239 }
240};
ECompartmentType
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
void SCR_AIPilotMoveFromIncomingVehicleBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, vector dangerPos, IEntity dangerEntity)
void SCR_AIMoveFromIncomingVehicleBehavior(SCR_AIUtilityComponent utility, SCR_AIActivityBase groupActivity, vector dangerPos, IEntity dangerEntity)
ref array< ref Shape > m_aShapes
Event which gets broadcasted from danger-causing places to AI.
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external IEntity GetRootParent()
Definition Math.c:13
static bool MovingPointSphereIntersectionTest(vector p, vector v, float r, out float outT)
bool VehicleIntersectsMyPath(notnull IEntity myVehicle, notnull IEntity otherVehicle)