v1.7.7.0 (Winter Update 2024)
This commit is contained in:
@@ -96,9 +96,13 @@ namespace Barotrauma
|
||||
new Vector2(Math.Sign(targetHull.Rect.Center.X - rect.Center.X), 0.0f)
|
||||
: new Vector2(0.0f, Math.Sign((rect.Y - rect.Height / 2.0f) - (targetHull.Rect.Y - targetHull.Rect.Height / 2.0f)));
|
||||
|
||||
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
|
||||
Vector2 arrowPos = new Vector2(WorldRect.Center.X, WorldRect.Y - WorldRect.Height / 2);
|
||||
if (Submarine != null)
|
||||
{
|
||||
arrowPos += (Submarine.DrawPosition - Submarine.Position);
|
||||
}
|
||||
arrowPos.Y = -arrowPos.Y;
|
||||
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2), dir.Y * (WorldRect.Height / 2));
|
||||
|
||||
bool invalidDir = false;
|
||||
if (dir == Vector2.Zero)
|
||||
{
|
||||
|
||||
@@ -404,8 +404,8 @@ namespace Barotrauma
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.LastExtinguishPos.X, (int)-fs.LastExtinguishPos.Y, 5,5), Color.Yellow, true);
|
||||
}
|
||||
|
||||
|
||||
GUI.DrawLine(spriteBatch, new Vector2(drawRect.X, -WorldSurface), new Vector2(drawRect.Right, -WorldSurface), Color.Cyan * 0.5f);
|
||||
float worldSurface = surface + Submarine.DrawPosition.Y;
|
||||
GUI.DrawLine(spriteBatch, new Vector2(drawRect.X, -worldSurface), new Vector2(drawRect.Right, -worldSurface), Color.Cyan * 0.5f);
|
||||
for (int i = 0; i < waveY.Length - 1; i++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
@@ -578,8 +578,7 @@ namespace Barotrauma
|
||||
corners[4] = new Vector3(x, bottom, 0.0f);
|
||||
//bottom right
|
||||
corners[5] = new Vector3(x + width, bottom, 0.0f);
|
||||
|
||||
Vector2[] uvCoords = new Vector2[4];
|
||||
|
||||
for (int n = 0; n < 4; n++)
|
||||
{
|
||||
uvCoords[n] = Vector2.Transform(new Vector2(corners[n].X, -corners[n].Y), transform);
|
||||
|
||||
@@ -9,26 +9,56 @@ namespace Barotrauma
|
||||
{
|
||||
static partial class CaveGenerator
|
||||
{
|
||||
public static List<VertexPositionTexture> GenerateWallVertices(List<Vector2[]> triangles, LevelGenerationParams generationParams, float zCoord)
|
||||
public static List<VertexPositionColor> GenerateWallVertices(List<Vector2[]> triangles, Color color, float zCoord)
|
||||
{
|
||||
var vertices = new List<VertexPositionTexture>();
|
||||
var vertices = new List<VertexPositionColor>();
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
foreach (Vector2 vertex in triangles[i])
|
||||
{
|
||||
Vector2 uvCoords = vertex / generationParams.WallTextureSize;
|
||||
vertices.Add(new VertexPositionTexture(new Vector3(vertex, zCoord), uvCoords));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(vertex, zCoord), color));
|
||||
}
|
||||
}
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
public static List<VertexPositionTexture> GenerateWallEdgeVertices(List<VoronoiCell> cells, Level level, float zCoord)
|
||||
/// <summary>
|
||||
/// Generates texture coordinates for the vertices based on their positions
|
||||
/// </summary>
|
||||
public static VertexPositionColorTexture[] ConvertToTextured(VertexPositionColor[] verts, float textureSize)
|
||||
{
|
||||
float outWardThickness = level.GenerationParams.WallEdgeExpandOutwardsAmount;
|
||||
VertexPositionColorTexture[] texturedVerts = new VertexPositionColorTexture[verts.Length];
|
||||
for (int i = 0; i < verts.Length; i++)
|
||||
{
|
||||
VertexPositionColor vertex = verts[i];
|
||||
texturedVerts[i] = new VertexPositionColorTexture(vertex.Position, vertex.Color, textureCoordinate: Vector2.Zero);
|
||||
}
|
||||
GenerateTextureCoordinates(texturedVerts, textureSize);
|
||||
return texturedVerts;
|
||||
}
|
||||
|
||||
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
|
||||
/// <summary>
|
||||
/// Generates texture coordinates for the vertices based on their positions
|
||||
/// </summary>
|
||||
public static void GenerateTextureCoordinates(VertexPositionColorTexture[] verts, float textureSize)
|
||||
{
|
||||
for (int i = 0; i < verts.Length; i++)
|
||||
{
|
||||
VertexPositionColorTexture vertex = verts[i];
|
||||
Vector2 uvCoords = new Vector2(vertex.Position.X, vertex.Position.Y) / textureSize;
|
||||
verts[i] = new VertexPositionColorTexture(verts[i].Position, verts[i].Color, uvCoords);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<VertexPositionColorTexture> GenerateWallEdgeVertices(
|
||||
List<VoronoiCell> cells,
|
||||
float expandOutwards, float expandInwards,
|
||||
Color outerColor, Color innerColor,
|
||||
Level level, float zCoord, bool preventExpandThroughCell = false)
|
||||
{
|
||||
float outWardThickness = expandOutwards;
|
||||
|
||||
List<VertexPositionColorTexture> vertices = new List<VertexPositionColorTexture>();
|
||||
foreach (VoronoiCell cell in cells)
|
||||
{
|
||||
Vector2 minVert = cell.Edges[0].Point1;
|
||||
@@ -49,7 +79,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (!edge.IsSolid) { continue; }
|
||||
|
||||
GraphEdge leftEdge = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||
//the left-side edge on this same cell
|
||||
GraphEdge myLeftEdge = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||
//the left-side edge on either this cell, or the adjacent one if this is attached to another cell
|
||||
GraphEdge leftEdge = myLeftEdge;
|
||||
var leftAdjacentCell = leftEdge?.AdjacentCell(cell);
|
||||
if (leftAdjacentCell != null)
|
||||
{
|
||||
@@ -57,7 +90,10 @@ namespace Barotrauma
|
||||
if (adjEdge != null) { leftEdge = adjEdge; }
|
||||
}
|
||||
|
||||
GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||
//the right-side edge on this same cell
|
||||
GraphEdge myRightEdge = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||
//the right-side edge on either this cell, or the adjacent one if this is attached to another cell
|
||||
GraphEdge rightEdge = myRightEdge;
|
||||
var rightAdjacentCell = rightEdge?.AdjacentCell(cell);
|
||||
if (rightAdjacentCell != null)
|
||||
{
|
||||
@@ -67,18 +103,25 @@ namespace Barotrauma
|
||||
|
||||
Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;
|
||||
|
||||
float inwardThickness1 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||
float inwardThickness2 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||
float inwardThickness1 = Math.Min(expandInwards, edge.Length);
|
||||
float inwardThickness2 = inwardThickness1;
|
||||
if (leftEdge != null && !leftEdge.IsSolid)
|
||||
{
|
||||
//the left-side edge is non-solid (an edge between two cells, not an actual solid wall edge)
|
||||
// -> expand in the direction of that edge
|
||||
leftNormal = edge.Point1.NearlyEquals(leftEdge.Point1) ?
|
||||
Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
|
||||
Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
|
||||
//maximum expansion is half of the size of the edge (otherwise the expansions from different sides of the edge could overlap or even extend "through" the cell)
|
||||
inwardThickness1 = Math.Min(inwardThickness1, leftEdge.Length / 2);
|
||||
}
|
||||
else if (leftEdge != null)
|
||||
{
|
||||
//use the average of this edge's and the adjacent edge's normals
|
||||
leftNormal = -Vector2.Normalize(edge.GetNormal(cell) + leftEdge.GetNormal(leftAdjacentCell ?? cell));
|
||||
if (!MathUtils.IsValid(leftNormal)) { leftNormal = -edge.GetNormal(cell); }
|
||||
//maximum expansion is the length of the adjacent edge (more expansion causes the textures to distort)
|
||||
inwardThickness1 = Math.Min(Math.Min(inwardThickness1, leftEdge.Length), myLeftEdge.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,11 +152,13 @@ namespace Barotrauma
|
||||
rightNormal = edge.Point2.NearlyEquals(rightEdge.Point1) ?
|
||||
Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
|
||||
Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
|
||||
inwardThickness2 = Math.Min(inwardThickness2, rightEdge.Length / 2);
|
||||
}
|
||||
else if (rightEdge != null)
|
||||
{
|
||||
rightNormal = -Vector2.Normalize(edge.GetNormal(cell) + rightEdge.GetNormal(rightAdjacentCell ?? cell));
|
||||
if (!MathUtils.IsValid(rightNormal)) { rightNormal = -edge.GetNormal(cell); }
|
||||
inwardThickness2 = Math.Min(Math.Min(inwardThickness2, rightEdge.Length), myRightEdge.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,10 +195,51 @@ namespace Barotrauma
|
||||
point1UV = point1UV / MathHelper.TwoPi * textureRepeatCount;
|
||||
point2UV = point2UV / MathHelper.TwoPi * textureRepeatCount;
|
||||
|
||||
//if calculating the UVs based on polar coordinates would result in stretching (using less than 10% of the texture for a wall the size of the texture)
|
||||
//just calculate the UVs based on the length of the wall
|
||||
//(this will mean the textures don't align at point2, but it doesn't seem that noticeable)
|
||||
if ((point2UV - point1UV) * level.GenerationParams.WallEdgeTextureWidth < edge.Length * 0.1f)
|
||||
{
|
||||
point2UV = point1UV + edge.Length / 2 / level.GenerationParams.WallEdgeTextureWidth;
|
||||
}
|
||||
|
||||
//"extruding" inwards, need to make sure we don't make the edge poke through the cell from the other side
|
||||
if (preventExpandThroughCell)
|
||||
{
|
||||
foreach (GraphEdge otherEdge in cell.Edges)
|
||||
{
|
||||
if (otherEdge == edge || Vector2.Dot(otherEdge.GetNormal(cell), edge.GetNormal(cell)) > 0) { continue; }
|
||||
if (otherEdge != leftEdge)
|
||||
{
|
||||
inwardThickness1 = ClampThickness(otherEdge, edge.Point1, leftNormal, inwardThickness1);
|
||||
}
|
||||
if (otherEdge != rightEdge)
|
||||
{
|
||||
inwardThickness2 = ClampThickness(otherEdge, edge.Point2, rightNormal, inwardThickness2);
|
||||
}
|
||||
}
|
||||
|
||||
static float ClampThickness(GraphEdge otherEdge, Vector2 thisPoint, Vector2 thisEdgeNormal, float currThickness)
|
||||
{
|
||||
if (MathUtils.GetLineIntersection(
|
||||
thisPoint, thisPoint + thisEdgeNormal * currThickness,
|
||||
otherEdge.Point1, otherEdge.Point2, areLinesInfinite: false, out Vector2 intersection1))
|
||||
{
|
||||
return Math.Min(currThickness, Vector2.Distance(thisPoint, intersection1));
|
||||
}
|
||||
return currThickness;
|
||||
}
|
||||
}
|
||||
|
||||
//there needs to be some minimum amount of inward thickness,
|
||||
//if the edge texture doesn't extend inside at all you can see through between the edge texture and the solid part of the cell
|
||||
inwardThickness1 = Math.Max(inwardThickness1, Math.Min(100.0f, expandInwards));
|
||||
inwardThickness2 = Math.Max(inwardThickness2, Math.Min(100.0f, expandInwards));
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Vector2[] verts = new Vector2[3];
|
||||
VertexPositionTexture[] vertPos = new VertexPositionTexture[3];
|
||||
VertexPositionColorTexture[] vertPos = new VertexPositionColorTexture[3];
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
@@ -161,9 +247,9 @@ namespace Barotrauma
|
||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||
verts[2] = edge.Point1 + leftNormal * inwardThickness1;
|
||||
|
||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 0.0f));
|
||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point1UV, 1.0f));
|
||||
vertPos[0] = new VertexPositionColorTexture(new Vector3(verts[0], zCoord), outerColor, new Vector2(point1UV, 0.0f));
|
||||
vertPos[1] = new VertexPositionColorTexture(new Vector3(verts[1], zCoord), outerColor, new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionColorTexture(new Vector3(verts[2], zCoord), innerColor, new Vector2(point1UV, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -172,9 +258,9 @@ namespace Barotrauma
|
||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||
verts[2] = edge.Point2 + rightNormal * inwardThickness2;
|
||||
|
||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 1.0f));
|
||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point2UV, 1.0f));
|
||||
vertPos[0] = new VertexPositionColorTexture(new Vector3(verts[0], zCoord), innerColor, new Vector2(point1UV, 1.0f));
|
||||
vertPos[1] = new VertexPositionColorTexture(new Vector3(verts[1], zCoord), outerColor, new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionColorTexture(new Vector3(verts[2], zCoord), innerColor, new Vector2(point2UV, 1.0f));
|
||||
}
|
||||
vertices.AddRange(vertPos);
|
||||
}
|
||||
|
||||
+23
-5
@@ -10,9 +10,11 @@ namespace Barotrauma
|
||||
{
|
||||
partial class LevelObjectManager
|
||||
{
|
||||
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
||||
private readonly List<LevelObject> visibleObjectsMid = new List<LevelObject>();
|
||||
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
||||
// Pre-initialized to the max size, so that we don't have to resize the lists at runtime. TODO: Could the capacity (of some collections?) be lower?
|
||||
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly List<LevelObject> visibleObjectsMid = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly HashSet<LevelObject> allVisibleObjects = new HashSet<LevelObject>(MaxVisibleObjects);
|
||||
|
||||
private double NextRefreshTime;
|
||||
|
||||
@@ -47,9 +49,25 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<LevelObject> GetVisibleObjects()
|
||||
/// <summary>
|
||||
/// Returns all visible objects, but not in order, because internally uses a HashSet.
|
||||
/// </summary>
|
||||
public IEnumerable<LevelObject> GetAllVisibleObjects()
|
||||
{
|
||||
return visibleObjectsBack.Union(visibleObjectsMid).Union(visibleObjectsFront);
|
||||
allVisibleObjects.Clear();
|
||||
foreach (LevelObject obj in visibleObjectsBack)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsMid)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsFront)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
return allVisibleObjects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -11,10 +11,25 @@ namespace Barotrauma
|
||||
{
|
||||
class LevelWallVertexBuffer : IDisposable
|
||||
{
|
||||
public VertexBuffer WallEdgeBuffer, WallBuffer;
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the "actual" wall texture.
|
||||
/// </summary>
|
||||
public VertexBuffer WallBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the repeating edge texture drawn at the edges of the walls.
|
||||
/// </summary>
|
||||
public VertexBuffer WallEdgeBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the inner, non-textured black part of the wall.
|
||||
/// </summary>
|
||||
public VertexBuffer WallInnerBuffer;
|
||||
|
||||
public readonly Texture2D WallTexture, EdgeTexture;
|
||||
private VertexPositionColorTexture[] wallVertices;
|
||||
private VertexPositionColorTexture[] wallEdgeVertices;
|
||||
private VertexPositionColor[] wallInnerVertices;
|
||||
|
||||
public bool IsDisposed
|
||||
{
|
||||
@@ -22,7 +37,7 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public LevelWallVertexBuffer(VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices, VertexPositionColor[] wallInnerVertices, Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
if (wallVertices.Length == 0)
|
||||
{
|
||||
@@ -32,32 +47,41 @@ namespace Barotrauma
|
||||
{
|
||||
throw new ArgumentException("Failed to instantiate a LevelWallVertexBuffer (no wall edge vertices).");
|
||||
}
|
||||
this.wallVertices = LevelRenderer.GetColoredVertices(wallVertices, color);
|
||||
this.wallVertices = wallVertices;
|
||||
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallVertices.Length, BufferUsage.WriteOnly);
|
||||
WallBuffer.SetData(this.wallVertices);
|
||||
WallTexture = wallTexture;
|
||||
|
||||
this.wallEdgeVertices = LevelRenderer.GetColoredVertices(wallEdgeVertices, color);
|
||||
this.wallEdgeVertices = wallEdgeVertices;
|
||||
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||
EdgeTexture = edgeTexture;
|
||||
|
||||
if (wallInnerVertices != null)
|
||||
{
|
||||
this.wallInnerVertices = wallInnerVertices;
|
||||
WallInnerBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColor.VertexDeclaration, wallInnerVertices.Length, BufferUsage.WriteOnly);
|
||||
WallInnerBuffer.SetData(this.wallInnerVertices);
|
||||
}
|
||||
}
|
||||
|
||||
public void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
|
||||
public void Append(VertexPositionColorTexture[] newWallVertices, VertexPositionColorTexture[] newWallEdgeVertices, VertexPositionColor[] newWallInnerVertices)
|
||||
{
|
||||
WallBuffer.Dispose();
|
||||
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallVertices.Length + wallVertices.Length, BufferUsage.WriteOnly);
|
||||
int originalWallVertexCount = this.wallVertices.Length;
|
||||
Array.Resize(ref this.wallVertices, originalWallVertexCount + wallVertices.Length);
|
||||
Array.Copy(LevelRenderer.GetColoredVertices(wallVertices, color), 0, this.wallVertices, originalWallVertexCount, wallVertices.Length);
|
||||
WallBuffer.SetData(this.wallVertices);
|
||||
WallBuffer = Append(WallBuffer, ref wallVertices, newWallVertices, VertexPositionColorTexture.VertexDeclaration);
|
||||
WallEdgeBuffer = Append(WallEdgeBuffer, ref wallEdgeVertices, newWallEdgeVertices, VertexPositionColorTexture.VertexDeclaration);
|
||||
WallInnerBuffer = Append(WallInnerBuffer, ref wallInnerVertices, newWallInnerVertices, VertexPositionColor.VertexDeclaration);
|
||||
|
||||
WallEdgeBuffer.Dispose();
|
||||
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallEdgeVertices.Length + wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||
int originalWallEdgeVertexCount = this.wallEdgeVertices.Length;
|
||||
Array.Resize(ref this.wallEdgeVertices, originalWallEdgeVertexCount + wallEdgeVertices.Length);
|
||||
Array.Copy(LevelRenderer.GetColoredVertices(wallEdgeVertices, color), 0, this.wallEdgeVertices, originalWallEdgeVertexCount, wallEdgeVertices.Length);
|
||||
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||
static VertexBuffer Append<T>(VertexBuffer buffer, ref T[] currentVertices, T[] newVertices, VertexDeclaration vertexDeclaration) where T : struct, IVertexType
|
||||
{
|
||||
buffer?.Dispose();
|
||||
int originalVertexCount = currentVertices.Length;
|
||||
int newBufferSize = originalVertexCount + newVertices.Length;
|
||||
buffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, vertexDeclaration, newBufferSize, BufferUsage.WriteOnly);
|
||||
Array.Resize(ref currentVertices, newBufferSize);
|
||||
Array.Copy(newVertices, 0, currentVertices, originalVertexCount, newVertices.Length);
|
||||
buffer.SetData(currentVertices);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -70,7 +94,7 @@ namespace Barotrauma
|
||||
|
||||
class LevelRenderer : IDisposable
|
||||
{
|
||||
private static BasicEffect wallEdgeEffect, wallCenterEffect;
|
||||
private static BasicEffect wallEdgeEffect, wallCenterEffect, wallInnerEffect;
|
||||
|
||||
private Vector2 waterParticleOffset;
|
||||
private Vector2 waterParticleVelocity;
|
||||
@@ -129,7 +153,16 @@ namespace Barotrauma
|
||||
};
|
||||
wallCenterEffect.CurrentTechnique = wallCenterEffect.Techniques["BasicEffect_Texture"];
|
||||
}
|
||||
|
||||
|
||||
if (wallInnerEffect == null)
|
||||
{
|
||||
wallInnerEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
VertexColorEnabled = true,
|
||||
TextureEnabled = false
|
||||
};
|
||||
wallInnerEffect.CurrentTechnique = wallInnerEffect.Techniques["BasicEffect_Texture"];
|
||||
}
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@@ -184,7 +217,7 @@ namespace Barotrauma
|
||||
//calculate the sum of the forces of nearby level triggers
|
||||
//and use it to move the water texture and water distortion effect
|
||||
Vector2 currentWaterParticleVel = level.GenerationParams.WaterParticleVelocity;
|
||||
foreach (LevelObject levelObject in level.LevelObjectManager.GetVisibleObjects())
|
||||
foreach (LevelObject levelObject in level.LevelObjectManager.GetAllVisibleObjects())
|
||||
{
|
||||
if (levelObject.Triggers == null) { continue; }
|
||||
//use the largest water flow velocity of all the triggers
|
||||
@@ -225,16 +258,16 @@ namespace Barotrauma
|
||||
return verts;
|
||||
}
|
||||
|
||||
public void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public void SetVertices(VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices, VertexPositionColor[] wallInnerVertices, Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
var existingBuffer = vertexBuffers.Find(vb => vb.WallTexture == wallTexture && vb.EdgeTexture == edgeTexture);
|
||||
if (existingBuffer != null)
|
||||
{
|
||||
existingBuffer.Append(wallVertices, wallEdgeVertices,color);
|
||||
existingBuffer.Append(wallVertices, wallEdgeVertices, wallInnerVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexBuffers.Add(new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color));
|
||||
vertexBuffers.Add(new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallInnerVertices, wallTexture, edgeTexture));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,15 +530,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
wallEdgeEffect.Alpha = 1.0f;
|
||||
wallCenterEffect.Alpha = 1.0f;
|
||||
|
||||
wallCenterEffect.World = transformMatrix;
|
||||
wallEdgeEffect.World = transformMatrix;
|
||||
wallEdgeEffect.Alpha = wallInnerEffect.Alpha = wallCenterEffect.Alpha = 1.0f;
|
||||
wallCenterEffect.World = wallInnerEffect.World = wallEdgeEffect.World = transformMatrix;
|
||||
|
||||
//render static walls
|
||||
foreach (var vertexBuffer in vertexBuffers)
|
||||
{
|
||||
wallInnerEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphicsDevice.SetVertexBuffer(vertexBuffer.WallInnerBuffer);
|
||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(vertexBuffer.WallInnerBuffer.VertexCount / 3.0f));
|
||||
|
||||
wallCenterEffect.Texture = vertexBuffer.WallTexture;
|
||||
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphicsDevice.SetVertexBuffer(vertexBuffer.WallBuffer);
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -26,22 +23,29 @@ namespace Barotrauma
|
||||
Matrix.CreateTranslation(new Vector3(ConvertUnits.ToDisplayUnits(Body.Position), 0.0f));
|
||||
}
|
||||
|
||||
public void SetWallVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public void SetWallVertices(
|
||||
VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices,
|
||||
Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
if (VertexBuffer != null && !VertexBuffer.IsDisposed) { VertexBuffer.Dispose(); }
|
||||
VertexBuffer = new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color);
|
||||
VertexBuffer = new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallInnerVertices: null, wallTexture, edgeTexture);
|
||||
}
|
||||
|
||||
public void GenerateVertices()
|
||||
{
|
||||
float zCoord = this is DestructibleLevelWall ? Rand.Range(0.9f, 1.0f) : 0.9f;
|
||||
List<VertexPositionTexture> wallVertices = CaveGenerator.GenerateWallVertices(triangles, level.GenerationParams, zCoord);
|
||||
var nonTexturedWallVerts =
|
||||
CaveGenerator.GenerateWallVertices(triangles, color, zCoord: 0.9f).ToArray();
|
||||
var wallVerts = CaveGenerator.ConvertToTextured(nonTexturedWallVerts, level.GenerationParams.WallTextureSize);
|
||||
SetWallVertices(
|
||||
wallVertices.ToArray(),
|
||||
CaveGenerator.GenerateWallEdgeVertices(Cells, level, zCoord).ToArray(),
|
||||
wallVertices: wallVerts,
|
||||
wallEdgeVertices: CaveGenerator.GenerateWallEdgeVertices(Cells,
|
||||
level.GenerationParams.WallEdgeExpandOutwardsAmount, level.GenerationParams.WallEdgeExpandInwardsAmount,
|
||||
outerColor: color, innerColor: color,
|
||||
level, zCoord)
|
||||
.ToArray(),
|
||||
level.GenerationParams.WallSprite.Texture,
|
||||
level.GenerationParams.WallEdgeSprite.Texture,
|
||||
color);
|
||||
level.GenerationParams.WallEdgeSprite.Texture);
|
||||
}
|
||||
|
||||
public bool IsVisible(Rectangle worldView)
|
||||
|
||||
@@ -443,10 +443,10 @@ namespace Barotrauma.Lights
|
||||
|
||||
public bool Intersects(Rectangle rect)
|
||||
{
|
||||
if (!Enabled) return false;
|
||||
if (!Enabled) { return false; }
|
||||
|
||||
Rectangle transformedBounds = BoundingBox;
|
||||
if (ParentEntity != null && ParentEntity.Submarine != null)
|
||||
if (ParentEntity is { Submarine: not null })
|
||||
{
|
||||
transformedBounds.X += (int)ParentEntity.Submarine.Position.X;
|
||||
transformedBounds.Y += (int)ParentEntity.Submarine.Position.Y;
|
||||
|
||||
@@ -243,6 +243,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="backgroundObstructor">A render target that contains the structures that should obstruct lights in the background. If not given, damageable walls and hulls are rendered to obstruct the background lights.</param>
|
||||
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
||||
{
|
||||
if (!LightingEnabled) { return; }
|
||||
@@ -411,11 +412,21 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
|
||||
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
|
||||
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.End();
|
||||
if (backgroundObstructor != null)
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: Matrix.Identity, effect: GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
||||
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
||||
spriteBatch.End();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
|
||||
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
|
||||
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
graphics.BlendState = BlendState.Additive;
|
||||
|
||||
@@ -680,11 +691,14 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
return visibleHulls;
|
||||
}
|
||||
|
||||
private static readonly List<VertexPositionColor> ShadowVertices = new List<VertexPositionColor>(500);
|
||||
private static readonly List<VertexPositionTexture> PenumbraVertices = new List<VertexPositionTexture>(500);
|
||||
|
||||
public void UpdateObstructVision(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Vector2 lookAtPosition)
|
||||
{
|
||||
if ((!LosEnabled || LosMode == LosMode.None) && ObstructVisionAmount <= 0.0f) { return; }
|
||||
if (ViewTarget == null) return;
|
||||
if (ViewTarget == null) { return; }
|
||||
|
||||
graphics.SetRenderTarget(LosTexture);
|
||||
|
||||
@@ -767,11 +781,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (convexHulls != null)
|
||||
{
|
||||
List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>();
|
||||
List<VertexPositionTexture> penumbraVerts = new List<VertexPositionTexture>();
|
||||
ShadowVertices.Clear();
|
||||
PenumbraVertices.Clear();
|
||||
foreach (ConvexHull convexHull in convexHulls)
|
||||
{
|
||||
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
|
||||
if (!convexHull.Intersects(camView)) { continue; }
|
||||
|
||||
Vector2 relativeViewPos = pos;
|
||||
if (convexHull.ParentEntity?.Submarine != null)
|
||||
@@ -783,26 +797,26 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 0; i < convexHull.ShadowVertexCount; i++)
|
||||
{
|
||||
shadowVerts.Add(convexHull.ShadowVertices[i]);
|
||||
ShadowVertices.Add(convexHull.ShadowVertices[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < convexHull.PenumbraVertexCount; i++)
|
||||
{
|
||||
penumbraVerts.Add(convexHull.PenumbraVertices[i]);
|
||||
PenumbraVertices.Add(convexHull.PenumbraVertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowVerts.Count > 0)
|
||||
if (ShadowVertices.Count > 0)
|
||||
{
|
||||
ConvexHull.shadowEffect.World = shadowTransform;
|
||||
ConvexHull.shadowEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, shadowVerts.ToArray(), 0, shadowVerts.Count / 3, VertexPositionColor.VertexDeclaration);
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, ShadowVertices.ToArray(), 0, ShadowVertices.Count / 3, VertexPositionColor.VertexDeclaration);
|
||||
|
||||
if (penumbraVerts.Count > 0)
|
||||
if (PenumbraVertices.Count > 0)
|
||||
{
|
||||
ConvexHull.penumbraEffect.World = shadowTransform;
|
||||
ConvexHull.penumbraEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, penumbraVerts.ToArray(), 0, penumbraVerts.Count / 3, VertexPositionTexture.VertexDeclaration);
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, PenumbraVertices.ToArray(), 0, PenumbraVertices.Count / 3, VertexPositionTexture.VertexDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,7 +592,17 @@ namespace Barotrauma.Lights
|
||||
private void CheckHullsInRange(Submarine sub)
|
||||
{
|
||||
//find the list of convexhulls that belong to the sub
|
||||
ConvexHullList chList = convexHullsInRange.FirstOrDefault(chList => chList.Submarine == sub);
|
||||
|
||||
// Performance-sensitive code, hence implemented without Linq.
|
||||
ConvexHullList chList = null;
|
||||
foreach (var chl in convexHullsInRange)
|
||||
{
|
||||
if (chl.Submarine == sub)
|
||||
{
|
||||
chList = chl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//not found -> create one
|
||||
if (chList == null)
|
||||
|
||||
@@ -451,7 +451,7 @@ namespace Barotrauma
|
||||
MathUtils.PositiveModulo(-textureOffset.X, Prefab.BackgroundSprite.SourceRect.Width * TextureScale.X * Scale),
|
||||
MathUtils.PositiveModulo(-textureOffset.Y, Prefab.BackgroundSprite.SourceRect.Height * TextureScale.Y * Scale));
|
||||
|
||||
float rotationRad = rotationForSprite(this.rotationRad, Prefab.BackgroundSprite);
|
||||
float rotationRad = GetRotationForSprite(this.rotationRad, Prefab.BackgroundSprite);
|
||||
|
||||
Prefab.BackgroundSprite.DrawTiled(
|
||||
spriteBatch,
|
||||
@@ -492,7 +492,7 @@ namespace Barotrauma
|
||||
advanceY = advanceY.FlipX();
|
||||
}
|
||||
|
||||
float sectionSpriteRotationRad = rotationForSprite(this.rotationRad, Prefab.Sprite);
|
||||
float sectionSpriteRotationRad = GetRotationForSprite(this.rotationRad, Prefab.Sprite);
|
||||
|
||||
for (int i = 0; i < Sections.Length; i++)
|
||||
{
|
||||
@@ -501,11 +501,17 @@ namespace Barotrauma
|
||||
{
|
||||
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / MaxHealth);
|
||||
|
||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
|
||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.05f)
|
||||
{
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
BlendState.NonPremultiplied, SamplerState.LinearWrap,
|
||||
null, null,
|
||||
damageEffect,
|
||||
Screen.Selected.Cam.Transform);
|
||||
|
||||
damageEffect.Parameters["aCutoff"].SetValue(newCutoff);
|
||||
damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f);
|
||||
damageEffect.Parameters["inColor"].SetValue(color.ToVector4());
|
||||
|
||||
damageEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
@@ -570,9 +576,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
static float rotationForSprite(float rotationRad, Sprite sprite)
|
||||
static float GetRotationForSprite(float rotationRad, Sprite sprite)
|
||||
{
|
||||
if (sprite.effects.HasFlag(SpriteEffects.FlipHorizontally) != sprite.effects.HasFlag(SpriteEffects.FlipVertically))
|
||||
// Use bitwise operations instead of HasFlag to avoid boxing, as this is performance-sensitive code.
|
||||
bool flipHorizontally = (sprite.effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;
|
||||
bool flipVertically = (sprite.effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
|
||||
|
||||
if (flipHorizontally != flipVertically)
|
||||
{
|
||||
rotationRad = -rotationRad;
|
||||
}
|
||||
@@ -604,6 +614,10 @@ namespace Barotrauma
|
||||
if (GetSection(i).damage > 0)
|
||||
{
|
||||
var textPos = SectionPosition(i, true);
|
||||
if (Submarine != null)
|
||||
{
|
||||
textPos += (Submarine.DrawPosition - Submarine.Position);
|
||||
}
|
||||
textPos.Y = -textPos.Y;
|
||||
GUI.DrawString(spriteBatch, textPos, "Damage: " + (int)((GetSection(i).damage / MaxHealth) * 100f) + "%", Color.Yellow);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Barotrauma
|
||||
foreach (Submarine sub in Loaded)
|
||||
{
|
||||
Rectangle worldBorders = sub.Borders;
|
||||
worldBorders.Location += sub.WorldPosition.ToPoint();
|
||||
worldBorders.Location += (sub.DrawPosition + sub.HiddenSubPosition).ToPoint();
|
||||
worldBorders.Y = -worldBorders.Y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5);
|
||||
@@ -161,38 +161,38 @@ namespace Barotrauma
|
||||
public static float DamageEffectCutoff;
|
||||
public static Color DamageEffectColor;
|
||||
|
||||
private static readonly List<Structure> depthSortedDamageable = new List<Structure>();
|
||||
public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false, Predicate<MapEntity> predicate = null)
|
||||
{
|
||||
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.MapEntityList;
|
||||
|
||||
depthSortedDamageable.Clear();
|
||||
|
||||
//insertion sort according to draw depth
|
||||
foreach (MapEntity e in entitiesToRender)
|
||||
if (!editing && visibleEntities != null)
|
||||
{
|
||||
if (e is Structure structure && structure.DrawDamageEffect)
|
||||
foreach (MapEntity e in visibleEntities)
|
||||
{
|
||||
if (predicate != null)
|
||||
if (e is Structure structure && structure.DrawDamageEffect)
|
||||
{
|
||||
if (!predicate(e)) { continue; }
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(structure)) { continue; }
|
||||
}
|
||||
structure.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
float drawDepth = structure.GetDrawDepth();
|
||||
int i = 0;
|
||||
while (i < depthSortedDamageable.Count)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Structure structure in Structure.WallList)
|
||||
{
|
||||
if (structure.DrawDamageEffect)
|
||||
{
|
||||
float otherDrawDepth = depthSortedDamageable[i].GetDrawDepth();
|
||||
if (otherDrawDepth < drawDepth) { break; }
|
||||
i++;
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(structure)) { continue; }
|
||||
}
|
||||
structure.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
depthSortedDamageable.Insert(i, structure);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Structure s in depthSortedDamageable)
|
||||
{
|
||||
s.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
|
||||
if (damageEffect != null)
|
||||
{
|
||||
damageEffect.Parameters["aCutoff"].SetValue(0.0f);
|
||||
@@ -506,6 +506,16 @@ namespace Barotrauma
|
||||
warnings.Add(SubEditorScreen.WarningType.WaterInHulls);
|
||||
Hull.ShowHulls = true;
|
||||
}
|
||||
|
||||
if (Info.IsWreck)
|
||||
{
|
||||
Point vanillaBrainSize = new Point(204, 204);
|
||||
if (WreckAI.GetPotentialBrainRooms(this, WreckAIConfig.GetRandom(), minSize: vanillaBrainSize).None())
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoSuitableBrainRoomsWarning").Value);
|
||||
warnings.Add(SubEditorScreen.WarningType.NoSuitableBrainRooms);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NotEnoughContainers))
|
||||
{
|
||||
|
||||
@@ -46,6 +46,10 @@ namespace Barotrauma
|
||||
}
|
||||
if (IsHighlighted || IsHighlighted) { clr = Color.Lerp(clr, Color.White, 0.8f); }
|
||||
|
||||
if (Stairs is { Removed: true }) { Stairs = null; }
|
||||
if (Ladders is { Item.Removed: true }) { Ladders = null; }
|
||||
if (ConnectedGap is { Removed: true }) { ConnectedGap = null; }
|
||||
|
||||
int iconSize = spawnType == SpawnType.Path ? WaypointSize : SpawnPointSize;
|
||||
if (ConnectedDoor != null || Ladders != null || Stairs != null || SpawnType != SpawnType.Path)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user