Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_ObstacleDetector.c
Go to the documentation of this file.
1 #ifdef WORKBENCH
2 
7 class SCR_ObstacleDetector
8 {
9  protected bool m_bAvoidObjects;
10  protected float m_fAvoidObjectsDetectionRadius;
11  protected float m_fAvoidObjectsDetectionHeight;
12  protected bool m_bAvoidRoads;
13  protected bool m_bAvoidRivers;
14  protected bool m_bAvoidPowerLines;
15  protected bool m_bAvoidTracks;
16  protected bool m_bAvoidForests;
17  protected bool m_bAvoidLakes;
18  protected bool m_bAvoidLand;
19  protected bool m_bAvoidOcean;
20  protected float m_fAvoidLandOceanOffset;
21  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoRoads;
22  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoRivers;
23  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoPowerLines;
24  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoTracks;
25  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoLakes;
26  protected ref array<ref SCR_ObstacleDetectorSplineInfo> m_aAvoidInfoForests;
27 
28  protected float m_fOceanLevel;
29  protected ref TraceSphere m_AvoidObjectTraceSphere;
30 
31  protected WorldEditorAPI m_WorldEditorAPI;
32 
33  //------------------------------------------------------------------------------------------------
36  bool IsValid()
37  {
38  return m_WorldEditorAPI != null;
39  }
40 
41  //------------------------------------------------------------------------------------------------
42  void SetAvoidObjects(bool avoidObjects)
43  {
44  m_bAvoidObjects = avoidObjects;
45  }
46 
47  //------------------------------------------------------------------------------------------------
49  void SetAvoidObjectsDetectionRadius(float radius)
50  {
51  if (radius < 0)
52  radius = 0;
53 
54  m_fAvoidObjectsDetectionRadius = radius;
55  if (m_AvoidObjectTraceSphere)
56  m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
57  }
58 
59  //------------------------------------------------------------------------------------------------
60  void SetAvoidObjectsDetectionHeight(float height)
61  {
62  m_fAvoidObjectsDetectionHeight = height;
63  if (m_AvoidObjectTraceSphere)
64  m_AvoidObjectTraceSphere.End[1] = m_AvoidObjectTraceSphere.Start[1] + m_fAvoidObjectsDetectionHeight;
65  }
66 
67  //------------------------------------------------------------------------------------------------
68  void SetAvoidRoads(bool avoidRoads)
69  {
70  m_bAvoidRoads = avoidRoads;
71  }
72 
73  //------------------------------------------------------------------------------------------------
74  void SetAvoidRivers(bool avoidRivers)
75  {
76  m_bAvoidRivers = avoidRivers;
77  }
78 
79  //------------------------------------------------------------------------------------------------
80  void SetAvoidPowerLines(bool avoidPowerLines)
81  {
82  m_bAvoidPowerLines = avoidPowerLines;
83  }
84 
85  //------------------------------------------------------------------------------------------------
86  void SetAvoidTracks(bool avoidTracks)
87  {
88  m_bAvoidTracks = avoidTracks;
89  }
90 
91  //------------------------------------------------------------------------------------------------
92  void SetAvoidForests(bool avoidForests)
93  {
94  m_bAvoidForests = avoidForests;
95  }
96 
97  //------------------------------------------------------------------------------------------------
98  void SetAvoidLakes(bool avoidLakes)
99  {
100  m_bAvoidLakes = avoidLakes;
101  }
102 
103  //------------------------------------------------------------------------------------------------
104  void SetAvoidLand(bool avoidLand)
105  {
106  m_bAvoidLand = avoidLand;
107  }
108 
109  //------------------------------------------------------------------------------------------------
110  void SetAvoidOcean(bool avoidOcean)
111  {
112  m_bAvoidOcean = avoidOcean;
113  }
114 
115  //------------------------------------------------------------------------------------------------
118  void SetAvoidLandOceanOffset(float offset)
119  {
120  m_fAvoidLandOceanOffset = offset;
121  }
122 
123  //------------------------------------------------------------------------------------------------
124  // used by SCR_GeneratorBaseEntity.RefreshObstacles() (and RefreshObstaclesByWorld() which is unused)
125  void RefreshObstaclesByAABB(vector worldMin, vector worldMax)
126  {
127  if (!m_WorldEditorAPI.GetWorld())
128  return;
129 
130  SetupObstacleArrays(true, true);
131  m_fOceanLevel = m_WorldEditorAPI.GetWorld().GetOceanBaseHeight();
132  m_WorldEditorAPI.GetWorld().QueryEntitiesByAABB(worldMin, worldMax, AllSplineQueryFilter);
133  }
134 
135  //------------------------------------------------------------------------------------------------
136  // unused
137  void RefreshObstaclesByWorld()
138  {
139  if (!m_WorldEditorAPI.GetWorld())
140  return;
141 
142  vector min, max;
143  m_WorldEditorAPI.GetWorld().GetBoundBox(min, max);
144  RefreshObstaclesByAABB(min, max);
145  }
146 
147  //------------------------------------------------------------------------------------------------
148  // used by ObjectBrushTool.CreateObjects()
149  void RefreshRoadObstaclesBySphere(vector worldPos, float radius)
150  {
151  if (!m_WorldEditorAPI.GetWorld())
152  return;
153 
154  SetupObstacleArrays(true, false);
155  m_fOceanLevel = m_WorldEditorAPI.GetWorld().GetOceanBaseHeight();
156  m_WorldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, RoadSplineQueryFilter);
157  }
158 
159  //------------------------------------------------------------------------------------------------
160  // used by ObjectBrushTool.OnMousePressEvent()
161  void RefreshAreaObstaclesBySphere(vector worldPos, float radius)
162  {
163  if (!m_WorldEditorAPI.GetWorld())
164  return;
165 
166  SetupObstacleArrays(false, true);
167  m_fOceanLevel = m_WorldEditorAPI.GetWorld().GetOceanBaseHeight();
168  m_WorldEditorAPI.GetWorld().QueryEntitiesBySphere(worldPos, radius, AreaSplineQueryFilter);
169  }
170 
171  //------------------------------------------------------------------------------------------------
172  // used by ObjectBrushTool.OnMousePressEvent()
173  void RefreshAreaObstaclesByWorld()
174  {
175  if (!m_WorldEditorAPI.GetWorld())
176  return;
177 
178  SetupObstacleArrays(false, true);
179  m_fOceanLevel = m_WorldEditorAPI.GetWorld().GetOceanBaseHeight();
180  vector min, max;
181  m_WorldEditorAPI.GetWorld().GetBoundBox(min, max);
182  m_WorldEditorAPI.GetWorld().QueryEntitiesByAABB(min, max, AreaSplineQueryFilter);
183  }
184 
185  //------------------------------------------------------------------------------------------------
190  bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
191  {
192  if (!m_aAvoidInfoRoads) // a null array means obstacles were cleared or never initialised
193  {
194  Print("SCR_ObstacleDetector.HasObstacle() method requires obtaining obstacles info through SCR_ObstacleDetector.RefreshObstaclesBy*() method first", LogLevel.ERROR);
195  return true; // prevent placement by default
196  }
197 
198  BaseWorld world = m_WorldEditorAPI.GetWorld();
199  if (!world)
200  return true;
201 
202  if (world.IsOcean())
203  {
204  if (m_bAvoidLand && m_bAvoidOcean)
205  return true; // let's save some time
206 
207  float terrainY = world.GetSurfaceY(worldPos[0], worldPos[2]);
208 
209  if (m_bAvoidOcean && terrainY < m_fOceanLevel + m_fAvoidLandOceanOffset)
210  return true;
211 
212  if (m_bAvoidLand && terrainY > m_fOceanLevel + m_fAvoidLandOceanOffset)
213  return true;
214  }
215 
216  if (m_bAvoidForests)
217  {
218  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoForests)
219  {
220  if (Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
221  return true;
222  }
223  }
224 
225  if (m_bAvoidLakes)
226  {
227  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoLakes)
228  {
229  if (worldPos[1] < info.m_fLakeSurfaceY && Math2D.IsPointInPolygon(info.m_a2DPoints, worldPos[0], worldPos[2]))
230  return true;
231  }
232  }
233 
234  if (m_bAvoidRoads)
235  {
236  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRoads)
237  {
238  if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
239  return true;
240  }
241  }
242 
243  if (m_bAvoidRivers)
244  {
245  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoRivers)
246  {
247  if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
248  return true;
249  }
250  }
251 
252  if (m_bAvoidPowerLines)
253  {
254  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoPowerLines)
255  {
256  if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
257  return true;
258  }
259  }
260 
261  if (m_bAvoidTracks)
262  {
263  foreach (SCR_ObstacleDetectorSplineInfo info : m_aAvoidInfoTracks)
264  {
265  if (info.IsNearRoadSplineXZ(worldPos) && SCR_Math3D.IsPointWithinSplineDistanceXZ(info.m_aTesselatedPoints, worldPos, info.m_fClearance))
266  return true;
267  }
268  }
269 
270  if (m_bAvoidObjects && (m_fAvoidObjectsDetectionHeight != 0 || m_fAvoidObjectsDetectionHeight > 0))
271  {
272  if (!m_AvoidObjectTraceSphere)
273  {
274  m_AvoidObjectTraceSphere = new TraceSphere();
275  m_AvoidObjectTraceSphere.Radius = m_fAvoidObjectsDetectionRadius;
276  m_AvoidObjectTraceSphere.LayerMask = EPhysicsLayerPresets.Main | EPhysicsLayerDefs.Water; // are the last two required?
277  m_AvoidObjectTraceSphere.Flags = TraceFlags.ENTS;
278  }
279 
280  m_AvoidObjectTraceSphere.Start = worldPos;
281  m_AvoidObjectTraceSphere.End = { worldPos[0], worldPos[1] + m_fAvoidObjectsDetectionHeight, worldPos[2] }; // move up
282 
283  if (exclusionList)
284  m_AvoidObjectTraceSphere.ExcludeArray = exclusionList;
285  else if (m_AvoidObjectTraceSphere.ExcludeArray)
286  m_AvoidObjectTraceSphere.ExcludeArray.Clear();
287 
288  world.TraceMove(m_AvoidObjectTraceSphere, null);
289 
290  if (m_AvoidObjectTraceSphere.TraceEnt) // or TraceMove < 1
291  return true;
292  }
293 
294  return false;
295  }
296 
297  //------------------------------------------------------------------------------------------------
300  bool HasObstaclesList()
301  {
302  return m_aAvoidInfoRoads != null;
303  }
304 
305  //------------------------------------------------------------------------------------------------
309  protected void SetupObstacleArrays(bool setupRoadSplines, bool setupAreaSplines)
310  {
311  // roads
312  if (setupRoadSplines || !m_aAvoidInfoRoads)
313  m_aAvoidInfoRoads = {};
314 
315  if (setupRoadSplines || !m_aAvoidInfoRivers)
316  m_aAvoidInfoRivers = {};
317 
318  if (setupRoadSplines || !m_aAvoidInfoPowerLines)
319  m_aAvoidInfoPowerLines = {};
320 
321  if (setupRoadSplines || !m_aAvoidInfoTracks)
322  m_aAvoidInfoTracks = {};
323 
324  // areas
325  if (setupAreaSplines || !m_aAvoidInfoForests)
326  m_aAvoidInfoForests = {};
327 
328  if (setupAreaSplines || !m_aAvoidInfoLakes)
329  m_aAvoidInfoLakes = {};
330  }
331 
332  //------------------------------------------------------------------------------------------------
334  // TODO: separate areas (Forest for now) vs splines
336  array<ref SCR_ObstacleDetectorSplineInfo> GetObstacles()
337  {
338  if (!m_aAvoidInfoRoads) // a null array means obstacles were cleared or never initialised
339  return null;
340 
341  array<ref SCR_ObstacleDetectorSplineInfo> result = {};
342  array<array<ref SCR_ObstacleDetectorSplineInfo>> arrays = {
343  m_aAvoidInfoRoads,
344  m_aAvoidInfoRivers,
345  m_aAvoidInfoPowerLines,
346  m_aAvoidInfoTracks,
347  m_aAvoidInfoForests,
348  m_aAvoidInfoLakes,
349  };
350 
351  foreach (array<ref SCR_ObstacleDetectorSplineInfo> arr : arrays)
352  {
353  foreach (SCR_ObstacleDetectorSplineInfo info : arr)
354  {
355  result.Insert(info);
356  }
357  }
358 
359  return result;
360  }
361 
362  //------------------------------------------------------------------------------------------------
364  void ClearObstacles()
365  {
366  m_aAvoidInfoRoads = null;
367  m_aAvoidInfoRivers = null;
368  m_aAvoidInfoPowerLines = null;
369  m_aAvoidInfoTracks = null;
370  m_aAvoidInfoForests = null;
371  m_aAvoidInfoLakes = null;
372  }
373 
374  //------------------------------------------------------------------------------------------------
380  protected bool BaseSplineQueryFilter(IEntity entity, bool getRoadSplines, bool getAreaSplines)
381  {
382  if (!getRoadSplines && !getAreaSplines)
383  return true;
384 
385  ShapeEntity shapeEntity = ShapeEntity.Cast(entity);
386  if (!shapeEntity)
387  return true;
388 
389  if (!m_WorldEditorAPI)
390  return true;
391 
392  IEntitySource shapeSource = m_WorldEditorAPI.EntityToSource(shapeEntity);
393  if (!shapeSource)
394  return true;
395 
396  IEntitySource generatorSource;
397  typename generatorTypename;
398  bool isLake;
399  for (int i, count = shapeSource.GetNumChildren(); i < count; ++i)
400  {
401  generatorSource = shapeSource.GetChild(i);
402  generatorTypename = generatorSource.GetClassName().ToType();
403  if (!generatorTypename)
404  continue;
405 
406  if (getRoadSplines)
407  {
408  if (generatorTypename.IsInherited(RoadGeneratorEntity))
409  {
410  m_aAvoidInfoRoads.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
411  break;
412  }
413 
414  if (generatorTypename.IsInherited(RiverEntity))
415  {
416  m_aAvoidInfoRivers.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
417  break;
418  }
419 
420  if (generatorTypename.IsInherited(SCR_PowerlineGeneratorEntity))
421  {
422  m_aAvoidInfoPowerLines.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
423  break;
424  }
425 
426  if (generatorTypename.IsInherited(SCR_TrackGeneratorEntity))
427  {
428  m_aAvoidInfoTracks.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
429  break;
430  }
431  }
432 
433  if (getAreaSplines)
434  {
435  if (generatorTypename.IsInherited(ForestGeneratorEntity))
436  {
437  m_aAvoidInfoForests.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
438  break;
439  }
440 
441  if (generatorTypename.IsInherited(LakeGeneratorEntity) && generatorSource.Get("m_bIsLake", isLake) && isLake)
442  {
443  m_aAvoidInfoLakes.Insert(new SCR_ObstacleDetectorSplineInfo(shapeSource, shapeEntity, generatorSource));
444  break;
445  }
446  }
447  }
448 
449  return true;
450  }
451 
452  //------------------------------------------------------------------------------------------------
454  protected bool AllSplineQueryFilter(IEntity entity)
455  {
456  return BaseSplineQueryFilter(entity, true, true);
457  }
458 
459  //------------------------------------------------------------------------------------------------
461  protected bool RoadSplineQueryFilter(IEntity entity)
462  {
463  return BaseSplineQueryFilter(entity, true, false);
464  }
465 
466  //------------------------------------------------------------------------------------------------
468  protected bool AreaSplineQueryFilter(IEntity entity)
469  {
470  return BaseSplineQueryFilter(entity, false, true);
471  }
472 
473  //------------------------------------------------------------------------------------------------
474  // constructor
475  void SCR_ObstacleDetector(WorldEditorAPI worldEditorAPI) // not using notnull to prevent World Editor lockup
476  {
477  m_WorldEditorAPI = worldEditorAPI;
478  if (!m_WorldEditorAPI)
479  Print("Something went wrong with SCR_ObstacleDetector init: passed worldEditorAPI is null", LogLevel.ERROR);
480  }
481 }
482 
483 class SCR_ObstacleDetectorSplineInfo
484 {
485  float m_fClearance;
486  float m_fLakeSurfaceY;
487  ref array<float> m_a2DPoints;
488  ref array<vector> m_aTesselatedPoints;
489  ref array<vector> m_aMinsWithClearance;
490  ref array<vector> m_aMaxsWithClearance;
491  vector m_vMinWithClearance;
492  vector m_vMaxWithClearance;
493 
494  //------------------------------------------------------------------------------------------------
497  bool IsNearRoadSplineXZ(vector point)
498  {
499  float x = point[0];
500  float z = point[2];
501 
502  if (x < m_vMinWithClearance[0] || m_vMaxWithClearance[0] < x ||
503  z < m_vMinWithClearance[2] || m_vMaxWithClearance[2] < z)
504  return false; // nowhere near
505 
506  vector max;
507  foreach (int index, vector min : m_aMinsWithClearance)
508  {
509  max = m_aMaxsWithClearance[index];
510  if (min[0] <= x && x <= max[0])
511  {
512  if (min[2] <= z && z <= max[2])
513  return true;
514  }
515  }
516 
517  return false;
518  }
519 
520  //------------------------------------------------------------------------------------------------
525  // minor performance gains to add clearance to mins/maxs but gains nonetheless (e.g 500ms on 20s calculation so ~= 2.5% on big area)
526  protected void GetAndSetMinMaxWithClearance(inout notnull array<vector> mins, inout notnull array<vector> maxs, out vector min, out vector max)
527  {
528  vector vectorClearance = { m_fClearance, 0, m_fClearance };
529  int minsCount = mins.Count();
530  int maxsCount = maxs.Count();
531 
532  if (minsCount < 1 || maxsCount < 1 || minsCount != maxsCount)
533  {
534  min = -vectorClearance;
535  max = vectorClearance;
536  return;
537  }
538 
539  min = mins[0];
540  for (int i; i < minsCount; i++)
541  {
542  mins[i] = mins[i] - vectorClearance;
543  for (int j; j < 3; j++)
544  {
545  if (min[j] > mins[i][j])
546  min[j] = mins[i][j];
547  }
548  }
549 
550  max = maxs[0];
551  for (int i; i < maxsCount; i++)
552  {
553  maxs[i] = maxs[i] + vectorClearance;
554  for (int j; j < 3; j++)
555  {
556  if (max[j] < maxs[i][j])
557  max[j] = maxs[i][j];
558  }
559  }
560  }
561 
562  //------------------------------------------------------------------------------------------------
568  protected static int GetPoints2D3D(notnull ShapeEntity shapeEntity, out array<float> pos2D, out array<vector> pos3D)
569  {
570  if (!pos2D && !pos3D)
571  return -1;
572 
573  array<vector> points3D = {};
574  shapeEntity.GetPointsPositions(points3D);
575 
576  if (pos2D)
577  {
578  pos2D.Clear();
579  foreach (vector point : points3D)
580  {
581  pos2D.Insert(point[0]);
582  pos2D.Insert(point[2]);
583  }
584  }
585 
586  if (pos3D)
587  pos3D.Copy(points3D);
588 
589  return points3D.Count();
590  }
591 
592  //------------------------------------------------------------------------------------------------
593  protected array<vector> GetTesselatedWorldPoints(notnull ShapeEntity shapeEntity)
594  {
595  array<vector> result = {};
596 
597  shapeEntity.GenerateTesselatedShape(result);
598  for (int i, count = result.Count(); i < count; i++)
599  {
600  result[i] = shapeEntity.CoordToParent(result[i]);
601  }
602 
603  return result;
604  }
605 
606  //------------------------------------------------------------------------------------------------
607  // constructor
608  void SCR_ObstacleDetectorSplineInfo(notnull IEntitySource shapeEntitySource, notnull ShapeEntity shapeEntity, notnull IEntitySource generatorSource)
609  {
610  typename generatorTypeName = generatorSource.GetClassName().ToType();
611  if (!generatorTypeName)
612  return;
613 
614  m_aMinsWithClearance = {};
615  m_aMaxsWithClearance = {};
616 
617  /*
618  ROAD
619  */
620  if (generatorTypeName.IsInherited(RoadGeneratorEntity))
621  {
622  generatorSource.Get("RoadClearance", m_fClearance);
623  m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
624  shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
625  GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
626  return;
627  }
628 
629  /*
630  RIVER,
631  POWER LINE
632  */
633  if (generatorTypeName.IsInherited(RiverEntity) ||
634  generatorTypeName.IsInherited(SCR_PowerlineGeneratorEntity))
635  {
636  generatorSource.Get("Clearance", m_fClearance);
637  m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
638  shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
639  GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
640  return;
641  }
642 
643  /*
644  TRACK
645  */
646  if (generatorTypeName.IsInherited(SCR_TrackGeneratorEntity))
647  {
648  generatorSource.Get("m_fClearance", m_fClearance);
649  m_aTesselatedPoints = GetTesselatedWorldPoints(shapeEntity);
650  shapeEntity.GetAllInfluenceBBoxes(shapeEntitySource, m_aMinsWithClearance, m_aMaxsWithClearance);
651  GetAndSetMinMaxWithClearance(m_aMinsWithClearance, m_aMaxsWithClearance, m_vMinWithClearance, m_vMaxWithClearance);
652  return;
653  }
654 
655  /*
656  FOREST
657  */
658  if (generatorTypeName.IsInherited(ForestGeneratorEntity))
659  {
660  m_a2DPoints = {};
661  GetPoints2D3D(shapeEntity, m_a2DPoints, null);
662  return;
663  }
664 
665  /*
666  LAKE
667  */
668  if (generatorTypeName.IsInherited(LakeGeneratorEntity))
669  {
670  m_a2DPoints = {};
671  array<vector> a3DPoints = {};
672  GetPoints2D3D(shapeEntity, m_a2DPoints, a3DPoints);
673 
674  bool flattenByBottomPlane;
675  generatorSource.Get("m_bFlattenByBottomPlane", flattenByBottomPlane);
676 
677  if (a3DPoints.IsEmpty())
678  return;
679 
680  // all this to be replaced with a later LakeGeneratorEntity method
681  float minOrMaxY = a3DPoints[0][1];
682  foreach (vector a3DPoint : a3DPoints)
683  {
684  if (flattenByBottomPlane)
685  {
686  if (a3DPoint[1] < minOrMaxY)
687  minOrMaxY = a3DPoint[1];
688  }
689  else
690  {
691  if (a3DPoint[1] > minOrMaxY)
692  minOrMaxY = a3DPoint[1];
693  }
694  }
695 
696  m_fLakeSurfaceY = minOrMaxY;
697  return;
698  }
699  }
700 }
701 
702 #endif
SCR_PowerlineGeneratorEntity
void SCR_PowerlineGeneratorEntity(IEntitySource src, IEntity parent)
Definition: SCR_PowerlineGeneratorEntity.c:980
SCR_TrackGeneratorEntity
void SCR_TrackGeneratorEntity(IEntitySource src, IEntity parent)
Definition: SCR_TrackGeneratorEntity.c:12
SCR_Math3D
Contains various scripted 3D math functions.
Definition: SCR_Math3D.c:2
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
IsValid
override bool IsValid(IEntity actionOwner, IEntity actionUser, SCR_BaseUseSupportStationAction action, vector actionPosition, out ESupportStationReasonInvalid reasonInvalid, out int supplyCost)
Definition: SCR_BaseDamageHealSupportStationComponent.c:98