14 static bool TraceCylinder(vector pos,
float radius = 0.5,
float height = 2, TraceFlags flags = TraceFlags.ENTS | TraceFlags.OCEAN, BaseWorld world =
null)
19 float heightHalf = height * 0.5;
21 autoptr TraceParam trace =
new TraceParam();
24 vector dir = Vector(radius, heightHalf, 0);
25 trace.Start = pos + dir;
26 trace.End = pos - dir;
27 if (world.TraceMove(trace,
null) < 1)
30 dir = Vector(-radius, heightHalf, 0);
31 trace.Start = pos + dir;
32 trace.End = pos - dir;
33 if (world.TraceMove(trace,
null) < 1)
36 dir = Vector(0, heightHalf, radius);
37 trace.Start = pos + dir;
38 trace.End = pos - dir;
39 if (world.TraceMove(trace,
null) < 1)
42 dir = Vector(0, heightHalf, -radius);
43 trace.Start = pos + dir;
44 trace.End = pos - dir;
45 if (world.TraceMove(trace,
null) < 1)
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)
67 if (areaRadius <= 0 || cylinderRadius <= 0 || cylinderHeight <= 0)
69 outPosition = areaCenter;
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));
82 TraceParam trace =
new TraceParam();
83 trace.Flags = flags | TraceFlags.WORLD;
84 vector traceOffset = Vector(0, 10, 0);
87 int yMin, yMax, yStep;
89 for (
int r; r < rMax; r++)
91 for (
int x = -r; x <= r; x++)
94 posY = cellH * (x -
SCR_Math.fmod(x, 1)) * 0.5;
96 yMin = Math.Max(-r - x, -r);
97 yMax = Math.Min(r - x, r);
98 if (Math.AbsInt(x) == r)
103 for (
int y = yMin; y <= yMax; y += yStep)
105 outPosition = areaCenter + Vector(posX, 0, posY + cellH * y);
106 if (vector.DistanceXZ(outPosition, areaCenter) > areaRadius - cylinderRadius)
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]));
115 if (TraceCylinder(outPosition + cylinderVectorOffset, cylinderRadius, cylinderHeight, flags, world))
120 outPosition = areaCenter;
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)
141 if (areaRadius <= 0 || cylinderRadius <= 0 || cylinderHeight <= 0)
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));
153 TraceParam trace =
new TraceParam();
154 trace.Flags = flags | TraceFlags.WORLD;
155 vector traceOffset = Vector(0, 10, 0);
159 int yMin, yMax, yStep;
161 for (
int r; r < rMax; r++)
163 for (
int x = -r; x <= r; x++)
166 posY = cellH * (x -
SCR_Math.fmod(x, 1)) * 0.5;
168 yMin = Math.Max(-r - x, -r);
169 yMax = Math.Min(r - x, r);
170 if (Math.AbsInt(x) == r)
175 for (
int y = yMin; y <= yMax; y += yStep)
177 position = areaCenter + Vector(posX, 0, posY + cellH * y);
178 if (vector.DistanceXZ(
position, areaCenter) > areaRadius - cylinderRadius)
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]));
187 if (TraceCylinder(
position + cylinderVectorOffset, cylinderRadius, cylinderHeight, flags, world))
191 if (maxResults > -1 && outPositions.Count() >= maxResults)
195 return outPositions.Count();
207 static bool IsObjectUnderwater(notnull IEntity
object, vector
position = vector.Zero,
int boneID = -1, out
float depth = -1)
209 BaseWorld world =
object.GetWorld();
214 Physics physics =
object.GetPhysics();
216 position += physics.GetGeomPosition(boneID);
219 vector outWaterSurfacePoint;
221 vector transformWS[4];
224 bool isUnderwater =
ChimeraWorldUtils.TryGetWaterSurface(world,
position, outWaterSurfacePoint, outType, transformWS, obbExtents);
226 depth = vector.Distance(outWaterSurfacePoint,
position);
232 static float GetWaterSurfaceY(BaseWorld world, vector worldPos, out
EWaterSurfaceType waterSurfaceType, out
float lakeArea)
234 vector waterSurfacePos;
235 vector transformWS[4];
238 ChimeraWorldUtils.TryGetWaterSurface(world, worldPos, waterSurfacePos, waterSurfaceType, transformWS, obbExtents);
239 lakeArea = obbExtents[0] * obbExtents[2];
241 return waterSurfacePos[1];