Dayz Explorer  1.24.157551 (v105080)
Dayz Code Explorer by Zeroy
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  if (!item.IsTakeable())
174  return true;
175 
176  return false;
177  }
178 
179  bool ExcludeFromContainer_Phase3(Object object_in_cone)
180  {
181  EntityAI entity;
182  PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
183 
184  //Print("---object in cone: " + object_in_cone);
185  if (!Class.CastTo(entity, object_in_cone))
186  return true;
187  if (entity == player)
188  return true;
189  if (entity.IsParticle())
190  return true;
191  if (entity.IsScriptedLight())
192  return true;
193  if (entity.IsBeingPlaced())
194  return true;
195  if (entity.IsHologram())
196  return true;
197 
198  ItemBase item;
199  if (!Class.CastTo(item, object_in_cone) && !object_in_cone.IsTransport() && !PASBroadcaster.Cast(object_in_cone))
200  return true;
201  if (item && !item.IsTakeable())
202  return true;
203 
204  return false;
205  }
206 
207  bool CanIgnoreDistanceCheck(EntityAI entity_ai)
208  {
209  return MiscGameplayFunctions.CanIgnoreDistanceCheck(entity_ai);
210  }
211 
212  //per frame call
213  void RefreshVicinityItems()
214  {
215  PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
216 
217  array<Object> objectsInVicinity = new array<Object>();
218  array<CargoBase> proxyCargos = new array<CargoBase>();
219  array<Object> filteredObjects = new array<Object>();
220  array<Object> allFoundObjects = new array<Object>();
221  vector playerPosition = player.GetPosition();
222  vector playerHeadPositionFixed = playerPosition;
223  playerHeadPositionFixed[1] = playerPosition[1] + 1.6;
224  vector headingDirection = MiscGameplayFunctions.GetHeadingVector(player);
225 
227  bool cameraActive = FreeDebugCamera.GetInstance() && FreeDebugCamera.GetInstance().IsActive();
228  if (cameraActive)
229  {
230  playerPosition = FreeDebugCamera.GetInstance().GetPosition();
231  playerHeadPositionFixed = playerPosition;
232 
233  float headingAngle = FreeDebugCamera.GetInstance().GetOrientation()[0] * Math.DEG2RAD;
234 
235  headingDirection[0] = Math.Cos(headingAngle);
236  headingDirection[1] = 0;
237  headingDirection[2] = Math.Sin(headingAngle);
238  headingDirection.Normalize();
239  }
240 
241  if (m_VicinityItems)
242  m_VicinityItems.Clear();
243 
244  if (m_VicinityCargos)
245  m_VicinityCargos.Clear();
246 
247  //1. GetAll actors in VICINITY_ACTOR_DISTANCE
248  //DebugActorsSphereDraw(VICINITY_ACTOR_DISTANCE);
249  GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_ACTOR_DISTANCE, objectsInVicinity, proxyCargos);
250 
251  // no filtering for cargo (initial implementation)
252  foreach (CargoBase cargoObject : proxyCargos)
253  AddVicinityCargos(cargoObject);
254 
255  //filter unnecessary and duplicate objects beforehand
256  foreach (Object actorInRadius : objectsInVicinity)
257  {
258  if (allFoundObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
259  allFoundObjects.Insert(actorInRadius);
260 
261  if (ExcludeFromContainer_Phase1(actorInRadius))
262  continue;
263 
264  if (filteredObjects.Find(actorInRadius) == INDEX_NOT_FOUND)
265  filteredObjects.Insert(actorInRadius);
266  }
267 
268  if (objectsInVicinity)
269  objectsInVicinity.Clear();
270 
271  //2. GetAll Objects in VICINITY_DISTANCE
272  GetGame().GetObjectsAtPosition3D(playerPosition, VICINITY_DISTANCE, objectsInVicinity, proxyCargos);
273  //DebugObjectsSphereDraw(VICINITY_DISTANCE);
274 
275  //filter unnecessary and duplicate objects beforehand
276  foreach (Object objectInRadius : objectsInVicinity)
277  {
278  if (allFoundObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
279  allFoundObjects.Insert(objectInRadius);
280 
281  if (ExcludeFromContainer_Phase2(objectInRadius))
282  continue;
283 
284  if (filteredObjects.Find(objectInRadius) == INDEX_NOT_FOUND)
285  filteredObjects.Insert(objectInRadius);
286  }
287 
288  if (objectsInVicinity)
289  objectsInVicinity.Clear();
290 
291  //3. Add objects from GetEntitiesInCone
292  DayZPlayerUtils.GetEntitiesInCone(playerPosition, headingDirection, VICINITY_CONE_ANGLE, VICINITY_CONE_REACH_DISTANCE, CONE_HEIGHT_MIN, CONE_HEIGHT_MAX, objectsInVicinity);
293  //DebugConeDraw(playerPosition, VICINITY_CONE_ANGLE);
294 
295  RaycastRVParams rayInput;
297  //filter unnecessary and duplicate objects beforehand
298  foreach (Object objectInCone : objectsInVicinity)
299  {
300  if (allFoundObjects.Find(objectInCone) == INDEX_NOT_FOUND)
301  allFoundObjects.Insert(objectInCone);
302 
303  if (ExcludeFromContainer_Phase3(objectInCone))
304  continue;
305 
306  if (filteredObjects.Find(objectInCone) == INDEX_NOT_FOUND)
307  {
308  //Test distance to closest component first
309  rayInput = new RaycastRVParams(playerHeadPositionFixed, objectInCone.GetPosition());
310  rayInput.flags = CollisionFlags.NEARESTCONTACT;
311  rayInput.type = ObjIntersectView;
312  rayInput.radius = 0.1;
313  DayZPhysics.RaycastRVProxy(rayInput, raycastResults, {player});
314 
315  foreach (RaycastRVResult result : raycastResults)
316  {
317  if (vector.DistanceSq(result.pos, playerHeadPositionFixed) > VICINITY_CONE_REACH_DISTANCE * VICINITY_CONE_REACH_DISTANCE)
318  continue;
319 
320  if (result.hierLevel > 0 && result.parent == objectInCone)
321  filteredObjects.Insert(objectInCone);
322  else if (result.hierLevel == 0 && result.obj == objectInCone)
323  filteredObjects.Insert(objectInCone);
324  }
325  }
326  }
327 
328  //4. Add large objects - particularly buildings and BaseBuildingBase
329  BoxCollidingParams params = new BoxCollidingParams();
330  vector boxEdgeLength = {
331  VICINITY_LARGE_ACTOR_DISTANCE,
332  VICINITY_LARGE_ACTOR_DISTANCE,
333  VICINITY_LARGE_ACTOR_DISTANCE
334  };
335 
336  params.SetParams(playerPosition, headingDirection.VectorToAngles(), boxEdgeLength * 2, ObjIntersect.View, ObjIntersect.Fire, true);
338  if (GetGame().IsBoxCollidingGeometryProxy(params, {player}, results))
339  {
340  foreach (BoxCollidingResult bResult : results)
341  {
342  if (bResult.obj && (bResult.obj.CanObstruct() || bResult.obj.CanProxyObstruct()))
343  {
344  if (allFoundObjects.Find(bResult.obj) == INDEX_NOT_FOUND)
345  {
346  allFoundObjects.Insert(bResult.obj);
347  }
348  }
349 
350  if (bResult.parent && (bResult.parent.CanObstruct() || bResult.parent.CanProxyObstruct()))
351  {
352  if (allFoundObjects.Find(bResult.parent) == INDEX_NOT_FOUND)
353  {
354  allFoundObjects.Insert(bResult.parent);
355  }
356  }
357  }
358  }
359 
360  //5. Filter filtered objects with RayCast from the player ( head bone )
361  array<Object> obstructingObjects = new array<Object>();
362  MiscGameplayFunctions.FilterObstructingObjects(allFoundObjects, obstructingObjects);
363 
365  if (obstructingObjects.Count() > 0 && !cameraActive)
366  {
367  if (filteredObjects.Count() > 10)
368  {
369  vector rayStart;
370  MiscGameplayFunctions.GetHeadBonePos(player, rayStart);
371 
372  array<Object> filteredObjectsGrouped = new array<Object>();
373  MiscGameplayFunctions.FilterObstructedObjectsByGrouping(rayStart, VICINITY_CONE_DISTANCE, 0.3, filteredObjects, obstructingObjects, filteredObjectsGrouped, true, true, VICINITY_CONE_REACH_DISTANCE);
374 
375  foreach (Object object: filteredObjectsGrouped)
376  AddVicinityItems(object);
377  }
378  else
379  {
380  foreach (Object filteredObjectClose: filteredObjects)
381  {
382  EntityAI entity;
383  Class.CastTo(entity, filteredObjectClose);
384 
385  //distance check
386  if (vector.DistanceSq(playerPosition, entity.GetPosition()) > VICINITY_CONE_REACH_DISTANCE * VICINITY_CONE_REACH_DISTANCE)
387  {
388  if (!CanIgnoreDistanceCheck(entity))
389  {
390  continue;
391  }
392  }
393 
394  if (!IsObstructed(filteredObjectClose))
395  {
396  AddVicinityItems(filteredObjectClose);
397  }
398  }
399  }
400  }
401  else
402  {
403  foreach (Object filteredObject: filteredObjects)
404  AddVicinityItems(filteredObject);
405  }
406  }
407 
408  bool IsObstructed(Object filtered_object)
409  {
410  return MiscGameplayFunctions.IsObjectObstructed(filtered_object);
411  }
412 
413 #ifdef DIAG_DEVELOPER
414  //Debug functions
415 
416  ref array<Shape> rayShapes = new array<Shape>();
417 
418  private void DebugActorsSphereDraw(float radius)
419  {
420  CleanupDebugShapes(rayShapes);
421 
422  rayShapes.Insert(Debug.DrawSphere( GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
423  }
424 
425  private void DebugObjectsSphereDraw(float radius)
426  {
427  rayShapes.Insert(Debug.DrawSphere(GetGame().GetPlayer().GetPosition(), radius, COLOR_GREEN, ShapeFlags.TRANSP|ShapeFlags.WIREFRAME));
428  }
429 
430  private void DebugRaycastDraw(vector start, vector end)
431  {
432  rayShapes.Insert(Debug.DrawArrow(start, end, 0.5, COLOR_YELLOW));
433  }
434 
435  private void DebugConeDraw(vector start, float cone_angle)
436  {
437  vector endL, endR;
438  float playerAngle;
439  float xL,xR,zL,zR;
440 
441  playerAngle = MiscGameplayFunctions.GetHeadingAngle(PlayerBase.Cast(GetGame().GetPlayer()));
442 
443  endL = start;
444  endR = start;
445  xL = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // x
446  zL = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF + cone_angle * Math.DEG2RAD ); // z
447  xR = VICINITY_CONE_REACH_DISTANCE * Math.Cos( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // x
448  zR = VICINITY_CONE_REACH_DISTANCE * Math.Sin( playerAngle + Math.PI_HALF - cone_angle * Math.DEG2RAD ); // z
449  endL[0] = endL[0] + xL;
450  endL[2] = endL[2] + zL;
451  endR[0] = endR[0] + xR;
452  endR[2] = endR[2] + zR;
453 
454  rayShapes.Insert(Debug.DrawLine(start, endL, COLOR_GREEN));
455  rayShapes.Insert(Debug.DrawLine(start, endR, COLOR_GREEN)) ;
456  rayShapes.Insert(Debug.DrawLine(endL, endR, COLOR_GREEN));
457  }
458 
459  private void CleanupDebugShapes(array<Shape> shapesArr)
460  {
461  foreach (Shape shape : shapesArr)
462  Debug.RemoveShape(shape);
463 
464  shapesArr.Clear();
465  }
466 #endif
467 }
ItemBase
Definition: inventoryitem.c:730
GetGame
proto native CGame GetGame()
INDEX_NOT_FOUND
const int INDEX_NOT_FOUND
Definition: gameplay.c:13
DayZPlayerUtils
private void DayZPlayerUtils()
cannot be instantiated
Definition: dayzplayerutils.c:461
COLOR_YELLOW
const int COLOR_YELLOW
Definition: constants.c:67
RaycastRVResult
Definition: dayzphysics.c:98
CollisionFlags
CollisionFlags
Definition: endebug.c:140
GetPosition
class JsonUndergroundAreaTriggerData GetPosition
Definition: undergroundarealoader.c:9
PlayerBase
Definition: playerbaseclient.c:1
RaycastRVParams
Definition: dayzphysics.c:49
VicinityItemManager
Definition: vicinityitemmanager.c:1
vector
Definition: enconvert.c:105
CargoBase
represents base for cargo storage for entities
Definition: cargo.c:6
ShapeFlags
ShapeFlags
Definition: endebug.c:125
Object
Definition: objecttyped.c:1
COLOR_GREEN
const int COLOR_GREEN
Definition: constants.c:65
array< EntityAI >
BoxCollidingParams
Class that holds parameters to feed into CGame.IsBoxCollidingGeometryProxy.
Definition: isboxcollidinggeometryproxyclasses.c:2
GetPlayer
protected void GetPlayer()
Definition: crosshairselector.c:127
Debug
Definition: debug.c:13
DayZPhysics
Definition: dayzphysics.c:123
Math
Definition: enmath.c:6
Class
Super root of all classes in Enforce script.
Definition: enscript.c:10
PASBroadcaster
Definition: land_radio_panelpas.c:1
ZombieBase
Definition: zombiefemalebase.c:1
EntityAI
Definition: building.c:5
Shape
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
GameInventory
script counterpart to engine's class Inventory
Definition: inventory.c:78