Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIGroupFireteamManager.c
Go to the documentation of this file.
3
4typedef array<ref SCR_AIGroupFireteam> TAIFireteamArray;
5
7{
8 protected const int FIRETEAM_MIN_SIZE = 1;
9
11 protected ref array<ref SCR_AIGroupFireteam> m_aFireteams = {};
12 bool m_bRebalanceFireteams = false; // True when fireteams become unbalanced
13
14 // Fireteam events
15 protected ref ScriptInvokerBase<SCR_AIOnFireteamRemoved> Event_OnFireteamRemoved = new ScriptInvokerBase<SCR_AIOnFireteamRemoved>();
16
17 //---------------------------------------------------------------------------------------------------
19 {
20 m_Group = group;
21 }
22
23 //---------------------------------------------------------------------------------------------------
24 ScriptInvokerBase<SCR_AIOnFireteamRemoved> GetOnFireteamRemoved()
25 {
27 }
28
29 //---------------------------------------------------------------------------------------------------
31 void OnAgentAdded(AIAgent agent)
32 {
33 // Add to fireteam
34 // We find smallest fireteam and rebalance them later
35 typename ftTypename = SCR_AIGroupFireteam;
37 if (!destFt)
38 destFt = CreateFireteam(m_aFireteams, ftTypename);
39 destFt.AddMember(agent);
40
42 }
43
44 //---------------------------------------------------------------------------------------------------
46 void OnAgentRemoved(AIAgent agent)
47 {
48 // Remove from fireteam
50 if (ft)
51 {
52 ft.RemoveMember(agent); // bye
53
54 int ftSize = ft.GetMemberCount();
55 if (ftSize == 0)
57
58 // Rebalance fireteams later
60 }
61 }
62
63 //---------------------------------------------------------------------------------------------------
64 void OnAgentAssignedToVehicle(notnull AIAgent agent, notnull SCR_AIVehicleUsageComponent vehicleComp, ECompartmentType compType)
65 {
66 // Remove from current fireteam
67 SCR_AIGroupFireteam prevFt = FindFireteam(agent);
68
69 if (prevFt)
70 {
71 prevFt.RemoveMember(agent);
72
73 int ftSize = prevFt.GetMemberCount();
74 if (ftSize == 0)
76 }
77
78 // Depending on compartment type, we will add the agent to specific type of fireteam
79 // Which was created for this vehicle
80 typename ftTypename;
81 if (compType == ECompartmentType.CARGO)
82 ftTypename = SCR_AIGroupFireteamVehicleCargo;
83 else
84 ftTypename = SCR_AIGroupFireteamVehicleCrew;
85
86 array<ref SCR_AIGroupFireteam> ftsOfVehicle = {};
87 FindFireteamsOfVehicle(ftsOfVehicle, vehicleComp, ftTypename);
89 if (!ft)
90 {
92 ft.SetVehicle(vehicleComp);
93 }
94 ft.AddMember(agent);
95
97 }
98
99 //---------------------------------------------------------------------------------------------------
100 void OnAgentUnassignedFromVehicle(AIAgent agent, notnull SCR_AIVehicleUsageComponent vehicleComp)
101 {
102 // Remove from current fireteam
103 SCR_AIGroupFireteam prevFt = FindFireteam(agent);
104
105 if (prevFt)
106 {
107 prevFt.RemoveMember(agent);
108
109 int ftSize = prevFt.GetMemberCount();
110 if (ftSize == 0)
112 }
113
114 // Add to a generic fireteam
115 typename ftTypename = SCR_AIGroupFireteam;
117 if (!destFt)
118 destFt = CreateFireteam(m_aFireteams, ftTypename);
119 destFt.AddMember(agent);
120
121 // Rebalance fireteams later
123 }
124
125 //---------------------------------------------------------------------------------------------------
128 {
129 array<ref SCR_AIGroupFireteam> fireteamsOfVehicle = {};
130 FindFireteamsOfVehicle(fireteamsOfVehicle, vehicleComp, SCR_AIGroupFireteamVehicleBase);
131
132 array<AIAgent> agents = {};
133 foreach (SCR_AIGroupFireteam ft : fireteamsOfVehicle)
134 {
135 agents.Clear();
136 ft.GetMembers(agents);
137 foreach (AIAgent agent : agents)
138 OnAgentUnassignedFromVehicle(agent, vehicleComp);
139 }
140 }
141
142 //---------------------------------------------------------------------------------------------------
143 // Tries to find at least 'count' free fireteams. Returns true if it was able to achieve this amount of fireteams.
144 bool FindFreeFireteams(notnull array<SCR_AIGroupFireteam> outFireteams, int count, typename ftTypename, array<SCR_AIGroupFireteam> fireteamsExclude = null)
145 {
146 outFireteams.Clear();
147 for (int i = 0; i < m_aFireteams.Count(); i++)
148 {
150
151 if (ft.Type() != ftTypename)
152 continue;
153
154 if (!ft.IsLocked())
155 {
156 if (!fireteamsExclude || (fireteamsExclude && fireteamsExclude.Find(ft) == -1))
157 {
158 outFireteams.Insert(ft);
159 if (outFireteams.Count() == count)
160 return true;
161 }
162 }
163 }
164
165 return false;
166 }
167
168 //---------------------------------------------------------------------------------------------------
169 // Returns all free fireteams
170 void GetFreeFireteams(notnull array<SCR_AIGroupFireteam> outFireteams, typename ftTypename, array<SCR_AIGroupFireteam> fireteamsExclude = null)
171 {
172 outFireteams.Clear();
173 for (int i = 0; i < m_aFireteams.Count(); i++)
174 {
176
177 if (ft.Type() != ftTypename)
178 continue;
179
180 if (!ft.IsLocked())
181 {
182 if (!fireteamsExclude || (fireteamsExclude && fireteamsExclude.Find(ft) == -1))
183 {
184 outFireteams.Insert(ft);
185 }
186 }
187 }
188 }
189
190 //---------------------------------------------------------------------------------------------------
193 {
194 foreach (SCR_AIGroupFireteam ft : m_aFireteams)
195 {
196 if (ft.HasMember(agent))
197 return ft;
198 }
199 return null;
200 }
201
202 //---------------------------------------------------------------------------------------------------
203 void FindFireteamsOfVehicle(notnull array<ref SCR_AIGroupFireteam> outFireteams, notnull SCR_AIVehicleUsageComponent vehicleComp, typename ftType)
204 {
205 foreach (SCR_AIGroupFireteam ft : m_aFireteams)
206 {
208 if (!ftVehicle)
209 continue;
210 if (ftVehicle.Type() != ftType)
211 continue;
212 if (ftVehicle.GetVehicle() == vehicleComp)
213 outFireteams.Insert(ftVehicle);
214 }
215 }
216
217 //---------------------------------------------------------------------------------------------------
219 {
220 return m_aFireteams.Count();
221 }
222
223 //---------------------------------------------------------------------------------------------------
225 {
226 foreach (int id, auto _ft : m_aFireteams)
227 {
228 if (_ft == ft)
229 return id;
230 }
231 return -1;
232 }
233
234 //---------------------------------------------------------------------------------------------------
236 {
237 // Rebalance all normal fireteams
238 array<ref SCR_AIGroupFireteam> normalFireteams = {};
239 foreach (auto ft : m_aFireteams)
240 {
241 if (ft.Type() == SCR_AIGroupFireteam)
242 normalFireteams.Insert(ft);
243 }
244
245 if (RebalanceFireteams(normalFireteams, SCR_AIGroupFireteam))
246 m_bRebalanceFireteams = false;
247
248 // Rebalance all vehicle-associated cargo fireteams
249 // For each vehicle, find all cargo fireteams associated with it
251 foreach (SCR_AIGroupFireteam ft : m_aFireteams)
252 {
253 SCR_AIGroupFireteamVehicleCargo ftCargo = SCR_AIGroupFireteamVehicleCargo.Cast(ft);
254 if (!ftCargo || !ftCargo.GetVehicle())
255 continue;
256
257 TAIFireteamArray ftArray;
258 if (!m.Find(ftCargo.GetVehicle(), ftArray))
259 {
260 ftArray = new TAIFireteamArray();
261 m.Insert(ftCargo.GetVehicle(), ftArray);
262 }
263 ftArray.Insert(ftCargo);
264 }
265
266 foreach (SCR_AIVehicleUsageComponent vehicleComp, TAIFireteamArray ftArray : m)
267 {
268 // All cargo fireteams of that vehicle are rebalanced together
269 RebalanceFireteams(ftArray, SCR_AIGroupFireteamVehicleCargo);
270
271 // All fireteams which have been created must be associated with this vehicle
272 foreach (SCR_AIGroupFireteam ft : ftArray)
273 SCR_AIGroupFireteamVehicleBase.Cast(ft).SetVehicle(vehicleComp);
274 }
275 }
276
277
278
279 //---------------------------------------------------------------------------------------------------
280 // PROTECTED / INTERNAL
281
282 //---------------------------------------------------------------------------------------------------
284 protected SCR_AIGroupFireteam CreateFireteam(notnull array<ref SCR_AIGroupFireteam> fireteams, typename t)
285 {
287 fireteams.Insert(ft);
288 if (fireteams != m_aFireteams)
289 m_aFireteams.Insert(ft);
290 return ft;
291 }
292
293 //---------------------------------------------------------------------------------------------------
294 protected static SCR_AIGroupFireteam FireteamFactory(typename t)
295 {
296 switch (t)
297 {
299 return new SCR_AIGroupFireteam();
300 case SCR_AIGroupFireteamVehicleCrew:
301 return new SCR_AIGroupFireteamVehicleCrew();
302 case SCR_AIGroupFireteamVehicleCargo:
303 return new SCR_AIGroupFireteamVehicleCargo();
304 }
305 return null;
306 }
307
308 //---------------------------------------------------------------------------------------------------
309 protected void RemoveFireteam(notnull array<ref SCR_AIGroupFireteam> fireteams, SCR_AIGroupFireteam ft)
310 {
311 int id = fireteams.Find(ft);
312 if (id == -1)
313 return;
314
315 if (ft.GetMemberCount() != 0)
316 {
317 Print("SCR_AIGroupUtilityComponent: removing a non-empty fireteam", LogLevel.ERROR);
318 return;
319 }
320
321 Event_OnFireteamRemoved.Invoke(ft);
322
323 fireteams.Remove(id);
324
325 if (fireteams != m_aFireteams)
326 {
327 int _id = m_aFireteams.Find(ft);
328 if (_id != -1)
329 m_aFireteams.Remove(_id);
330 }
331 }
332
333 //---------------------------------------------------------------------------------------------------
334 protected static SCR_AIGroupFireteam FindSmallestFireteam(notnull array<ref SCR_AIGroupFireteam> fireteams, typename fireteamTypename, array<SCR_AIGroupFireteam> fireteamsExclude = null)
335 {
336 if (fireteams.IsEmpty())
337 return null;
338
339 int minSize = int.MAX;
341 for (int i = 0; i < fireteams.Count(); i++)
342 {
343 SCR_AIGroupFireteam ft = fireteams[i];
344
345 if (ft.Type() != fireteamTypename)
346 continue;
347
348 int size = ft.GetMemberCount();
349 if (size < minSize)
350 {
351 if (!fireteamsExclude || (fireteamsExclude && fireteamsExclude.Find(ft) == -1))
352 {
353 minSize = size;
354 outFt = ft;
355 }
356 }
357 }
358
359 return outFt;
360 }
361
362 //---------------------------------------------------------------------------------------------------
363 protected static SCR_AIGroupFireteam FindBiggestFireteam(notnull array<ref SCR_AIGroupFireteam> fireteams, typename fireteamTypename, notnull array<SCR_AIGroupFireteam> fireteamsExclude = null)
364 {
365 if (fireteams.IsEmpty())
366 return null;
367
368 int maxSize = int.MIN;
370 for (int i = 0; i < fireteams.Count(); i++)
371 {
372 SCR_AIGroupFireteam ft = fireteams[i];
373
374 if (ft.Type() != fireteamTypename)
375 continue;
376
377 int size = ft.GetMemberCount();
378 if (size > maxSize)
379 {
380 if (!fireteamsExclude || (fireteamsExclude && fireteamsExclude.Find(ft) == -1))
381 {
382 maxSize = size;
383 outFt = ft;
384 }
385 }
386 }
387
388 return outFt;
389 }
390
391 //---------------------------------------------------------------------------------------------------
392 protected static int GetMaxFireteamSize(int groupSize)
393 {
394 if (groupSize >= 12)
395 return 4;
396 else if (groupSize > 4)
397 return 3;
398 else if (groupSize == 4)
399 return 2; // When exactly 4 members, we want two fireteams of 2 members
400 else if (groupSize == 3)
401 return 2; // When 3 members, one fireteam of 2, one fireteam of 1
402 else if (groupSize == 2)
403 return 1;
404 else
405 return groupSize; // When below 4 members, one fireteam or 1-2
406 }
407
408 //---------------------------------------------------------------------------------------------------
409 protected bool RebalanceFireteams(array<ref SCR_AIGroupFireteam> existingFireteams, typename ftTypename)
410 {
411 int agentsCount = 0;
412 foreach (SCR_AIGroupFireteam ft : existingFireteams)
413 agentsCount += ft.GetMemberCount();
414
415 // Bail if group size is 0
416 if (agentsCount == 0)
417 return true;
418
419 int maxFtSize = GetMaxFireteamSize(agentsCount);
420 float fMaxFtSize = maxFtSize;
421 float fAgentsCount = agentsCount;
422
423 int desiredFtCount = Math.Ceil(fAgentsCount / fMaxFtSize);
424
425 if (existingFireteams.Count() < desiredFtCount)
426 {
427 // Create new fireteams
428 int newFtCount = desiredFtCount - existingFireteams.Count();
429 for (int i = 0; i < newFtCount; i++)
430 CreateFireteam(existingFireteams, ftTypename);
431 }
432 else if (existingFireteams.Count() > desiredFtCount)
433 {
434 // Delete fireteams ...
435
436 int deleteFtCount = existingFireteams.Count() - desiredFtCount;
437 array<SCR_AIGroupFireteam> fireteamsDelete = {};
438
439 // Find smallelst fireteams for deletion
440 for (int i = 0; i < deleteFtCount; i++)
441 {
442 SCR_AIGroupFireteam smallestFt = FindSmallestFireteam(existingFireteams, ftTypename, fireteamsDelete);
443 fireteamsDelete.Insert(smallestFt);
444 }
445
446 // Move members from those selected fireteams, and delete them
447 foreach (SCR_AIGroupFireteam fireteamDelete : fireteamsDelete)
448 {
449 SCR_AIGroupFireteam destinationFt = FindSmallestFireteam(existingFireteams, ftTypename, fireteamsDelete);
450 destinationFt.MoveMembersFrom(fireteamDelete, fireteamDelete.GetMemberCount());
451 RemoveFireteam(existingFireteams, fireteamDelete);
452 }
453 }
454
455 array<SCR_AIGroupFireteam> fireteamsTooBig = {};
456 array<SCR_AIGroupFireteam> fireteamsTooSmall = {};
457 CountUnbalancedFireteams(existingFireteams, maxFtSize, fireteamsTooBig, fireteamsTooSmall);
458
459 //array<SCR_AIGroupFireteam> fireteamsExclude = {};
460 bool failed = false;
461 int nIterations = 0;
462 const int maxIterations = 128;
463 while ((!fireteamsTooBig.IsEmpty() || !fireteamsTooSmall.IsEmpty()) && !failed && nIterations < maxIterations)
464 {
465 if (!fireteamsTooBig.IsEmpty())
466 {
467 // First split big fireteams
468 SCR_AIGroupFireteam srcFt = fireteamsTooBig[0];
469
470 // Take one big fireteam and move some members to smaller fireteams
471 int nExcessMembers = srcFt.GetMemberCount() - maxFtSize;
472 for (int i = 0; i < nExcessMembers; i++)
473 {
474 SCR_AIGroupFireteam dstFt = FindSmallestFireteam(existingFireteams, ftTypename, fireteamsTooBig);
475 if (!dstFt)
476 {
477 // It shouldn't be possible
478 Print(string.Format("SCR_AIGroupUtilityComponent: failed to reorganize fireteams, all other fireteams are full. %1",
480 failed = true;
481 break;
482 }
483 else
484 {
485 dstFt.MoveMembersFrom(srcFt, 1);
486 }
487 }
488 }
489 else if (!fireteamsTooSmall.IsEmpty())
490 {
491 // Second fill up the smallest fireteams
492 SCR_AIGroupFireteam dstFt = fireteamsTooSmall[0];
493
494 int nLackMembers = FIRETEAM_MIN_SIZE - dstFt.GetMemberCount(); // How many more members we need
495
496 for (int i = 0; i < nLackMembers; i++)
497 {
498 SCR_AIGroupFireteam srcFt = FindBiggestFireteam(existingFireteams, ftTypename, fireteamsTooSmall);
499
500 if (!srcFt)
501 {
502 // It shouldn't be possible in general case
503 // It could only happen when group size is very small
504 //if (agentsCount > maxFtSize)
505 Print(string.Format("SCR_AIGroupUtilityComponent: failed to reorganize fireteams, all other fireteams are too small. %1",
507 failed = true; // For very small group size (1) it might be impossible to make 'balanced' fireteams at all, due to lack of group members
508 break;
509 }
510 else
511 {
512 dstFt.MoveMembersFrom(srcFt, 1);
513 }
514 }
515
516 }
517
518 CountUnbalancedFireteams(existingFireteams, maxFtSize, fireteamsTooBig, fireteamsTooSmall);
519 nIterations++;
520 }
521
522 if (nIterations == maxIterations)
523 {
524 Print(string.Format("SCR_AIGroupUtilityComponent: RebalanceFireteams: max amount of iterations has been reached. %1", DiagGetFireteamsData()), LogLevel.ERROR);
525 }
526
527 return true;
528 }
529 protected static void CountUnbalancedFireteams(notnull array<ref SCR_AIGroupFireteam> inFireteams, int maxFtSize, notnull array<SCR_AIGroupFireteam> fireteamsTooBig, notnull array<SCR_AIGroupFireteam> fireteamsTooSmall)
530 {
531 fireteamsTooBig.Clear();
532 fireteamsTooSmall.Clear();
533 foreach (SCR_AIGroupFireteam ft : inFireteams)
534 {
535 int size = ft.GetMemberCount();
536 if (size == maxFtSize) // Perfect
537 continue;
538
539 if (size > maxFtSize)
540 fireteamsTooBig.Insert(ft);
541 else if (size < FIRETEAM_MIN_SIZE)
542 fireteamsTooSmall.Insert(ft); // Includes empty or with one member
543 }
544 }
545
546 //---------------------------------------------------------------------------------------------------
549 {
550 string s = string.Format("Fireteams: %1: ", m_aFireteams.Count());
551 foreach (SCR_AIGroupFireteam ft : m_aFireteams)
552 {
553 string strLocked = string.Empty;
554 if (ft.IsLocked())
555 strLocked = "L";
556
557 s = s + string.Format("%1%2, ", ft.GetMemberCount(), strLocked);
558 }
559 return s;
560 }
561
562 //---------------------------------------------------------------------------------------------------
564 {
565 int bgColors[8] = {
566 Color.DARK_RED,
567 Color.DARK_GREEN,
568 Color.DARK_BLUE,
569 Color.DARK_CYAN,
570 Color.DARK_MAGENTA,
571 Color.DARK_YELLOW,
572 Color.DODGER_BLUE,
573 Color.VIOLET
574 };
575 const int bgColorsCount = 8;
576
577 /*
578 static const int DARK_BLUE = 0xff000080; // navy
579 static const int DARK_CYAN = 0xff008080; // teal
580 static const int DARK_MAGENTA = 0xff800080; // purple
581 static const int DARK_YELLOW = 0xff808000; // olive
582 };
583 */
584
585 array<AIAgent> members = {};
586 foreach (int fireteamId, SCR_AIGroupFireteam ft : m_aFireteams)
587 {
588 ft.GetMembers(members);
589 int bgColor = bgColors[fireteamId % bgColorsCount];
590 foreach (AIAgent agent : members)
591 {
592 IEntity e = agent.GetControlledEntity();
593 if (!e)
594 continue;
595 vector textPos = e.GetOrigin() + Vector (0, 0.5, 0);
596
597 string strFtType;
598 if (SCR_AIGroupFireteamVehicleCrew.Cast(ft))
599 {
600 strFtType = "Crew ";
601 textPos[1] = textPos[1] + 0.25;
602 }
603 else if (SCR_AIGroupFireteamVehicleCargo.Cast(ft))
604 {
605 strFtType = "Cargo ";
606 textPos[1] = textPos[1] + 0.5;
607 }
608
609 string text = string.Format("%1FT: %2", strFtType, fireteamId);
610 DebugTextWorldSpace.Create(GetGame().GetWorld(), text, DebugTextFlags.ONCE | DebugTextFlags.CENTER | DebugTextFlags.FACE_CAMERA,
611 textPos[0], textPos[1], textPos[2], color: Color.WHITE, bgColor: bgColor,
612 size: 13.0);
613 }
614 }
615 }
616}
AddonBuildInfoTool id
ECompartmentType
ArmaReforgerScripted GetGame()
Definition game.c:1398
int size
array< ref SCR_AIGroupFireteam > TAIFireteamArray
func SCR_AIOnFireteamRemoved
SCR_DSOperating maxSize
Definition Color.c:13
proto external vector GetOrigin()
Definition Math.c:13
void AddMember(AIAgent agent)
void MoveMembersFrom(notnull SCR_AIGroupFireteam otherFt, int count)
Moves 'count' members from other fireteam to this one.
void RemoveMember(AIAgent agent)
SCR_AIGroupFireteam FindFireteam(AIAgent agent)
Finds fireteam which has the provided agent.
static SCR_AIGroupFireteam FireteamFactory(typename t)
void OnAgentAssignedToVehicle(notnull AIAgent agent, notnull SCR_AIVehicleUsageComponent vehicleComp, ECompartmentType compType)
void OnAgentUnassignedFromVehicle(AIAgent agent, notnull SCR_AIVehicleUsageComponent vehicleComp)
string DiagGetFireteamsData()
Returns string with data about fireteams.
static void CountUnbalancedFireteams(notnull array< ref SCR_AIGroupFireteam > inFireteams, int maxFtSize, notnull array< SCR_AIGroupFireteam > fireteamsTooBig, notnull array< SCR_AIGroupFireteam > fireteamsTooSmall)
ref ScriptInvokerBase< SCR_AIOnFireteamRemoved > Event_OnFireteamRemoved
static SCR_AIGroupFireteam FindBiggestFireteam(notnull array< ref SCR_AIGroupFireteam > fireteams, typename fireteamTypename, notnull array< SCR_AIGroupFireteam > fireteamsExclude=null)
ScriptInvokerBase< SCR_AIOnFireteamRemoved > GetOnFireteamRemoved()
void SCR_AIGroupFireteamManager(SCR_AIGroup group)
void OnAgentRemoved(AIAgent agent)
Called from SCR_AIGroupUtilityComponent.
static SCR_AIGroupFireteam FindSmallestFireteam(notnull array< ref SCR_AIGroupFireteam > fireteams, typename fireteamTypename, array< SCR_AIGroupFireteam > fireteamsExclude=null)
void RemoveFireteam(notnull array< ref SCR_AIGroupFireteam > fireteams, SCR_AIGroupFireteam ft)
int GetFireteamId(notnull SCR_AIGroupFireteam ft)
void OnVehicleRemoved(SCR_AIVehicleUsageComponent vehicleComp)
Removes all fireteams related to this vehicle, soldiers are redistributed.
bool FindFreeFireteams(notnull array< SCR_AIGroupFireteam > outFireteams, int count, typename ftTypename, array< SCR_AIGroupFireteam > fireteamsExclude=null)
static int GetMaxFireteamSize(int groupSize)
void FindFireteamsOfVehicle(notnull array< ref SCR_AIGroupFireteam > outFireteams, notnull SCR_AIVehicleUsageComponent vehicleComp, typename ftType)
ref array< ref SCR_AIGroupFireteam > m_aFireteams
SCR_AIGroupFireteam CreateFireteam(notnull array< ref SCR_AIGroupFireteam > fireteams, typename t)
Creates a fireteam and registers it.
bool RebalanceFireteams(array< ref SCR_AIGroupFireteam > existingFireteams, typename ftTypename)
void GetFreeFireteams(notnull array< SCR_AIGroupFireteam > outFireteams, typename ftTypename, array< SCR_AIGroupFireteam > fireteamsExclude=null)
void OnAgentAdded(AIAgent agent)
Called from SCR_AIGroupUtilityComponent.
SCR_AIVehicleUsageComponent GetVehicle()
void SetVehicle(notnull SCR_AIVehicleUsageComponent vehicleComp)
Definition Types.c:486
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
DebugTextFlags
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
proto native vector Vector(float x, float y, float z)