DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
VicinityItemManager.c
Go to the documentation of this file.
2{
3 private const float UPDATE_FREQUENCY = 0.25;
4 private const float VICINITY_DISTANCE = 0.5;
5 private const float VICINITY_ACTOR_DISTANCE = 2.0;
6 private const float VICINITY_LARGE_ACTOR_DISTANCE = 3.0;
7 private const float VICINITY_CONE_DISTANCE = 2.0;
8 private const float VICINITY_CONE_REACH_DISTANCE = 2.0;
9 private const float VICINITY_CONE_ANGLE = 30;
10 private const float VICINITY_CONE_RADIANS = 0.5;
11 private const string CE_CENTER = "ce_center";
12 private const float HEIGHT_OFFSET = 0.2;
13 private const int OBJECT_OBSTRUCTION_WEIGHT = 10000; //in grams
14 private const float CONE_HEIGHT_MIN = -0.5;
15 private const float CONE_HEIGHT_MAX = 3.0;
16
19 private float m_RefreshCounter;
20 private static ref VicinityItemManager s_Instance;
21
23 {
24 if (!s_Instance)
26
27 return s_Instance;
28 }
29
30 void Init()
31 {
32 }
33
35 {
36 return m_VicinityItems;
37 }
38
40 {
41 EntityAI entity = EntityAI.Cast(object);
42 if (entity)
43 {
45 {
46 m_VicinityItems.Insert(entity);
47 }
48 }
49 }
50
52 {
53 return m_VicinityCargos;
54 }
55
57 {
58 if (m_VicinityCargos.Find(object) == INDEX_NOT_FOUND)
59 {
60 m_VicinityCargos.Insert(object);
61 }
62 }
63
65 {
67 }
68
69 void Update(float delta_time)
70 {
71 m_RefreshCounter += delta_time;
72
74 {
77 }
78 }
79
80 bool ExcludeFromContainer_Phase1(Object actor_in_radius)
81 {
82 EntityAI entity;
83 if (!Class.CastTo(entity, actor_in_radius))
84 return true;
85
86 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
87 if (entity == player)
88 return true;
89 if (entity.IsParticle())
90 return true;
91 if (entity.IsScriptedLight())
92 return true;
93 if (entity.IsBeingPlaced())
94 return true;
95 if (entity.IsHologram())
96 return true;
97 if (entity.IsMan() || entity.IsZombie() || entity.IsZombieMilitary())
98 {
99 //visibility cone check
100 vector entityPosition = entity.GetPosition();
101
102 if (entity && entity.IsMan())
103 {
104 PlayerBase vicinityPlayer = PlayerBase.Cast(entity);
105 if (vicinityPlayer)
106 {
107 entityPosition = vicinityPlayer.GetBonePositionWS(vicinityPlayer.GetBoneIndexByName("spine3"));
108 }
109 }
110 else if (entity && (entity.IsZombie() || entity.IsZombieMilitary()))
111 {
112 ZombieBase zombie = ZombieBase.Cast(entity);
113 if (zombie)
114 {
115 entityPosition = zombie.GetBonePositionWS(zombie.GetBoneIndexByName("spine3"));
116 }
117 }
118
119 vector entityDirection = player.GetPosition() - entityPosition;
120 entityDirection.Normalize();
121 entityDirection[1] = 0; //ignore height
122
123 vector playerDirection = MiscGameplayFunctions.GetHeadingVector(player);
124 playerDirection.Normalize();
125 playerDirection[1] = 0; //ignore height
126
127 float dotRadians = vector.Dot(playerDirection, entityDirection);
128 if (dotRadians > -0.5)
129 return true;
130 }
131
132 return false;
133 }
134
135 bool ExcludeFromContainer_Phase2(Object object_in_radius)
136 {
137 EntityAI entity;
138
139 if (!Class.CastTo(entity, object_in_radius))
140 return true;
141 if (entity == PlayerBase.Cast(GetGame().GetPlayer()))
142 return true;
143 if (entity.IsParticle())
144 return true;
145 if (entity.IsScriptedLight())
146 return true;
147 if (entity.IsBeingPlaced())
148 return true;
149 if (entity.IsHologram())
150 return true;
151
152 ItemBase item;
153 if (!Class.CastTo(item, object_in_radius))
154 return true;
155 if (!item.IsTakeable())
156 return true;
157
158 return false;
159 }
160
162 {
163 EntityAI entity;
164 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
165
166 //Print("---object in cone: " + object_in_cone);
167 if (!Class.CastTo(entity, object_in_cone))
168 return true;
169 if (entity == player)
170 return true;
171 if (entity.IsParticle())
172 return true;
173 if (entity.IsScriptedLight())
174 return true;
175 if (entity.IsBeingPlaced())
176 return true;
177 if (entity.IsHologram())
178 return true;
179
180 ItemBase item;
181 if (!Class.CastTo(item, object_in_cone) && !object_in_cone.IsTransport() && !PASBroadcaster.Cast(object_in_cone))
182 return true;
183 if (item && !item.IsTakeable())
184 return true;
185
186 return false;
187 }
188
190 {
191 return MiscGameplayFunctions.CanIgnoreDistanceCheck(entity_ai);
192 }
193
194 //per frame call
196 {
197 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
198
199 array<Object> objectsInVicinity = new array<Object>();
200 array<CargoBase> proxyCargos = new array<CargoBase>();
201 array<Object> filteredObjects = new array<Object>();
202 array<Object> allFoundObjects = new array<Object>();
203 vector playerPosition = player.GetPosition();
204 vector headingDirection = MiscGameplayFunctions.GetHeadingVector(player);
205 vector playerHeadPos;
206 MiscGameplayFunctions.GetHeadBonePos(player, playerHeadPos);
207
208 if (m_VicinityItems)
209 m_VicinityItems.Clear();
210
212 m_VicinityCargos.Clear();
213
214 //1. GetAll actors in VICINITY_ACTOR_DISTANCE
215// DebugActorsSphereDraw( VICINITY_ACTOR_DISTANCE );
216 GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_ACTOR_DISTANCE, objectsInVicinity, proxyCargos);
217
218 // no filtering for cargo (initial implementation)
219 foreach (CargoBase cargoObject : proxyCargos)
220 AddVicinityCargos(cargoObject);
221
222 //filter unnecessary and duplicate objects beforehand
223 foreach (Object actorInRadius : objectsInVicinity)
224 {
225 if (allFoundObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
226 {
227 allFoundObjects.Insert(actorInRadius);
228 }
229
230 if (ExcludeFromContainer_Phase1(actorInRadius))
231 continue;
232
233 if (filteredObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
234 {
235 filteredObjects.Insert(actorInRadius);
236 }
237 }
238
239 if (objectsInVicinity)
240 {
241 objectsInVicinity.Clear();
242 }
243
244 //2. GetAll Objects in VICINITY_DISTANCE
245 GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_DISTANCE, objectsInVicinity, proxyCargos);
246// DebugObjectsSphereDraw( VICINITY_DISTANCE );
247
248 //filter unnecessary and duplicate objects beforehand
249 foreach (Object objectInRadius : objectsInVicinity)
250 {
251 if (allFoundObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
252 {
253 allFoundObjects.Insert(objectInRadius);
254 }
255
256 if (ExcludeFromContainer_Phase2(objectInRadius))
257 continue;
258
259 if (filteredObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
260 {
261 filteredObjects.Insert(objectInRadius);
262 }
263 }
264
265 if (objectsInVicinity)
266 {
267 objectsInVicinity.Clear();
268 }
269
270 //3. Add objects from GetEntitiesInCone
271 DayZPlayerUtils.GetEntitiesInCone( playerPosition, headingDirection, VICINITY_CONE_ANGLE, VICINITY_CONE_REACH_DISTANCE, CONE_HEIGHT_MIN, CONE_HEIGHT_MAX, objectsInVicinity);
272// DebugConeDraw( playerPosition, VICINITY_CONE_ANGLE );
273
274 RaycastRVParams rayInput;
276 //filter unnecessary and duplicate objects beforehand
277 foreach (Object objectInCone : objectsInVicinity)
278 {
279 if (allFoundObjects.Find(objectInCone) == INDEX_NOT_FOUND)
280 {
281 allFoundObjects.Insert(objectInCone);
282 }
283
284 if (ExcludeFromContainer_Phase3(objectInCone))
285 continue;
286
287 if (filteredObjects.Find(objectInCone) == INDEX_NOT_FOUND)
288 {
289 //Test distance to closest component first
290 rayInput = new RaycastRVParams(playerHeadPos, objectInCone.GetPosition(), player, 0.1);
291 DayZPhysics.RaycastRVProxy(rayInput,raycastResults);
292
293 foreach (RaycastRVResult result : raycastResults)
294 {
296 {
297 continue;
298 }
299
300 if (result.hierLevel > 0 && result.parent == objectInCone)
301 {
302 filteredObjects.Insert(objectInCone);
303 }
304 else if (result.hierLevel == 0 && result.obj == objectInCone)
305 {
306 filteredObjects.Insert(objectInCone);
307 }
308 }
309 }
310 }
311
312 //4. Add large objects - particularly buildings and BaseBuildingBase
314 vector boxEdgeLength = {
318 };
319
320 params.SetParams(playerPosition, headingDirection.VectorToAngles(), boxEdgeLength * 2, ObjIntersect.View, ObjIntersect.Fire, true);
322 if (GetGame().IsBoxCollidingGeometryProxy(params, {player}, results))
323 {
324 foreach (BoxCollidingResult bResult : results)
325 {
326 if (bResult.obj && (bResult.obj.CanObstruct() || bResult.obj.CanProxyObstruct()))
327 {
328 if (allFoundObjects.Find(bResult.obj) == INDEX_NOT_FOUND)
329 {
330 allFoundObjects.Insert(bResult.obj);
331 }
332 }
333
334 if (bResult.parent && (bResult.parent.CanObstruct() || bResult.parent.CanProxyObstruct()))
335 {
336 if (allFoundObjects.Find(bResult.parent) == INDEX_NOT_FOUND)
337 {
338 allFoundObjects.Insert(bResult.parent);
339 }
340 }
341 }
342 }
343
344 //5. Filter filtered objects with RayCast from the player ( head bone )
345 array<Object> obstructingObjects = new array<Object>();
346 MiscGameplayFunctions.FilterObstructingObjects(allFoundObjects, obstructingObjects);
347
348 if (obstructingObjects.Count() > 0)
349 {
350 if (filteredObjects.Count() > 10)
351 {
352 vector rayStart;
353 MiscGameplayFunctions.GetHeadBonePos(player, rayStart);
354
355 array<Object> filteredObjectsGrouped = new array<Object>();
356 MiscGameplayFunctions.FilterObstructedObjectsByGrouping(rayStart, VICINITY_CONE_DISTANCE, 0.3, filteredObjects, obstructingObjects, filteredObjectsGrouped, true, true, VICINITY_CONE_REACH_DISTANCE);
357
358 foreach (Object object: filteredObjectsGrouped)
359 AddVicinityItems(object);
360 }
361 else
362 {
363 foreach (Object filteredObjectClose: filteredObjects)
364 {
365 EntityAI entity;
366 Class.CastTo(entity, filteredObjectClose);
367
368 //distance check
369 if (vector.DistanceSq(playerPosition, entity.GetPosition()) > VICINITY_CONE_REACH_DISTANCE * VICINITY_CONE_REACH_DISTANCE)
370 {
371 if (!CanIgnoreDistanceCheck(entity))
372 {
373 continue;
374 }
375 }
376
377 if (!IsObstructed(filteredObjectClose))
378 {
379 AddVicinityItems(filteredObjectClose);
380 }
381 }
382 }
383 }
384 else
385 {
386 foreach (Object filteredObject: filteredObjects)
387 AddVicinityItems(filteredObject);
388 }
389 }
390
391 bool IsObstructed(Object filtered_object)
392 {
393 return MiscGameplayFunctions.IsObjectObstructed(filtered_object);
394 }
395
396#ifdef DIAG_DEVELOPER
397 //Debug functions
398
399 ref array<Shape> rayShapes = new array<Shape>();
400
401 private void DebugActorsSphereDraw(float radius)
402 {
403 CleanupDebugShapes(rayShapes);
404
405 rayShapes.Insert(Debug.DrawSphere( GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
406 }
407
408 private void DebugObjectsSphereDraw(float radius)
409 {
410 rayShapes.Insert(Debug.DrawSphere(GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
411 }
412
413 private void DebugRaycastDraw(vector start, vector end)
414 {
415 rayShapes.Insert(Debug.DrawArrow(start, end, 0.5, COLOR_YELLOW));
416 }
417
418 private void DebugConeDraw(vector start, float cone_angle)
419 {
420 vector endL, endR;
421 float playerAngle;
422 float xL,xR,zL,zR;
423
424 playerAngle = MiscGameplayFunctions.GetHeadingAngle(PlayerBase.Cast(GetGame().GetPlayer()));
425
426 endL = start;
427 endR = start;
428 xL = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // x
429 zL = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // z
430 xR = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // x
431 zR = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // z
432 endL[0] = endL[0] + xL;
433 endL[2] = endL[2] + zL;
434 endR[0] = endR[0] + xR;
435 endR[2] = endR[2] + zR;
436
437 rayShapes.Insert(Debug.DrawLine(start, endL, COLOR_GREEN));
438 rayShapes.Insert(Debug.DrawLine(start, endR, COLOR_GREEN)) ;
439 rayShapes.Insert(Debug.DrawLine(endL, endR, COLOR_GREEN));
440 }
441
442 private void CleanupDebugShapes(array<Shape> shapesArr)
443 {
444 foreach (Shape shape : shapesArr)
445 Debug.RemoveShape(shape);
446
447 shapesArr.Clear();
448 }
449#endif
450}
private void DayZPlayerUtils()
cannot be instantiated
PlayerBase GetPlayer()
class JsonUndergroundAreaTriggerData GetPosition
Class that holds parameters to feed into CGame.IsBoxCollidingGeometryProxy.
proto native void SetParams(vector center, vector orientation, vector edgeLength, ObjIntersect primaryType, ObjIntersect secondaryType, bool fullComponentInfo)
Set the parameters.
proto native void GetObjectsAtPosition3D(vector pos, float radius, out array< Object > objects, out array< CargoBase > proxyCargos)
Returns list of all objects in sphere "radius" around position "pos".
represents base for cargo storage for entities
Definition Cargo.c:7
Super root of all classes in Enforce script.
Definition EnScript.c:11
static proto bool RaycastRVProxy(notnull RaycastRVParams in, out notnull array< ref RaycastRVResult > results, array< Object > excluded=null)
Definition Debug.c:14
static Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, int flags=0)
Definition Debug.c:383
static Shape DrawLine(vector from, vector to, int color=0xFFFFFFFF, int flags=0)
Definition Debug.c:361
static Shape DrawSphere(vector pos, float size=1, int color=0x1fff7f7f, ShapeFlags flags=ShapeFlags.TRANSP|ShapeFlags.NOOUTLINE)
Definition Debug.c:306
override bool IsMan()
Definition Man.c:33
script counterpart to engine's class Inventory
Definition Inventory.c:77
static proto native bool CheckManipulatedObjectsDistances(notnull EntityAI e0, notnull EntityAI e1, float radius)
override bool IsTakeable()
Definition EnMath.c:7
private const float CONE_HEIGHT_MIN
private const int OBJECT_OBSTRUCTION_WEIGHT
bool IsObstructed(Object filtered_object)
private const float UPDATE_FREQUENCY
private const float HEIGHT_OFFSET
bool ExcludeFromContainer_Phase3(Object object_in_cone)
private const float VICINITY_CONE_REACH_DISTANCE
array< EntityAI > GetVicinityItems()
bool ExcludeFromContainer_Phase2(Object object_in_radius)
private ref array< CargoBase > m_VicinityCargos
static VicinityItemManager GetInstance()
private const float CONE_HEIGHT_MAX
void AddVicinityItems(Object object)
private const float VICINITY_CONE_DISTANCE
void AddVicinityCargos(CargoBase object)
private const string CE_CENTER
private const float VICINITY_LARGE_ACTOR_DISTANCE
bool ExcludeFromContainer_Phase1(Object actor_in_radius)
private const float VICINITY_CONE_ANGLE
void Update(float delta_time)
private const float VICINITY_DISTANCE
static private ref VicinityItemManager s_Instance
array< CargoBase > GetVicinityCargos()
private const float VICINITY_ACTOR_DISTANCE
private float m_RefreshCounter
private const float VICINITY_CONE_RADIANS
private ref array< EntityAI > m_VicinityItems
bool CanIgnoreDistanceCheck(EntityAI entity_ai)
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto float Normalize()
Normalizes vector. Returns length.
static proto native float DistanceSq(vector v1, vector v2)
Returns the square distance between tips of two 3D vectors.
proto vector VectorToAngles()
Converts vector to spherical coordinates with radius = 1.
static float Dot(vector v1, vector v2)
Returns Dot product of vector v1 and vector v2.
Definition EnConvert.c:271
const int INDEX_NOT_FOUND
Definition gameplay.c:13
proto native CGame GetGame()
const int COLOR_GREEN
Definition constants.c:65
const int COLOR_YELLOW
Definition constants.c:67
ShapeFlags
Definition EnDebug.c:126
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
static proto float Cos(float angle)
Returns cosinus of angle in radians.
static const float PI_HALF
Definition EnMath.c:14
static const float DEG2RAD
Definition EnMath.c:17
static proto float Sin(float angle)
Returns sinus of angle in radians.