Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_EntityHelper.c
Go to the documentation of this file.
2{
8 static Managed FindComponent(notnull IEntity entity, typename componentType, SCR_EComponentFinderQueryFlags queryFlags = SCR_EComponentFinderQueryFlags.ENTITY | SCR_EComponentFinderQueryFlags.SLOTS)
9 {
10 Managed foundComponent;
11
12 //~ Find on entity itself
13 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.ENTITY))
14 {
15 foundComponent = entity.FindComponent(componentType);
16 if (foundComponent)
17 return foundComponent;
18 }
19
20 //~ Find on slotted entities
21 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.SLOTS))
22 {
23 SlotManagerComponent slotManager = SlotManagerComponent.Cast(entity.FindComponent(SlotManagerComponent));
24 if (slotManager)
25 {
26 array<EntitySlotInfo> slotInfos = {};
27 slotManager.GetSlotInfos(slotInfos);
28 IEntity slotEntity;
29
30 foreach (EntitySlotInfo slotInfo : slotInfos)
31 {
32 slotEntity = slotInfo.GetAttachedEntity();
33 if (!slotEntity)
34 continue;
35
36 foundComponent = slotEntity.FindComponent(componentType);
37 if (foundComponent)
38 return foundComponent;
39 }
40 }
41 }
42
43 //~ Find on children
44 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.CHILDREN))
45 {
46 IEntity child = entity.GetChildren();
47
48 while (child)
49 {
50 foundComponent = child.FindComponent(componentType);
51 if (foundComponent)
52 return foundComponent;
53
54 child = child.GetSibling();
55 }
56 }
57
58 IEntity parent;
59
60 //~ Find in parent
61 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.PARENT))
62 {
63 parent = entity.GetParent();
64
65 if (parent)
66 {
67 foundComponent = parent.FindComponent(componentType);
68 if (foundComponent)
69 return foundComponent;
70 }
71 }
72
73 //~ Find on slotted entities of parent
74 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.PARENT_SLOTS))
75 {
76 if (!parent)
77 parent = entity.GetParent();
78
79 if (parent)
80 {
81 foundComponent = SCR_EntityHelper.FindComponent(parent, componentType, SCR_EComponentFinderQueryFlags.SLOTS);
82 if (foundComponent)
83 return foundComponent;
84 }
85 }
86
87 IEntity rootParent;
88
89 //~ Find in root parent
90 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.PARENT))
91 {
92 rootParent = entity.GetRootParent();
93
94 if (rootParent)
95 {
96 foundComponent = rootParent.FindComponent(componentType);
97 if (foundComponent)
98 return foundComponent;
99 }
100 }
101
102 //~ Find on slotted entities of root parent
103 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.PARENT_SLOTS))
104 {
105 if (!rootParent)
106 rootParent = entity.GetRootParent();
107
108 if (rootParent)
109 {
110 foundComponent = SCR_EntityHelper.FindComponent(rootParent, componentType, SCR_EComponentFinderQueryFlags.SLOTS);
111 if (foundComponent)
112 return foundComponent;
113 }
114 }
115
116 //~ Find in siblings
117 if (SCR_Enum.HasFlag(queryFlags, SCR_EComponentFinderQueryFlags.SIBLINGS))
118 {
119 if (!parent)
120 parent = entity.GetParent();
121
122 if (parent)
123 {
124 //~ Get siblings from parent
125 IEntity child = parent.GetChildren();
126
127 while (child)
128 {
129 //~ Ignore self
130 if (child == entity)
131 {
132 child = child.GetSibling();
133 continue;
134 }
135
136 foundComponent = child.FindComponent(componentType);
137 if (foundComponent)
138 return foundComponent;
139
140 child = child.GetSibling();
141 }
142 }
143 }
144
145 //~ Not found
146 return null;
147 }
148
149 //------------------------------------------------------------------------------------------------
154 // unused
155 static int GetChildrenCount(IEntity parent, bool recursive = false)
156 {
157 if (!parent)
158 return 0;
159
160 int num = 0;
161 IEntity child = parent.GetChildren();
162 while (child)
163 {
164 num++;
165 if (recursive)
166 num += GetChildrenCount(child);
167 child = child.GetSibling();
168 }
169
170 return num;
171 }
172
173 //------------------------------------------------------------------------------------------------
177 static void DeleteEntityAndChildren(IEntity entity)
178 {
179 RplComponent.DeleteRplEntity(entity, false);
180 }
181
182 //------------------------------------------------------------------------------------------------
185 static void DeleteBuilding(IEntity entity)
186 {
187 if (!entity)
188 return;
189
190 // Ensure deletion of interior for buildings
192 if (destructible)
193 {
195 if (destructibleComp)
196 destructibleComp.GoToDestroyedStateLoad(false);
197 }
198
199 // TODO(@jokin): Why do we need the second delete call for reload save game, even though destruction should have taken care of it?
200 RplComponent.DeleteRplEntity(entity, false);
201 }
202
203 //------------------------------------------------------------------------------------------------
207 static vector GetEntitySize(notnull IEntity entity)
208 {
209 vector entMins, entMaxs;
210 entity.GetBounds(entMins, entMaxs);
211
212 return entMaxs - entMins;
213 }
214
215 //------------------------------------------------------------------------------------------------
219 static vector GetEntityCenterWorld(notnull IEntity entity)
220 {
221 vector entMins, entMaxs;
222 entity.GetBounds(entMins, entMaxs);
223 return entity.CoordToParent((entMaxs + entMins) * 0.5);
224 }
225
226 //------------------------------------------------------------------------------------------------
229 static float GetEntityRadius(notnull IEntity entity)
230 {
231 return GetEntitySize(entity).Length() * 0.5;
232 }
233
234 //------------------------------------------------------------------------------------------------
238 static void GetHierarchyEntityList(notnull IEntity entity, notnull inout array<IEntity> output)
239 {
240 IEntity child = entity.GetChildren();
241 while (child)
242 {
243 GetHierarchyEntityList(child, output);
244 output.Insert(child);
245 child = child.GetSibling();
246 }
247 }
248
249 //------------------------------------------------------------------------------------------------
256 // unused
257 static void SnapToGround(notnull IEntity entity, array<IEntity> excludeArray = null, float maxLength = 10, vector startOffset = "0 0 0", bool onlyStatic = false)
258 {
259 vector origin = entity.GetOrigin();
260
261 // Trace against terrain and entities to detect nearest ground
262 TraceParam param = new TraceParam();
263 param.Start = origin + startOffset;
264 param.End = origin - vector.Up * maxLength;
265 param.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
266
267 if (excludeArray)
268 {
269 excludeArray.Insert(entity);
270 param.ExcludeArray = excludeArray;
271 }
272 else
273 {
274 param.Exclude = entity;
275 }
276
277 param.LayerMask = EPhysicsLayerPresets.Projectile;
278 BaseWorld world = entity.GetWorld();
279 float traceDistance;
280
281 if (onlyStatic)
282 traceDistance = world.TraceMove(param, OnlyStaticCallback);
283 else
284 traceDistance = world.TraceMove(param, null);
285
286 if (float.AlmostEqual(traceDistance, 1.0))
287 return;
288
289 entity.SetOrigin(traceDistance * (param.End - param.Start) + param.Start);
290 }
291
292 //------------------------------------------------------------------------------------------------
295 static void OrientUpToVector(vector newUp, inout vector mat[4])
296 {
297 vector origin = mat[3];
298 vector perpend = newUp.Perpend();
299 Math3D.DirectionAndUpMatrix(perpend, newUp, mat);
300
301 vector basis[4];
302 Math3D.AnglesToMatrix({ -perpend.VectorToAngles()[0], 0, 0 }, basis);
303 Math3D.MatrixMultiply3(mat, basis, mat);
304 mat[3] = origin;
305 }
306
307 //------------------------------------------------------------------------------------------------
310 // used by SnapToGround() which is unused
311 protected static bool OnlyStaticCallback(notnull IEntity entity)
312 {
313 Physics physics = entity.GetPhysics();
314 if (physics && physics.IsDynamic())
315 return false;
316
317 return true;
318 }
319
320 //------------------------------------------------------------------------------------------------
325 static IEntity GetMainParent(IEntity entity, bool self = false)
326 {
327 if (!entity)
328 return null;
329
330 IEntity parent = entity.GetRootParent();
331 if (parent != entity)
332 return parent;
333
334 // root element
335 if (self)
336 return entity;
337 else
338 return null;
339 }
340
341 //------------------------------------------------------------------------------------------------
345 static void SetHierarchyTransform(notnull IEntity entity, vector newTransform[4])
346 {
347 vector oldTransform[4];
348 entity.GetTransform(oldTransform);
349 entity.SetTransform(newTransform);
350
351 IEntity child = entity.GetChildren();
352 while (child)
353 {
354 SetHierarchyChildTransform(child, oldTransform, newTransform, true);
355 child = child.GetSibling();
356 }
357 }
358
359 //------------------------------------------------------------------------------------------------
365 // used by SetHierarchyTransform
366 protected static void SetHierarchyChildTransform(notnull IEntity entity, vector oldTransform[4], vector newTransform[4], bool recursive = true)
367 {
368 Physics entPhys = entity.GetPhysics();
369 if (entPhys)
370 {
371 if (entPhys.IsDynamic())
372 {
373 vector mat[4];
374 entity.GetTransform(mat);
375
376 vector diffMat[4];
377 Math3D.MatrixInvMultiply4(oldTransform, mat, diffMat);
378 Math3D.MatrixMultiply4(newTransform, diffMat, mat);
379
380 entity.SetTransform(mat);
381 }
382 }
383
384 IEntity child = entity.GetChildren();
385 while (child)
386 {
387 SetHierarchyChildTransform(child, oldTransform, newTransform, recursive);
388 child = child.GetSibling();
389 }
390 }
391
392 //------------------------------------------------------------------------------------------------
398 static bool GetRelativeLocalTransform(notnull IEntity owner, notnull IEntity member, out vector relativeTransform[4])
399 {
400 // Temporarily added because notnull seems to be ignored when using ScriptInvoker
401 if (!owner || !member)
402 return false;
403
404 // Use world transform if not members of same hierarchy
405 IEntity root = owner.GetRootParent();
406 if (root != member.GetRootParent())
407 {
408 vector ownerTransform[4];
409 owner.GetWorldTransform(ownerTransform);
410
411 vector memberTransform[4];
412 member.GetWorldTransform(memberTransform);
413
414 Math3D.MatrixInvMultiply4(ownerTransform, memberTransform, relativeTransform);
415
416 return true;
417 }
418
419 Math3D.MatrixIdentity4(relativeTransform);
420
421 // Simple check if member is parent of owner
422 IEntity parent = owner;
423 while (parent)
424 {
425 // Early return if succeded
426 if (parent == member)
427 return EntityUtils.GetAncestorToChildTransform(owner, member, relativeTransform);
428
429 parent = parent.GetParent();
430 }
431
432 // First get transform all the way up to root
433 vector ownerToRootTransform[4];
434 Math3D.MatrixIdentity4(ownerToRootTransform);
435 bool ownerToRoot = EntityUtils.GetAncestorToChildTransform(owner, root, ownerToRootTransform);
436
437 // Then go back to member
438 vector rootToMemberTransform[4];
439 Math3D.MatrixIdentity4(rootToMemberTransform);
440 bool rootToMember = EntityUtils.GetChildToAncestorTransform(member, root, rootToMemberTransform);
441
442 // Rewind the transform
443 Math3D.MatrixMultiply4(ownerToRootTransform, rootToMemberTransform, relativeTransform);
444
445 return ownerToRoot && rootToMember;
446 }
447
448 //------------------------------------------------------------------------------------------------
451 static RplComponent GetEntityRplComponent(notnull IEntity entity)
452 {
453 RplComponent rplComp;
454 BaseGameEntity gameEntity = BaseGameEntity.Cast(entity);
455 if (gameEntity)
456 rplComp = gameEntity.GetRplComponent();
457
458 if (!rplComp)
459 rplComp = RplComponent.Cast(entity.FindComponent(RplComponent));
460
461 return rplComp;
462 }
463
464 //------------------------------------------------------------------------------------------------
470 static void QuickSortEntitiesByDistanceToPoint(notnull inout array<IEntity> arr, vector pos, int low, int high)
471 {
472 if (low < high)
473 {
474 int pi = Partition(arr, pos, low, high);
475
476 QuickSortEntitiesByDistanceToPoint(arr, pos, low, pi - 1);
477 QuickSortEntitiesByDistanceToPoint(arr, pos, pi + 1, high);
478 }
479 }
480
481 //------------------------------------------------------------------------------------------------
488 protected static int Partition(notnull inout array<IEntity> arr, vector pos, int low, int high)
489 {
490 float pivot = vector.DistanceSq(arr[high].GetOrigin(), pos);
491 int i = (low - 1);
492
493 for (int j = low; j <= high - 1; j++)
494 {
495 if (vector.DistanceSq(arr[j].GetOrigin(), pos) <= pivot)
496 {
497 i++;
498 arr.SwapItems(i, j);
499 }
500 }
501
502 arr.SwapItems(i + 1, high);
503 return (i + 1);
504 }
505
506 //------------------------------------------------------------------------------------------------
508 {
509 if (ent)
510 {
511 RplComponent rplComp = GetEntityRplComponent(ent);
512 if (rplComp)
513 {
514 return rplComp.Id();
515 }
516 }
517 return RplId.Invalid();
518 }
519
520 //------------------------------------------------------------------------------------------------
522 {
523 RplComponent rplComp = RplComponent.Cast(Replication.FindItem(id));
524 if (!rplComp)
525 return null;
526
527 return rplComp.GetEntity();
528 }
529}
530
531class SCR_EntityHelperT<Class T>
532{
533 //------------------------------------------------------------------------------------------------
537 static T GetEntityInHierarchy(notnull IEntity parent)
538 {
539 IEntity child = parent.GetChildren();
540 while (child)
541 {
542 if (T.Cast(child))
543 return T.Cast(child);
544
545 child = child.GetSibling();
546 }
547
548 return null;
549 }
550}
551
554{
555 ENTITY = 1 << 0,
556 SLOTS = 1 << 1,
557 CHILDREN = 1 << 2,
558 PARENT = 1 << 3,
559 PARENT_SLOTS = 1 << 4,
560 ROOT_PARENT = 1 << 5,
562 SIBLINGS = 1 << 7,
563}
vector GetOrigin()
SCR_DestructionDamageManagerComponent destructible
SCR_EComponentFinderQueryFlags
Used for component finding to know where it can search to get the given component.
@ ROOT_PARENT
Find on Root parent of entity.
@ PARENT
Find on parent of entity.
@ SIBLINGS
Find on Siblings in hierarchy.
@ SLOTS
Find in SlotManagerComponent.
@ ROOT_PARENT_SLOTS
Find in SlotManagerComponent of root parent.
@ CHILDREN
Find on children of entity.
@ PARENT_SLOTS
Find in SlotManagerComponent of parent.
class SCR_EntityHelper GetEntityInHierarchy(notnull IEntity parent)
class SCR_MapHelperT< Class T, Class U > T
enum EVehicleType IEntity
Super root of all classes in Enforce script.
Definition Types.c:35
Adds ability to attach an object to a slot.
proto external Managed FindComponent(typename typeName)
proto external IEntity GetChildren()
proto external IEntity GetParent()
proto external IEntity GetSibling()
proto external IEntity GetRootParent()
Main replication API.
Definition Replication.c:14
Replication item identifier.
Definition RplId.c:14
static int Partition(notnull inout array< IEntity > arr, vector pos, int low, int high)
static void SetHierarchyChildTransform(notnull IEntity entity, vector oldTransform[4], vector newTransform[4], bool recursive=true)
static IEntity RplIdToEntity(RplId id)
static RplId EntityToRplId(IEntity ent)
static void QuickSortEntitiesByDistanceToPoint(notnull inout array< IEntity > arr, vector pos, int low, int high)
static void SetHierarchyTransform(notnull IEntity entity, vector newTransform[4])
static bool OnlyStaticCallback(notnull IEntity entity)
static bool GetRelativeLocalTransform(notnull IEntity owner, notnull IEntity member, out vector relativeTransform[4])
static IEntity GetMainParent(IEntity entity, bool self=false)
static RplComponent GetEntityRplComponent(notnull IEntity entity)
EPhysicsLayerPresets
Enum is filled by C++ by data in project config PhysicsSettings.LayerPresets.
Definition gameLib.c:19
TraceFlags
Definition TraceFlags.c:13