Dayz Explorer 1.28.160049
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
17 private ref array<EntityAI> m_VicinityItems = new array<EntityAI>();
18 private ref array<CargoBase> m_VicinityCargos = new array<CargoBase>();
19 private float m_RefreshCounter;
20 private static ref VicinityItemManager s_Instance;
21
22 static VicinityItemManager GetInstance ()
23 {
24 if (!s_Instance)
25 s_Instance = new VicinityItemManager();
26
27 return s_Instance;
28 }
29
30 void Init()
31 {
32 }
33
34 array<EntityAI> GetVicinityItems()
35 {
36 return m_VicinityItems;
37 }
38
39 void AddVicinityItems(Object object)
40 {
41 EntityAI entity = EntityAI.Cast(object);
42 if (!entity)
43 {
44 return;
45 }
46
47 if (m_VicinityItems.Find(entity) != INDEX_NOT_FOUND)
48 {
49 return;
50 }
51
52 if (GameInventory.CheckManipulatedObjectsDistances(entity, GetGame().GetPlayer(), VICINITY_CONE_REACH_DISTANCE + 1.0) == false)
53 {
54 if (!FreeDebugCamera.GetInstance() || FreeDebugCamera.GetInstance().IsActive() == false)
55 {
56 return;
57 }
58 }
59
60 m_VicinityItems.Insert(entity);
61 }
62
63 array<CargoBase> GetVicinityCargos()
64 {
65 return m_VicinityCargos;
66 }
67
68 void AddVicinityCargos(CargoBase object)
69 {
70 if (m_VicinityCargos.Find(object) == INDEX_NOT_FOUND)
71 {
72 m_VicinityCargos.Insert(object);
73 }
74 }
75
76 void ResetRefreshCounter()
77 {
78 m_RefreshCounter = 0;
79 }
80
81 void Update(float delta_time)
82 {
83 m_RefreshCounter += delta_time;
84
85 if (m_RefreshCounter >= UPDATE_FREQUENCY)
86 {
87 RefreshVicinityItems();
88 m_RefreshCounter = 0;
89 }
90 }
91
92 bool ExcludeFromContainer_Phase1(Object actor_in_radius)
93 {
94 EntityAI entity;
95 if (!Class.CastTo(entity, actor_in_radius))
96 return true;
97
98 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
99 if (entity == player)
100 return true;
101 if (entity.IsParticle())
102 return true;
103 if (entity.IsScriptedLight())
104 return true;
105 if (entity.IsBeingPlaced())
106 return true;
107 if (entity.IsHologram())
108 return true;
109 if (entity.IsMan() || entity.IsZombie() || entity.IsZombieMilitary())
110 {
111 //visibility cone check
112 vector entityPosition = entity.GetPosition();
113
114 if (entity && entity.IsMan())
115 {
116 PlayerBase vicinityPlayer = PlayerBase.Cast(entity);
117 if (vicinityPlayer)
118 {
119 entityPosition = vicinityPlayer.GetBonePositionWS(vicinityPlayer.GetBoneIndexByName("spine3"));
120 }
121 }
122 else if (entity && (entity.IsZombie() || entity.IsZombieMilitary()))
123 {
124 ZombieBase zombie = ZombieBase.Cast(entity);
125 if (zombie)
126 {
127 entityPosition = zombie.GetBonePositionWS(zombie.GetBoneIndexByName("spine3"));
128 }
129 }
130
132 if (FreeDebugCamera.GetInstance() && FreeDebugCamera.GetInstance().IsActive())
133 {
134 return false;
135 }
136
137 vector entityDirection = player.GetPosition() - entityPosition;
138 entityDirection.Normalize();
139 entityDirection[1] = 0; //ignore height
140
141 vector playerDirection = MiscGameplayFunctions.GetHeadingVector(player);
142 playerDirection.Normalize();
143 playerDirection[1] = 0; //ignore height
144
145 float dotRadians = vector.Dot(playerDirection, entityDirection);
146 if (dotRadians > -0.5)
147 return true;
148 }
149
150 return false;
151 }
152
153 bool ExcludeFromContainer_Phase2(Object object_in_radius)
154 {
155 EntityAI entity;
156
157 if (!Class.CastTo(entity, object_in_radius))
158 return true;
159 if (entity == PlayerBase.Cast(GetGame().GetPlayer()))
160 return true;
161 if (entity.IsParticle())
162 return true;
163 if (entity.IsScriptedLight())
164 return true;
165 if (entity.IsBeingPlaced())
166 return true;
167 if (entity.IsHologram())
168 return true;
169
170 ItemBase item;
171 if (!Class.CastTo(item, object_in_radius))
172 return true;
173
174 return false;
175 }
176
177 bool ExcludeFromContainer_Phase3(Object object_in_cone)
178 {
179 EntityAI entity;
180 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
181
182 //Print("---object in cone: " + object_in_cone);
183 if (!Class.CastTo(entity, object_in_cone))
184 return true;
185 if (entity == player)
186 return true;
187 if (entity.IsParticle())
188 return true;
189 if (entity.IsScriptedLight())
190 return true;
191 if (entity.IsBeingPlaced())
192 return true;
193 if (entity.IsHologram())
194 return true;
195
196 ItemBase item;
197 if (!Class.CastTo(item, object_in_cone) && !object_in_cone.IsTransport() && !PASBroadcaster.Cast(object_in_cone))
198 return true;
199
200 return false;
201 }
202
203 bool CanIgnoreDistanceCheck(EntityAI entity_ai)
204 {
205 return MiscGameplayFunctions.CanIgnoreDistanceCheck(entity_ai);
206 }
207
208 //per frame call
209 void RefreshVicinityItems()
210 {
211 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
212
213 array<Object> objectsInVicinity = new array<Object>();
214 array<CargoBase> proxyCargos = new array<CargoBase>();
215 array<Object> filteredObjects = new array<Object>();
216 array<Object> allFoundObjects = new array<Object>();
217 vector playerPosition = player.GetPosition();
218 vector playerHeadPositionFixed = playerPosition;
219 playerHeadPositionFixed[1] = playerHeadPositionFixed[1] + GetFixedHeadHeightAdjustment(player);
220 vector headingDirection = MiscGameplayFunctions.GetHeadingVector(player);
221
223 bool cameraActive = FreeDebugCamera.GetInstance() && FreeDebugCamera.GetInstance().IsActive();
224 if (cameraActive)
225 {
226 playerPosition = FreeDebugCamera.GetInstance().GetPosition();
227 playerHeadPositionFixed = playerPosition;
228
229 float headingAngle = FreeDebugCamera.GetInstance().GetOrientation()[0] * Math.DEG2RAD;
230
231 headingDirection[0] = Math.Cos(headingAngle);
232 headingDirection[1] = 0;
233 headingDirection[2] = Math.Sin(headingAngle);
234 headingDirection.Normalize();
235 }
236
237 if (m_VicinityItems)
238 m_VicinityItems.Clear();
239
240 if (m_VicinityCargos)
241 m_VicinityCargos.Clear();
242
243 //1. GetAll actors in VICINITY_ACTOR_DISTANCE
244 //DebugActorsSphereDraw(VICINITY_ACTOR_DISTANCE);
245 GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_ACTOR_DISTANCE, objectsInVicinity, proxyCargos);
246
247 // no filtering for cargo (initial implementation)
248 foreach (CargoBase cargoObject : proxyCargos)
249 AddVicinityCargos(cargoObject);
250
251 //filter unnecessary and duplicate objects beforehand
252 foreach (Object actorInRadius : objectsInVicinity)
253 {
254 if (allFoundObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
255 allFoundObjects.Insert(actorInRadius);
256
257 if (ExcludeFromContainer_Phase1(actorInRadius))
258 continue;
259
260 if (filteredObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
261 filteredObjects.Insert(actorInRadius);
262 }
263
264 if (objectsInVicinity)
265 objectsInVicinity.Clear();
266
267 //2. GetAll Objects in VICINITY_DISTANCE
268 GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_DISTANCE, objectsInVicinity, proxyCargos);
269 //DebugObjectsSphereDraw(VICINITY_DISTANCE);
270
271 //filter unnecessary and duplicate objects beforehand
272 foreach (Object objectInRadius : objectsInVicinity)
273 {
274 if (allFoundObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
275 allFoundObjects.Insert(objectInRadius);
276
277 if (ExcludeFromContainer_Phase2(objectInRadius))
278 continue;
279
280 if (filteredObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
281 filteredObjects.Insert(objectInRadius);
282 }
283
284 if (objectsInVicinity)
285 objectsInVicinity.Clear();
286
287 //3. Add objects from GetEntitiesInCone
288 DayZPlayerUtils.GetEntitiesInCone(playerPosition, headingDirection, VICINITY_CONE_ANGLE, VICINITY_CONE_REACH_DISTANCE, CONE_HEIGHT_MIN, CONE_HEIGHT_MAX, objectsInVicinity);
289 //DebugConeDraw(playerPosition, VICINITY_CONE_ANGLE);
290
291 RaycastRVParams rayInput;
293 //filter unnecessary and duplicate objects beforehand
294 foreach (Object objectInCone : objectsInVicinity)
295 {
296 if (allFoundObjects.Find(objectInCone) == INDEX_NOT_FOUND)
297 allFoundObjects.Insert(objectInCone);
298
299 if (ExcludeFromContainer_Phase3(objectInCone))
300 continue;
301
302 if (filteredObjects.Find(objectInCone) == INDEX_NOT_FOUND)
303 {
304 rayInput = new RaycastRVParams(playerHeadPositionFixed, objectInCone.GetPosition());
305 rayInput.flags = CollisionFlags.ALLOBJECTS;
306 rayInput.type = ObjIntersectView;
307 rayInput.radius = 0.1;
308 DayZPhysics.RaycastRVProxy(rayInput, raycastResults, {player});
309 //Debug.DrawLine(playerHeadPositionFixed,objectInCone.GetPosition(),COLOR_WHITE,ShapeFlags.ONCE);
310
311 foreach (RaycastRVResult result : raycastResults)
312 {
313 if (vector.DistanceSq(result.pos, playerPosition) > VICINITY_CONE_REACH_DISTANCE * VICINITY_CONE_REACH_DISTANCE)
314 continue;
315
316 if (result.hierLevel > 0)
317 {
318 if (result.parent.CanProxyObstruct())
319 break;
320
321 if (result.parent == objectInCone)
322 {
323 filteredObjects.Insert(objectInCone);
324 break;
325 }
326 }
327 else
328 {
329 if (result.obj == objectInCone)
330 {
331 filteredObjects.Insert(objectInCone);
332 break;
333 }
334 }
335 }
336 }
337 }
338
339 //4. Add large objects - particularly buildings and BaseBuildingBase
341 vector boxEdgeLength = {
342 VICINITY_LARGE_ACTOR_DISTANCE,
343 VICINITY_LARGE_ACTOR_DISTANCE,
344 VICINITY_LARGE_ACTOR_DISTANCE
345 };
346
347 params.SetParams(playerPosition, headingDirection.VectorToAngles(), boxEdgeLength * 2, ObjIntersect.View, ObjIntersect.Fire, true);
349 if (GetGame().IsBoxCollidingGeometryProxy(params, {player}, results))
350 {
351 foreach (BoxCollidingResult bResult : results)
352 {
353 if (bResult.obj && (bResult.obj.CanObstruct() || bResult.obj.CanProxyObstruct()))
354 {
355 if (allFoundObjects.Find(bResult.obj) == INDEX_NOT_FOUND)
356 allFoundObjects.Insert(bResult.obj);
357 }
358
359 if (bResult.parent && (bResult.parent.CanObstruct() || bResult.parent.CanProxyObstruct()))
360 {
361 if (allFoundObjects.Find(bResult.parent) == INDEX_NOT_FOUND)
362 allFoundObjects.Insert(bResult.parent);
363 }
364 }
365 }
366
367 //5. Filter filtered objects with RayCast from the player ( head bone )
368 array<Object> obstructingObjects = new array<Object>();
369 MiscGameplayFunctions.FilterObstructingObjects(allFoundObjects, obstructingObjects);
370
372 if (obstructingObjects.Count() > 0 && !cameraActive)
373 {
374 //obstructingObjects.Debug();
375 if (filteredObjects.Count() > 10)
376 {
377 array<Object> filteredObjectsGrouped = new array<Object>();
378 MiscGameplayFunctions.FilterObstructedObjectsByGrouping(playerHeadPositionFixed, VICINITY_CONE_DISTANCE, 0.3, filteredObjects, obstructingObjects, filteredObjectsGrouped, true, true, VICINITY_CONE_REACH_DISTANCE);
379
380 foreach (Object object: filteredObjectsGrouped)
381 AddVicinityItems(object);
382 }
383 else
384 {
385 foreach (Object filteredObjectClose: filteredObjects)
386 {
387 EntityAI entity;
388 Class.CastTo(entity, filteredObjectClose);
389
390 //distance check
391 if (vector.DistanceSq(playerPosition, entity.GetPosition()) > VICINITY_CONE_REACH_DISTANCE * VICINITY_CONE_REACH_DISTANCE)
392 {
393 if (!CanIgnoreDistanceCheck(entity))
394 {
395 continue;
396 }
397 }
398
399 if (!IsObstructed(filteredObjectClose))
400 {
401 AddVicinityItems(filteredObjectClose);
402 }
403 }
404 }
405 }
406 else
407 {
408 foreach (Object filteredObject: filteredObjects)
409 AddVicinityItems(filteredObject);
410 }
411 }
412
414 {
415 if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_ERECT|DayZPlayerConstants.STANCEMASK_RAISEDERECT))
416 return PlayerConstants.HEAD_HEIGHT_ERECT;
417 if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_CROUCH|DayZPlayerConstants.STANCEMASK_RAISEDCROUCH))
418 return PlayerConstants.HEAD_HEIGHT_CROUCH;
419 if (player.IsPlayerInStance(DayZPlayerConstants.STANCEMASK_PRONE|DayZPlayerConstants.STANCEMASK_RAISEDPRONE))
420 return PlayerConstants.HEAD_HEIGHT_PRONE;
421
422 return PlayerConstants.HEAD_HEIGHT_ERECT;
423 }
424
425 bool IsObstructed(Object filtered_object)
426 {
427 return MiscGameplayFunctions.IsObjectObstructed(filtered_object);
428 }
429
430#ifdef DIAG_DEVELOPER
431 //Debug functions
432
433 ref array<Shape> rayShapes = new array<Shape>();
434
435 private void DebugActorsSphereDraw(float radius)
436 {
437 CleanupDebugShapes(rayShapes);
438
439 rayShapes.Insert(Debug.DrawSphere( GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
440 }
441
442 private void DebugObjectsSphereDraw(float radius)
443 {
444 rayShapes.Insert(Debug.DrawSphere(GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
445 }
446
447 private void DebugRaycastDraw(vector start, vector end)
448 {
449 rayShapes.Insert(Debug.DrawArrow(start, end, 0.5, COLOR_YELLOW));
450 }
451
452 private void DebugConeDraw(vector start, float cone_angle)
453 {
454 vector endL, endR;
455 float playerAngle;
456 float xL,xR,zL,zR;
457
458 playerAngle = MiscGameplayFunctions.GetHeadingAngle(PlayerBase.Cast(GetGame().GetPlayer()));
459
460 endL = start;
461 endR = start;
462 xL = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // x
463 zL = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // z
464 xR = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // x
465 zR = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // z
466 endL[0] = endL[0] + xL;
467 endL[2] = endL[2] + zL;
468 endR[0] = endR[0] + xR;
469 endR[2] = endR[2] + zR;
470
471 rayShapes.Insert(Debug.DrawLine(start, endL, COLOR_GREEN));
472 rayShapes.Insert(Debug.DrawLine(start, endR, COLOR_GREEN)) ;
473 rayShapes.Insert(Debug.DrawLine(endL, endR, COLOR_GREEN));
474 }
475
476 private void CleanupDebugShapes(array<Shape> shapesArr)
477 {
478 foreach (Shape shape : shapesArr)
479 Debug.RemoveShape(shape);
480
481 shapesArr.Clear();
482 }
483#endif
484}
Class that holds parameters to feed into CGame.IsBoxCollidingGeometryProxy.
represents base for cargo storage for entities
Definition cargo.c:7
Super root of all classes in Enforce script.
Definition enscript.c:11
Definition debug.c:2
script counterpart to engine's class Inventory
Definition inventory.c:79
static proto native bool CheckManipulatedObjectsDistances(notnull EntityAI e0, notnull EntityAI e1, float radius)
Definition enmath.c:7
bool IsObstructed(Object filtered_object)
float GetFixedHeadHeightAdjustment(PlayerBase player)
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
DayZPlayerConstants
defined in C++
Definition dayzplayer.c:602
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
CollisionFlags
Definition endebug.c:141
ShapeFlags
Definition endebug.c:126
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
class JsonUndergroundAreaTriggerData GetPosition
PlayerBase GetPlayer()