Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_WorldTools.c
Go to the documentation of this file.
2 {
3  //------------------------------------------------------------------------------------------------
14  static bool TraceCylinder(vector pos, float radius = 0.5, float height = 2, TraceFlags flags = TraceFlags.ENTS | TraceFlags.OCEAN, BaseWorld world = null)
15  {
16  if (!world)
17  world = GetGame().GetWorld();
18 
19  float heightHalf = height * 0.5;
20 
21  autoptr TraceParam trace = new TraceParam();
22  trace.Flags = flags;
23 
24  vector dir = Vector(radius, heightHalf, 0);
25  trace.Start = pos + dir;
26  trace.End = pos - dir;
27  if (world.TraceMove(trace, null) < 1)
28  return false;
29 
30  dir = Vector(-radius, heightHalf, 0);
31  trace.Start = pos + dir;
32  trace.End = pos - dir;
33  if (world.TraceMove(trace, null) < 1)
34  return false;
35 
36  dir = Vector(0, heightHalf, radius);
37  trace.Start = pos + dir;
38  trace.End = pos - dir;
39  if (world.TraceMove(trace, null) < 1)
40  return false;
41 
42  dir = Vector(0, heightHalf, -radius);
43  trace.Start = pos + dir;
44  trace.End = pos - dir;
45  if (world.TraceMove(trace, null) < 1)
46  return false;
47 
48  return true;
49  }
50 
51  //------------------------------------------------------------------------------------------------
64  static bool FindEmptyTerrainPosition(out vector outPosition, vector areaCenter, float areaRadius, float cylinderRadius = 0.5, float cylinderHeight = 2, TraceFlags flags = TraceFlags.ENTS | TraceFlags.OCEAN, BaseWorld world = null)
65  {
66  //--- Incorrect params
67  if (areaRadius <= 0 || cylinderRadius <= 0 || cylinderHeight <= 0)
68  {
69  outPosition = areaCenter;
70  return false;
71  }
72 
73  if (!world)
74  world = GetGame().GetWorld();
75 
76  //--- Precalculate vars
77  float cellW = cylinderRadius * Math.Sqrt(3);
78  float cellH = cylinderRadius * 2;
79  vector cylinderVectorOffset = Vector(0, cylinderHeight * 0.5, 0);
80  int rMax = Math.Ceil(areaRadius / cylinderRadius / Math.Sqrt(3));
81 
82  TraceParam trace = new TraceParam();
83  trace.Flags = flags | TraceFlags.WORLD;
84  vector traceOffset = Vector(0, 10, 0);
85 
86  float posX, posY;
87  int yMin, yMax, yStep;
88  float traceCoef;
89  for (int r; r < rMax; r++)
90  {
91  for (int x = -r; x <= r; x++)
92  {
93  posX = cellW * x;
94  posY = cellH * (x - SCR_Math.fmod(x, 1)) * 0.5;
95 
96  yMin = Math.Max(-r - x, -r);
97  yMax = Math.Min(r - x, r);
98  if (Math.AbsInt(x) == r)
99  yStep = 1;
100  else
101  yStep = yMax - yMin;
102 
103  for (int y = yMin; y <= yMax; y += yStep)
104  {
105  outPosition = areaCenter + Vector(posX, 0, posY + cellH * y);
106  if (vector.DistanceXZ(outPosition, areaCenter) > areaRadius - cylinderRadius)
107  continue;
108 
109  //--- Find nearest surface below (make sure it's not underground)
110  trace.Start = outPosition;
111  trace.End = outPosition - traceOffset;
112  traceCoef = world.TraceMove(trace, null);
113  outPosition[1] = Math.Max(trace.Start[1] - traceCoef * traceOffset[1] + 0.01, world.GetSurfaceY(outPosition[0], outPosition[2]));
114 
115  if (TraceCylinder(outPosition + cylinderVectorOffset, cylinderRadius, cylinderHeight, flags, world))
116  return true;
117  }
118  }
119  }
120  outPosition = areaCenter;
121  return false;
122  }
123 
124  //------------------------------------------------------------------------------------------------
138  static int FindAllEmptyTerrainPositions(out notnull array<vector> outPositions, vector areaCenter, float areaRadius, float cylinderRadius = 0.5, float cylinderHeight = 2, int maxResults = -1, TraceFlags flags = TraceFlags.ENTS | TraceFlags.OCEAN, BaseWorld world = null)
139  {
140  //--- Incorrect params
141  if (areaRadius <= 0 || cylinderRadius <= 0 || cylinderHeight <= 0)
142  return 0;
143 
144  if (!world)
145  world = GetGame().GetWorld();
146 
147  //--- Precalculate vars
148  float cellW = cylinderRadius * Math.Sqrt(3);
149  float cellH = cylinderRadius * 2;
150  vector cylinderVectorOffset = Vector(0, cylinderHeight * 0.5, 0);
151  int rMax = Math.Ceil(areaRadius / cylinderRadius / Math.Sqrt(3));
152 
153  TraceParam trace = new TraceParam();
154  trace.Flags = flags | TraceFlags.WORLD;
155  vector traceOffset = Vector(0, 10, 0);
156 
157  vector position;
158  float posX, posY;
159  int yMin, yMax, yStep;
160  float traceCoef;
161  for (int r; r < rMax; r++)
162  {
163  for (int x = -r; x <= r; x++)
164  {
165  posX = cellW * x;
166  posY = cellH * (x - SCR_Math.fmod(x, 1)) * 0.5;
167 
168  yMin = Math.Max(-r - x, -r);
169  yMax = Math.Min(r - x, r);
170  if (Math.AbsInt(x) == r)
171  yStep = 1;
172  else
173  yStep = yMax - yMin;
174 
175  for (int y = yMin; y <= yMax; y += yStep)
176  {
177  position = areaCenter + Vector(posX, 0, posY + cellH * y);
178  if (vector.DistanceXZ(position, areaCenter) > areaRadius - cylinderRadius)
179  continue;
180 
181  //--- Find nearest surface below (make sure it's not underground)
182  trace.Start = position;
183  trace.End = position - traceOffset;
184  traceCoef = world.TraceMove(trace, null);
185  position[1] = Math.Max(trace.Start[1] - traceCoef * traceOffset[1] + 0.01, world.GetSurfaceY(position[0], position[2]));
186 
187  if (TraceCylinder(position + cylinderVectorOffset, cylinderRadius, cylinderHeight, flags, world))
188  outPositions.Insert(position);
189  }
190 
191  if (maxResults > -1 && outPositions.Count() >= maxResults)
192  break;
193  }
194  }
195  return outPositions.Count();
196  }
197 
198  //------------------------------------------------------------------------------------------------
207  static bool IsObjectUnderwater(notnull IEntity object, vector position = vector.Zero, int boneID = -1, out float depth = -1)
208  {
209  BaseWorld world = object.GetWorld();
210  position = object.CoordToParent(position);
211 
212  if (boneID >= 0)
213  {
214  Physics physics = object.GetPhysics();
215  if (physics)
216  position += physics.GetGeomPosition(boneID);
217  }
218 
219  vector outWaterSurfacePoint;
220  EWaterSurfaceType outType;
221  vector transformWS[4];
222  vector obbExtents;
223 
224  bool isUnderwater = ChimeraWorldUtils.TryGetWaterSurface(world, position, outWaterSurfacePoint, outType, transformWS, obbExtents);
225  if (isUnderwater)
226  depth = vector.Distance(outWaterSurfacePoint, position);
227 
228  return isUnderwater;
229  }
230 
231  //------------------------------------------------------------------------------------------------
232  static float GetWaterSurfaceY(BaseWorld world, vector worldPos, out EWaterSurfaceType waterSurfaceType, out float lakeArea)
233  {
234  vector waterSurfacePos;
235  vector transformWS[4];
236  vector obbExtents;
237 
238  ChimeraWorldUtils.TryGetWaterSurface(world, worldPos, waterSurfacePos, waterSurfaceType, transformWS, obbExtents);
239  lakeArea = obbExtents[0] * obbExtents[2];
240 
241  return waterSurfacePos[1];
242  }
243 };
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_WorldTools
Definition: SCR_WorldTools.c:1
SCR_Math
Definition: SCR_Math.c:1
position
vector position
Definition: SCR_DestructibleTreeV2.c:30
ChimeraWorldUtils
Definition: ChimeraWorldUtils.c:7
EWaterSurfaceType
EWaterSurfaceType
Definition: EWaterSurfaceType.c:7