Merge branch 'level-mirroring'
This commit is contained in:
@@ -28,9 +28,16 @@ namespace Barotrauma
|
|||||||
color = Color.LightGray;
|
color = Color.LightGray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (RuinGeneration.Ruin ruin in ruins)
|
||||||
|
{
|
||||||
|
Rectangle ruinArea = ruin.Area;
|
||||||
|
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch, ruinArea, Color.DarkSlateBlue, false, 0, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -766,7 +766,10 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
||||||
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level, true, false);
|
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level,
|
||||||
|
reloadSub: true,
|
||||||
|
loadSecondSub: false,
|
||||||
|
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||||
|
|||||||
@@ -192,7 +192,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private IEnumerable<object> LoadRound()
|
private IEnumerable<object> LoadRound()
|
||||||
{
|
{
|
||||||
GameMain.GameSession.StartRound(campaignUI.SelectedLevel, true);
|
GameMain.GameSession.StartRound(campaignUI.SelectedLevel,
|
||||||
|
reloadSub: true,
|
||||||
|
loadSecondSub: false,
|
||||||
|
mirrorLevel: GameMain.GameSession.Map.CurrentLocation != GameMain.GameSession.Map.SelectedConnection.Locations[0]);
|
||||||
GameMain.GameScreen.Select();
|
GameMain.GameScreen.Select();
|
||||||
|
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
|||||||
StartRound(randomLevel, true, loadSecondSub);
|
StartRound(randomLevel, true, loadSecondSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false)
|
public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false, bool mirrorLevel = false)
|
||||||
{
|
{
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||||
@@ -213,8 +213,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (level != null)
|
if (level != null)
|
||||||
{
|
{
|
||||||
level.Generate();
|
level.Generate(mirrorLevel);
|
||||||
|
|
||||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,9 +228,9 @@ namespace Barotrauma
|
|||||||
if (GameMode != null)
|
if (GameMode != null)
|
||||||
{
|
{
|
||||||
GameMode.MsgBox();
|
GameMode.MsgBox();
|
||||||
if (GameMode is MultiPlayerCampaign campaign && GameMain.Server != null)
|
if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.Server != null)
|
||||||
{
|
{
|
||||||
campaign.CargoManager.CreateItems();
|
mpCampaign.CargoManager.CreateItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,9 +136,8 @@ namespace Barotrauma
|
|||||||
for (int i = 0 ; i < amount; i++)
|
for (int i = 0 ; i < amount; i++)
|
||||||
{
|
{
|
||||||
BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
|
BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
|
||||||
GraphEdge selectedEdge = null;
|
|
||||||
Vector2 edgeNormal = Vector2.One;
|
Vector2 edgeNormal = Vector2.One;
|
||||||
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);
|
Vector2? pos = FindSpritePosition(level, prefab, out GraphEdge selectedEdge, out edgeNormal);
|
||||||
|
|
||||||
if (pos == null) continue;
|
if (pos == null) continue;
|
||||||
|
|
||||||
@@ -148,7 +147,8 @@ namespace Barotrauma
|
|||||||
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
|
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
|
||||||
}
|
}
|
||||||
|
|
||||||
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, Rand.RandSync.Server);
|
float randomRot = Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, Rand.RandSync.Server);
|
||||||
|
rotation += level.Mirrored ? -randomRot : randomRot;
|
||||||
|
|
||||||
var newSprite = new BackgroundSprite(prefab,
|
var newSprite = new BackgroundSprite(prefab,
|
||||||
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, Rand.RandSync.Server), rotation);
|
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, Rand.RandSync.Server), rotation);
|
||||||
@@ -231,6 +231,8 @@ namespace Barotrauma
|
|||||||
Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server),
|
Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server),
|
||||||
Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server));
|
Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server));
|
||||||
|
|
||||||
|
if (level.Mirrored) randomPos.X = level.Size.X - randomPos.X;
|
||||||
|
|
||||||
if (prefab.SpawnPos == BackgroundSpritePrefab.SpawnPosType.None) return randomPos;
|
if (prefab.SpawnPos == BackgroundSpritePrefab.SpawnPosType.None) return randomPos;
|
||||||
|
|
||||||
List<GraphEdge> edges = new List<GraphEdge>();
|
List<GraphEdge> edges = new List<GraphEdge>();
|
||||||
@@ -242,6 +244,9 @@ namespace Barotrauma
|
|||||||
if (prefab.SpawnPos.HasFlag(BackgroundSpritePrefab.SpawnPosType.Wall)) cells.AddRange(level.GetCells(randomPos));
|
if (prefab.SpawnPos.HasFlag(BackgroundSpritePrefab.SpawnPosType.Wall)) cells.AddRange(level.GetCells(randomPos));
|
||||||
if (prefab.SpawnPos.HasFlag(BackgroundSpritePrefab.SpawnPosType.SeaFloor)) cells.AddRange(level.ExtraWalls[0].Cells);
|
if (prefab.SpawnPos.HasFlag(BackgroundSpritePrefab.SpawnPosType.SeaFloor)) cells.AddRange(level.ExtraWalls[0].Cells);
|
||||||
|
|
||||||
|
//make sure the cells are in the same order regardless of whether the level is mirrored or not
|
||||||
|
cells.Sort((c1, c2) => { return level.Mirrored ? Math.Sign(c1.Center.X - c2.Center.X) : -Math.Sign(c1.Center.X - c2.Center.X); });
|
||||||
|
|
||||||
if (cells.Any())
|
if (cells.Any())
|
||||||
{
|
{
|
||||||
VoronoiCell cell = cells[Rand.Int(cells.Count, Rand.RandSync.Server)];
|
VoronoiCell cell = cells[Rand.Int(cells.Count, Rand.RandSync.Server)];
|
||||||
@@ -305,10 +310,12 @@ namespace Barotrauma
|
|||||||
edgeNormal = normals[index];
|
edgeNormal = normals[index];
|
||||||
|
|
||||||
float length = Vector2.Distance(closestEdge.point1, closestEdge.point2);
|
float length = Vector2.Distance(closestEdge.point1, closestEdge.point2);
|
||||||
Vector2 dir = (closestEdge.point1 - closestEdge.point2) / length;
|
|
||||||
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, Rand.RandSync.Server);
|
|
||||||
|
|
||||||
return pos;
|
Vector2 dir = (closestEdge.point1 - closestEdge.point2) / length;
|
||||||
|
float normalizedPos = Rand.Range(0.0f, 1.0f, Rand.RandSync.Server);
|
||||||
|
if (level.Mirrored) normalizedPos = 1.0f - normalizedPos;
|
||||||
|
|
||||||
|
return Vector2.Lerp(closestEdge.point2 + dir * prefab.Sprite.size.X / 2.0f, closestEdge.point1 - dir * prefab.Sprite.size.X / 2.0f, normalizedPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ namespace Barotrauma
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum PositionType
|
public enum PositionType
|
||||||
{
|
{
|
||||||
MainPath=1, Cave=2, Ruin=4
|
MainPath = 1, Cave = 2, Ruin = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InterestingPosition
|
struct InterestingPosition
|
||||||
{
|
{
|
||||||
public readonly Vector2 Position;
|
public Vector2 Position;
|
||||||
public readonly PositionType PositionType;
|
public readonly PositionType PositionType;
|
||||||
|
|
||||||
public InterestingPosition(Vector2 position, PositionType positionType)
|
public InterestingPosition(Vector2 position, PositionType positionType)
|
||||||
@@ -55,7 +55,8 @@ namespace Barotrauma
|
|||||||
//private float shaftHeight;
|
//private float shaftHeight;
|
||||||
|
|
||||||
//List<Body> bodies;
|
//List<Body> bodies;
|
||||||
private List<VoronoiCell> cells;
|
//TODO: change back to private
|
||||||
|
public List<VoronoiCell> cells;
|
||||||
|
|
||||||
//private VertexBuffer vertexBuffer;
|
//private VertexBuffer vertexBuffer;
|
||||||
|
|
||||||
@@ -145,7 +146,11 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Mirrored
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public LevelGenerationParams GenerationParams
|
public LevelGenerationParams GenerationParams
|
||||||
{
|
{
|
||||||
@@ -170,7 +175,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
this.generationParams = generationParams;
|
this.generationParams = generationParams;
|
||||||
|
|
||||||
borders = new Rectangle(0, 0, (int)generationParams.Width, (int)generationParams.Height);
|
borders = new Rectangle(0, 0,
|
||||||
|
(int)(Math.Ceiling(generationParams.Width / GridCellSize) * GridCellSize),
|
||||||
|
(int)(Math.Ceiling(generationParams.Height / GridCellSize) * GridCellSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Level CreateRandom(LocationConnection locationConnection)
|
public static Level CreateRandom(LocationConnection locationConnection)
|
||||||
@@ -192,8 +199,10 @@ namespace Barotrauma
|
|||||||
return new Level(seed, Rand.Range(30.0f, 80.0f, Rand.RandSync.Server), LevelGenerationParams.GetRandom(seed));
|
return new Level(seed, Rand.Range(30.0f, 80.0f, Rand.RandSync.Server), LevelGenerationParams.GetRandom(seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Generate(bool mirror = false)
|
public void Generate(bool mirror)
|
||||||
{
|
{
|
||||||
|
Mirrored = mirror;
|
||||||
|
|
||||||
if (backgroundSpriteManager == null)
|
if (backgroundSpriteManager == null)
|
||||||
{
|
{
|
||||||
var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundSpritePrefabs);
|
var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundSpritePrefabs);
|
||||||
@@ -304,8 +313,6 @@ namespace Barotrauma
|
|||||||
if (x < borders.Width - siteInterval.X && y < borders.Height - siteInterval.Y) sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f);
|
if (x < borders.Width - siteInterval.X && y < borders.Height - siteInterval.Y) sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mirror) site.X = borders.Width - site.X;
|
|
||||||
|
|
||||||
sites.Add(site);
|
sites.Add(site);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +341,7 @@ namespace Barotrauma
|
|||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
List<VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize,
|
List<VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize,
|
||||||
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.5f, mirror);
|
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.5f, false);
|
||||||
|
|
||||||
for (int i = 2; i < mainPath.Count; i += 3)
|
for (int i = 2; i < mainPath.Count; i += 3)
|
||||||
{
|
{
|
||||||
@@ -348,8 +355,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (InterestingPosition positionOfInterest in positionsOfInterest)
|
foreach (InterestingPosition positionOfInterest in positionsOfInterest)
|
||||||
{
|
{
|
||||||
WayPoint wayPoint = new WayPoint(positionOfInterest.Position, SpawnType.Enemy, null);
|
WayPoint wayPoint = new WayPoint(
|
||||||
wayPoint.MoveWithLevel = true;
|
mirror ? new Vector2(borders.X - positionOfInterest.Position.X, positionOfInterest.Position.Y) : positionOfInterest.Position,
|
||||||
|
SpawnType.Enemy,
|
||||||
|
submarine: null)
|
||||||
|
{
|
||||||
|
MoveWithLevel = true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
startPosition.X = pathCells[0].Center.X;
|
startPosition.X = pathCells[0].Center.X;
|
||||||
@@ -378,7 +390,6 @@ namespace Barotrauma
|
|||||||
pathCells.AddRange(newPathCells);
|
pathCells.AddRange(newPathCells);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine("path: " + sw2.ElapsedMilliseconds + " ms");
|
|
||||||
sw2.Restart();
|
sw2.Restart();
|
||||||
|
|
||||||
|
|
||||||
@@ -417,6 +428,62 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// mirror if needed
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if (mirror)
|
||||||
|
{
|
||||||
|
HashSet<GraphEdge> mirroredEdges = new HashSet<GraphEdge>();
|
||||||
|
HashSet<Site> mirroredSites = new HashSet<Site>();
|
||||||
|
List<VoronoiCell> allCells = new List<VoronoiCell>(cells);
|
||||||
|
allCells.AddRange(pathCells);
|
||||||
|
foreach (VoronoiCell cell in allCells)
|
||||||
|
{
|
||||||
|
foreach (GraphEdge edge in cell.edges)
|
||||||
|
{
|
||||||
|
if (mirroredEdges.Contains(edge)) continue;
|
||||||
|
edge.point1.X = borders.Width - edge.point1.X;
|
||||||
|
edge.point2.X = borders.Width - edge.point2.X;
|
||||||
|
if (!mirroredSites.Contains(edge.site1))
|
||||||
|
{
|
||||||
|
//make sure that sites right at the edge of a grid cell end up in the same cell as in the non-mirrored level
|
||||||
|
if (edge.site1.coord.x % GridCellSize < 1.0f &&
|
||||||
|
edge.site1.coord.x % GridCellSize >= 0.0f) edge.site1.coord.x += 1.0f;
|
||||||
|
edge.site1.coord.x = borders.Width - edge.site1.coord.x;
|
||||||
|
mirroredSites.Add(edge.site1);
|
||||||
|
}
|
||||||
|
if (!mirroredSites.Contains(edge.site2))
|
||||||
|
{
|
||||||
|
if (edge.site2.coord.x % GridCellSize < 1.0f &&
|
||||||
|
edge.site2.coord.x % GridCellSize >= 0.0f) edge.site2.coord.x += 1.0f;
|
||||||
|
edge.site2.coord.x = borders.Width - edge.site2.coord.x;
|
||||||
|
mirroredSites.Add(edge.site2);
|
||||||
|
}
|
||||||
|
mirroredEdges.Add(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (List<Vector2> smallTunnel in smallTunnels)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < smallTunnel.Count; i++)
|
||||||
|
{
|
||||||
|
smallTunnel[i] = new Vector2(borders.Width - smallTunnel[i].X, smallTunnel[i].Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < positionsOfInterest.Count; i++)
|
||||||
|
{
|
||||||
|
positionsOfInterest[i] = new InterestingPosition(
|
||||||
|
new Vector2(borders.Width - positionsOfInterest[i].Position.X, positionsOfInterest[i].Position.Y),
|
||||||
|
positionsOfInterest[i].PositionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
startPosition.X = borders.Width - startPosition.X;
|
||||||
|
endPosition.X = borders.Width - endPosition.X;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (VoronoiCell cell in cells)
|
foreach (VoronoiCell cell in cells)
|
||||||
{
|
{
|
||||||
int x = (int)Math.Floor(cell.Center.X / GridCellSize);
|
int x = (int)Math.Floor(cell.Center.X / GridCellSize);
|
||||||
@@ -435,10 +502,9 @@ namespace Barotrauma
|
|||||||
ruins = new List<Ruin>();
|
ruins = new List<Ruin>();
|
||||||
for (int i = 0; i < generationParams.RuinCount; i++)
|
for (int i = 0; i < generationParams.RuinCount; i++)
|
||||||
{
|
{
|
||||||
GenerateRuin(mainPath);
|
GenerateRuin(mainPath, mirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// generate the bodies and rendered triangles of the cells
|
// generate the bodies and rendered triangles of the cells
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@@ -466,7 +532,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bodies.Add(TopBarrier);
|
bodies.Add(TopBarrier);
|
||||||
|
|
||||||
GenerateSeaFloor();
|
GenerateSeaFloor(mirror);
|
||||||
|
|
||||||
backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount);
|
backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount);
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
@@ -665,7 +731,7 @@ namespace Barotrauma
|
|||||||
return newCells;
|
return newCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateSeaFloor()
|
private void GenerateSeaFloor(bool mirror)
|
||||||
{
|
{
|
||||||
BottomPos = generationParams.SeaFloorDepth;
|
BottomPos = generationParams.SeaFloorDepth;
|
||||||
SeaFloorTopPos = BottomPos;
|
SeaFloorTopPos = BottomPos;
|
||||||
@@ -688,7 +754,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < bottomPositions.Count - 1; i++)
|
for (int i = 0; i < bottomPositions.Count - 1; i++)
|
||||||
{
|
{
|
||||||
bottomPositions.Insert(i+1,
|
bottomPositions.Insert(i + 1,
|
||||||
(bottomPositions[i] + bottomPositions[i + 1]) / 2.0f +
|
(bottomPositions[i] + bottomPositions[i + 1]) / 2.0f +
|
||||||
Vector2.UnitY * Rand.Range(0.0f, generationParams.SeaFloorVariance, Rand.RandSync.Server));
|
Vector2.UnitY * Rand.Range(0.0f, generationParams.SeaFloorVariance, Rand.RandSync.Server));
|
||||||
|
|
||||||
@@ -698,6 +764,14 @@ namespace Barotrauma
|
|||||||
currInverval /= 2.0f;
|
currInverval /= 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mirror)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bottomPositions.Count; i++)
|
||||||
|
{
|
||||||
|
bottomPositions[i] = new Vector2(borders.Size.X - bottomPositions[i].X, bottomPositions[i].Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SeaFloorTopPos = bottomPositions.Max(p => p.Y);
|
SeaFloorTopPos = bottomPositions.Max(p => p.Y);
|
||||||
|
|
||||||
extraWalls = new LevelWall[] { new LevelWall(bottomPositions, new Vector2(0.0f, -2000.0f), backgroundColor, this) };
|
extraWalls = new LevelWall[] { new LevelWall(bottomPositions, new Vector2(0.0f, -2000.0f), backgroundColor, this) };
|
||||||
@@ -809,12 +883,13 @@ namespace Barotrauma
|
|||||||
return tunnelNodes;
|
return tunnelNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateRuin(List<VoronoiCell> mainPath)
|
private void GenerateRuin(List<VoronoiCell> mainPath, bool mirror)
|
||||||
{
|
{
|
||||||
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server), Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server));
|
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server), Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server));
|
||||||
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
|
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
|
||||||
|
|
||||||
Vector2 ruinPos = cells[Rand.Int(cells.Count, Rand.RandSync.Server)].Center;
|
int cellIndex = Rand.Int(cells.Count, Rand.RandSync.Server);
|
||||||
|
Vector2 ruinPos = cells[cellIndex].Center;
|
||||||
|
|
||||||
//50% chance of placing the ruins at a cave
|
//50% chance of placing the ruins at a cave
|
||||||
if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.5f)
|
if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.5f)
|
||||||
@@ -825,25 +900,33 @@ namespace Barotrauma
|
|||||||
ruinPos.Y = Math.Min(ruinPos.Y, borders.Y + borders.Height - ruinSize.Y / 2);
|
ruinPos.Y = Math.Min(ruinPos.Y, borders.Y + borders.Height - ruinSize.Y / 2);
|
||||||
ruinPos.Y = Math.Max(ruinPos.Y, SeaFloorTopPos + ruinSize.Y / 2.0f);
|
ruinPos.Y = Math.Max(ruinPos.Y, SeaFloorTopPos + ruinSize.Y / 2.0f);
|
||||||
|
|
||||||
|
float minDist = ruinRadius * 2.0f;
|
||||||
|
float minDistSqr = minDist * minDist;
|
||||||
|
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius * 2.0f))
|
while (mainPath.Any(p => Vector2.DistanceSquared(ruinPos, p.Center) < minDistSqr))
|
||||||
{
|
{
|
||||||
Vector2 weighedPathPos = ruinPos;
|
Vector2 weighedPathPos = ruinPos;
|
||||||
iter++;
|
iter++;
|
||||||
|
|
||||||
foreach (VoronoiCell pathCell in mainPath)
|
foreach (VoronoiCell pathCell in mainPath)
|
||||||
{
|
{
|
||||||
float dist = Vector2.Distance(pathCell.Center, ruinPos);
|
Vector2 diff = ruinPos - pathCell.Center;
|
||||||
if (dist > 10000.0f) continue;
|
float distSqr = diff.LengthSquared();
|
||||||
|
if (distSqr < 1.0f)
|
||||||
|
{
|
||||||
|
diff = Vector2.UnitY;
|
||||||
|
distSqr = 1.0f;
|
||||||
|
}
|
||||||
|
if (distSqr > 10000.0f * 10000.0f) continue;
|
||||||
|
|
||||||
Vector2 moveAmount = Vector2.Normalize(ruinPos - pathCell.Center) * 100000.0f / dist;
|
Vector2 moveAmount = Vector2.Normalize(diff) * 100000.0f / (float)Math.Sqrt(distSqr);
|
||||||
|
|
||||||
weighedPathPos += moveAmount;
|
weighedPathPos += moveAmount;
|
||||||
weighedPathPos.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y / 2, weighedPathPos.Y);
|
weighedPathPos.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y / 2, weighedPathPos.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ruinPos = weighedPathPos;
|
ruinPos = weighedPathPos;
|
||||||
|
|
||||||
if (iter > 10000) break;
|
if (iter > 10000) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,7 +942,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ruin = new Ruin(closestPathCell, cells, new Rectangle(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize)));
|
var ruin = new Ruin(closestPathCell, cells, new Rectangle(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize)), mirror);
|
||||||
ruins.Add(ruin);
|
ruins.Add(ruin);
|
||||||
|
|
||||||
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
|
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
|
||||||
@@ -1011,14 +1094,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
List<VoronoiCell> cells = new List<VoronoiCell>();
|
List<VoronoiCell> cells = new List<VoronoiCell>();
|
||||||
|
|
||||||
for (int x = startX; x <= endX; x++)
|
for (int y = startY; y <= endY; y++)
|
||||||
{
|
{
|
||||||
for (int y = startY; y <= endY; y++)
|
for (int x = startX; x <= endX; x++)
|
||||||
{
|
{
|
||||||
foreach (VoronoiCell cell in cellGrid[x, y])
|
foreach (VoronoiCell cell in cellGrid[x, y]) cells.Add(cell);
|
||||||
{
|
|
||||||
cells.Add(cell);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using FarseerPhysics.Factories;
|
using FarseerPhysics.Factories;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -35,7 +36,7 @@ namespace Barotrauma.RuinGeneration
|
|||||||
|
|
||||||
public Alignment GetLineAlignment(Line line)
|
public Alignment GetLineAlignment(Line line)
|
||||||
{
|
{
|
||||||
if (line.A.Y == line.B.Y)
|
if (line.IsHorizontal)
|
||||||
{
|
{
|
||||||
if (line.A.Y > rect.Center.Y && line.B.Y > rect.Center.Y)
|
if (line.A.Y > rect.Center.Y && line.B.Y > rect.Center.Y)
|
||||||
{
|
{
|
||||||
@@ -70,7 +71,7 @@ namespace Barotrauma.RuinGeneration
|
|||||||
|
|
||||||
foreach (Line line in Walls)
|
foreach (Line line in Walls)
|
||||||
{
|
{
|
||||||
if (line.A.X == line.B.X) //vertical line
|
if (!line.IsHorizontal) //vertical line
|
||||||
{
|
{
|
||||||
//line doesn't intersect the rectangle
|
//line doesn't intersect the rectangle
|
||||||
if (rectangle.X > line.A.X || rectangle.Right < line.A.X ||
|
if (rectangle.X > line.A.X || rectangle.Right < line.A.X ||
|
||||||
@@ -100,7 +101,7 @@ namespace Barotrauma.RuinGeneration
|
|||||||
newLines.Add(new Line(new Vector2(line.A.X, rectangle.Bottom), line.B, line.Type));
|
newLines.Add(new Line(new Vector2(line.A.X, rectangle.Bottom), line.B, line.Type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (line.A.Y == line.B.Y) //horizontal line
|
else
|
||||||
{
|
{
|
||||||
//line doesn't intersect the rectangle
|
//line doesn't intersect the rectangle
|
||||||
if (rectangle.X > line.B.X || rectangle.Right < line.A.X ||
|
if (rectangle.X > line.B.X || rectangle.Right < line.A.X ||
|
||||||
@@ -130,23 +131,40 @@ namespace Barotrauma.RuinGeneration
|
|||||||
newLines.Add(new Line(new Vector2(rectangle.Right, line.A.Y), line.B, line.Type));
|
newLines.Add(new Line(new Vector2(rectangle.Right, line.A.Y), line.B, line.Type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Error in StructureGenerator.SplitLines - lines must be axis aligned");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Walls = newLines;
|
Walls = newLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MirrorX(Vector2 mirrorOrigin)
|
||||||
|
{
|
||||||
|
rect.X = (int)(mirrorOrigin.X + (mirrorOrigin.X - rect.Right));
|
||||||
|
for (int i = 0; i < Walls.Count; i++)
|
||||||
|
{
|
||||||
|
Walls[i].A = new Vector2(mirrorOrigin.X + (mirrorOrigin.X - Walls[i].A.X), Walls[i].A.Y);
|
||||||
|
Walls[i].B = new Vector2(mirrorOrigin.X + (mirrorOrigin.X - Walls[i].B.X), Walls[i].B.Y);
|
||||||
|
|
||||||
|
if (Walls[i].B.X < Walls[i].A.X)
|
||||||
|
{
|
||||||
|
var temp = Walls[i].A.X;
|
||||||
|
Walls[i].A.X = Walls[i].B.X;
|
||||||
|
Walls[i].B.X = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Line
|
class Line
|
||||||
{
|
{
|
||||||
public readonly Vector2 A, B;
|
public Vector2 A, B;
|
||||||
|
|
||||||
public readonly RuinStructureType Type;
|
public readonly RuinStructureType Type;
|
||||||
|
|
||||||
|
public bool IsHorizontal
|
||||||
|
{
|
||||||
|
get { return Math.Abs(A.Y - B.Y) < Math.Abs(A.X - B.X); }
|
||||||
|
}
|
||||||
|
|
||||||
public Line(Vector2 a, Vector2 b, RuinStructureType type)
|
public Line(Vector2 a, Vector2 b, RuinStructureType type)
|
||||||
{
|
{
|
||||||
Debug.Assert(a.X <= b.X);
|
Debug.Assert(a.X <= b.X);
|
||||||
@@ -183,7 +201,7 @@ namespace Barotrauma.RuinGeneration
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ruin(VoronoiCell closestPathCell, List<VoronoiCell> caveCells, Rectangle area)
|
public Ruin(VoronoiCell closestPathCell, List<VoronoiCell> caveCells, Rectangle area, bool mirror = false)
|
||||||
{
|
{
|
||||||
Area = area;
|
Area = area;
|
||||||
|
|
||||||
@@ -194,10 +212,10 @@ namespace Barotrauma.RuinGeneration
|
|||||||
|
|
||||||
allShapes = new List<RuinShape>();
|
allShapes = new List<RuinShape>();
|
||||||
|
|
||||||
Generate(closestPathCell, caveCells, area);
|
Generate(closestPathCell, caveCells, area, mirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Generate(VoronoiCell closestPathCell, List<VoronoiCell> caveCells, Rectangle area)
|
public void Generate(VoronoiCell closestPathCell, List<VoronoiCell> caveCells, Rectangle area, bool mirror = false)
|
||||||
{
|
{
|
||||||
corridors.Clear();
|
corridors.Clear();
|
||||||
rooms.Clear();
|
rooms.Clear();
|
||||||
@@ -243,7 +261,12 @@ namespace Barotrauma.RuinGeneration
|
|||||||
float shortestDistance = 0.0f;
|
float shortestDistance = 0.0f;
|
||||||
foreach (BTRoom leaf in rooms)
|
foreach (BTRoom leaf in rooms)
|
||||||
{
|
{
|
||||||
float distance = Vector2.Distance(leaf.Rect.Center.ToVector2(), closestPathCell.Center);
|
Vector2 leafPos = leaf.Rect.Center.ToVector2();
|
||||||
|
if (mirror)
|
||||||
|
{
|
||||||
|
leafPos.X = area.Center.X + (area.Center.X - leafPos.X);
|
||||||
|
}
|
||||||
|
float distance = Vector2.Distance(leafPos, closestPathCell.Center);
|
||||||
if (entranceRoom == null || distance < shortestDistance)
|
if (entranceRoom == null || distance < shortestDistance)
|
||||||
{
|
{
|
||||||
entranceRoom = leaf;
|
entranceRoom = leaf;
|
||||||
@@ -289,14 +312,22 @@ namespace Barotrauma.RuinGeneration
|
|||||||
|
|
||||||
BTRoom.CalculateDistancesFromEntrance(entranceRoom, corridors);
|
BTRoom.CalculateDistancesFromEntrance(entranceRoom, corridors);
|
||||||
|
|
||||||
allShapes = GenerateStructures(caveCells);
|
allShapes = GenerateStructures(caveCells, area, mirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RuinShape> GenerateStructures(List<VoronoiCell> caveCells)
|
private List<RuinShape> GenerateStructures(List<VoronoiCell> caveCells, Rectangle ruinArea, bool mirror)
|
||||||
{
|
{
|
||||||
List<RuinShape> shapes = new List<RuinShape>(rooms);
|
List<RuinShape> shapes = new List<RuinShape>(rooms);
|
||||||
shapes.AddRange(corridors);
|
shapes.AddRange(corridors);
|
||||||
|
|
||||||
|
if (mirror)
|
||||||
|
{
|
||||||
|
foreach (RuinShape shape in shapes)
|
||||||
|
{
|
||||||
|
shape.MirrorX(ruinArea.Center.ToVector2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (RuinShape leaf in shapes)
|
foreach (RuinShape leaf in shapes)
|
||||||
{
|
{
|
||||||
RuinStructureType wallType = RuinStructureType.Wall;
|
RuinStructureType wallType = RuinStructureType.Wall;
|
||||||
|
|||||||
@@ -1267,7 +1267,10 @@ namespace Barotrauma.Networking
|
|||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset();
|
||||||
#endif
|
#endif
|
||||||
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level, true, teamCount > 1);
|
GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level,
|
||||||
|
reloadSub: true,
|
||||||
|
loadSecondSub: teamCount > 1,
|
||||||
|
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user