From aa5b2a973e3cc4657a231cb6ac633579c8acf03d Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 27 Jul 2018 10:36:52 +0300 Subject: [PATCH 1/6] Mirroring levels. Mirroring the wall geometry works, but ruins and background sprites are not placed at the correct positions yet. --- .../Source/Map/Levels/Level.cs | 11 +- .../Map/Levels/BackgroundSpriteManager.cs | 2 + .../Source/Map/Levels/Level.cs | 122 +++++++++++++++--- .../Source/Map/Levels/Ruins/RuinGenerator.cs | 39 +++++- 4 files changed, 144 insertions(+), 30 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaClient/Source/Map/Levels/Level.cs index 0fcdf9623..04fbb87e9 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Levels/Level.cs @@ -27,10 +27,17 @@ namespace Barotrauma { 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); } + + 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); + } } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs index a5b52b7c8..565d8e90f 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs @@ -231,6 +231,8 @@ namespace Barotrauma Rand.Range(0.0f, level.Size.X, 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; List edges = new List(); diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 7d7ce68e1..a7314c6dd 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -25,12 +25,12 @@ namespace Barotrauma [Flags] public enum PositionType { - MainPath=1, Cave=2, Ruin=4 + MainPath = 1, Cave = 2, Ruin = 4 } - + struct InterestingPosition { - public readonly Vector2 Position; + public Vector2 Position; public readonly PositionType PositionType; public InterestingPosition(Vector2 position, PositionType positionType) @@ -145,7 +145,11 @@ namespace Barotrauma private set; } - + public bool Mirrored + { + get; + private set; + } public LevelGenerationParams GenerationParams { @@ -170,7 +174,9 @@ namespace Barotrauma 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) @@ -194,6 +200,8 @@ namespace Barotrauma public void Generate(bool mirror = false) { + Mirrored = mirror; + if (backgroundSpriteManager == null) { var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundSpritePrefabs); @@ -303,9 +311,7 @@ namespace Barotrauma if (y < borders.Height - siteInterval.Y) sites.Add(new Vector2(x, y) + Vector2.UnitY * 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); } } @@ -334,7 +340,7 @@ namespace Barotrauma //---------------------------------------------------------------------------------- List 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) { @@ -348,8 +354,13 @@ namespace Barotrauma foreach (InterestingPosition positionOfInterest in positionsOfInterest) { - WayPoint wayPoint = new WayPoint(positionOfInterest.Position, SpawnType.Enemy, null); - wayPoint.MoveWithLevel = true; + WayPoint wayPoint = new WayPoint( + 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; @@ -400,7 +411,7 @@ namespace Barotrauma //---------------------------------------------------------------------------------- // initialize the cells that are still left and insert them into the cell grid //---------------------------------------------------------------------------------- - + foreach (VoronoiCell cell in pathCells) { cell.edges.ForEach(e => e.OutsideLevel = false); @@ -417,6 +428,55 @@ namespace Barotrauma } } + //---------------------------------------------------------------------------------- + // mirror if needed + //---------------------------------------------------------------------------------- + + if (mirror) + { + HashSet mirroredEdges = new HashSet(); + HashSet mirroredSites = new HashSet(); + foreach (VoronoiCell cell in cells) + { + 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)) + { + edge.site1.coord.x = borders.Width - edge.site1.coord.x; + mirroredSites.Add(edge.site1); + } + if (!mirroredSites.Contains(edge.site2)) + { + edge.site2.coord.x = borders.Width - edge.site2.coord.x; + mirroredSites.Add(edge.site2); + } + mirroredEdges.Add(edge); + } + } + + + foreach (List 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) { int x = (int)Math.Floor(cell.Center.X / GridCellSize); @@ -435,9 +495,12 @@ namespace Barotrauma ruins = new List(); for (int i = 0; i < generationParams.RuinCount; i++) { - GenerateRuin(mainPath); + System.Diagnostics.Debug.WriteLine("Generating ruin "+i+" *******************************************"); + GenerateRuin(mainPath, mirror); } + int testSync = Rand.Int(1000, Rand.RandSync.Server); + DebugConsole.NewMessage("TESTSYNC: " + testSync + " ---------------------------------------------",Color.White); //---------------------------------------------------------------------------------- // generate the bodies and rendered triangles of the cells @@ -809,40 +872,56 @@ namespace Barotrauma return tunnelNodes; } - private void GenerateRuin(List mainPath) + private void GenerateRuin(List 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)); float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f; - Vector2 ruinPos = cells[Rand.Int(cells.Count, Rand.RandSync.Server)].Center; + System.Diagnostics.Debug.WriteLine("Cell count " + cells.Count); + int cellIndex = Rand.Int(cells.Count, Rand.RandSync.Server); + System.Diagnostics.Debug.WriteLine("Cell index " + cellIndex); + Vector2 ruinPos = cells[cellIndex].Center; //50% chance of placing the ruins at a cave if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.5f) { + System.Diagnostics.Debug.WriteLine("Placing at cave"); TryGetInterestingPosition(true, PositionType.Cave, 0.0f, out ruinPos); } ruinPos.Y = Math.Min(ruinPos.Y, borders.Y + borders.Height - ruinSize.Y / 2); ruinPos.Y = Math.Max(ruinPos.Y, SeaFloorTopPos + ruinSize.Y / 2.0f); - + + float minDist = ruinRadius * 2.0f; + float minDistSqr = minDist * minDist; + + System.Diagnostics.Debug.WriteLine("Initial ruin pos "+ruinPos); + 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; iter++; foreach (VoronoiCell pathCell in mainPath) { - float dist = Vector2.Distance(pathCell.Center, ruinPos); - if (dist > 10000.0f) continue; + Vector2 diff = ruinPos - pathCell.Center; + 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.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y / 2, weighedPathPos.Y); } ruinPos = weighedPathPos; + System.Diagnostics.Debug.WriteLine(iter+": " + ruinPos); if (iter > 10000) break; } @@ -859,7 +938,8 @@ namespace Barotrauma } } - var ruin = new Ruin(closestPathCell, cells, new Rectangle(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize))); + System.Diagnostics.Debug.WriteLine("Final ruin pos: " + ruinPos); + var ruin = new Ruin(closestPathCell, cells, new Rectangle(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize)), mirror); ruins.Add(ruin); ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance)); diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs index ad9c9a4d0..3fc1a12a0 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs @@ -139,11 +139,28 @@ namespace Barotrauma.RuinGeneration 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; @@ -183,7 +200,7 @@ namespace Barotrauma.RuinGeneration private set; } - public Ruin(VoronoiCell closestPathCell, List caveCells, Rectangle area) + public Ruin(VoronoiCell closestPathCell, List caveCells, Rectangle area, bool mirror = false) { Area = area; @@ -194,10 +211,10 @@ namespace Barotrauma.RuinGeneration allShapes = new List(); - Generate(closestPathCell, caveCells, area); + Generate(closestPathCell, caveCells, area, mirror); } - public void Generate(VoronoiCell closestPathCell, List caveCells, Rectangle area) + public void Generate(VoronoiCell closestPathCell, List caveCells, Rectangle area, bool mirror = false) { corridors.Clear(); rooms.Clear(); @@ -289,13 +306,21 @@ namespace Barotrauma.RuinGeneration BTRoom.CalculateDistancesFromEntrance(entranceRoom, corridors); - allShapes = GenerateStructures(caveCells); + allShapes = GenerateStructures(caveCells, area, mirror); } - private List GenerateStructures(List caveCells) + private List GenerateStructures(List caveCells, Rectangle ruinArea, bool mirror) { List shapes = new List(rooms); shapes.AddRange(corridors); + + if (mirror) + { + foreach (RuinShape shape in shapes) + { + shape.MirrorX(ruinArea.Center.ToVector2()); + } + } foreach (RuinShape leaf in shapes) { From 3b4a6c00813348292b3de4c781d60d5c4ef42443 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 27 Jul 2018 13:01:04 +0300 Subject: [PATCH 2/6] Ruin and seafloor mirroring works now --- .../Source/Map/Levels/Level.cs | 49 +++++++++++++------ .../Source/Map/Levels/Ruins/RuinGenerator.cs | 24 +++++---- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index a7314c6dd..a8a394c14 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -397,11 +397,13 @@ namespace Barotrauma // remove unnecessary cells and create some holes at the bottom of the level //---------------------------------------------------------------------------------- + System.Diagnostics.Debug.WriteLine("cellcount before cleaning: " + cells.Count); cells = CleanCells(pathCells); pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle( (int)(borders.Width * 0.2f), 0, (int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f)))); - + System.Diagnostics.Debug.WriteLine("cellcount after bottom holes: " + cells.Count); + foreach (VoronoiCell cell in cells) { if (cell.Center.Y < borders.Height / 2) continue; @@ -412,6 +414,7 @@ namespace Barotrauma // initialize the cells that are still left and insert them into the cell grid //---------------------------------------------------------------------------------- + System.Diagnostics.Debug.WriteLine("pathcells before init: " + cells.Count); foreach (VoronoiCell cell in pathCells) { cell.edges.ForEach(e => e.OutsideLevel = false); @@ -432,11 +435,15 @@ namespace Barotrauma // mirror if needed //---------------------------------------------------------------------------------- + System.Diagnostics.Debug.WriteLine("cellcount: "+cells.Count); + System.Diagnostics.Debug.WriteLine("pathcellcount: " + pathCells.Count); if (mirror) { HashSet mirroredEdges = new HashSet(); HashSet mirroredSites = new HashSet(); - foreach (VoronoiCell cell in cells) + List allCells = new List(cells); + allCells.AddRange(pathCells); + foreach (VoronoiCell cell in allCells) { foreach (GraphEdge edge in cell.edges) { @@ -500,7 +507,7 @@ namespace Barotrauma } int testSync = Rand.Int(1000, Rand.RandSync.Server); - DebugConsole.NewMessage("TESTSYNC: " + testSync + " ---------------------------------------------",Color.White); + System.Diagnostics.Debug.WriteLine("TESTSYNC: " + testSync + " ---------------------------------------------",Color.White); //---------------------------------------------------------------------------------- // generate the bodies and rendered triangles of the cells @@ -529,7 +536,7 @@ namespace Barotrauma bodies.Add(TopBarrier); - GenerateSeaFloor(); + GenerateSeaFloor(mirror); backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount); #if CLIENT @@ -728,7 +735,7 @@ namespace Barotrauma return newCells; } - private void GenerateSeaFloor() + private void GenerateSeaFloor(bool mirror) { BottomPos = generationParams.SeaFloorDepth; SeaFloorTopPos = BottomPos; @@ -751,16 +758,24 @@ namespace Barotrauma { for (int i = 0; i < bottomPositions.Count - 1; i++) { - bottomPositions.Insert(i+1, + bottomPositions.Insert(i + 1, (bottomPositions[i] + bottomPositions[i + 1]) / 2.0f + Vector2.UnitY * Rand.Range(0.0f, generationParams.SeaFloorVariance, Rand.RandSync.Server)); - + i++; } 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); extraWalls = new LevelWall[] { new LevelWall(bottomPositions, new Vector2(0.0f, -2000.0f), backgroundColor, this) }; @@ -878,6 +893,10 @@ namespace Barotrauma float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f; System.Diagnostics.Debug.WriteLine("Cell count " + cells.Count); + for (int i = 0; i shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance)); for (int i = 0; i < 4; i++) { @@ -1091,15 +1115,12 @@ namespace Barotrauma List cells = new List(); - 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]) - { - cells.Add(cell); - } - } + foreach (VoronoiCell cell in cellGrid[x, y]) cells.Add(cell); + } } if (extraWalls != null) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs index 3fc1a12a0..f4126af3e 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Ruins/RuinGenerator.cs @@ -1,6 +1,7 @@ using FarseerPhysics; using FarseerPhysics.Factories; using Microsoft.Xna.Framework; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -35,7 +36,7 @@ namespace Barotrauma.RuinGeneration 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) { @@ -70,7 +71,7 @@ namespace Barotrauma.RuinGeneration 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 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)); } } - else if (line.A.Y == line.B.Y) //horizontal line + else { //line doesn't intersect the rectangle if (rectangle.X > line.B.X || rectangle.Right < line.A.X || @@ -130,11 +131,6 @@ namespace Barotrauma.RuinGeneration 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; @@ -164,6 +160,11 @@ namespace Barotrauma.RuinGeneration 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) { Debug.Assert(a.X <= b.X); @@ -260,7 +261,12 @@ namespace Barotrauma.RuinGeneration float shortestDistance = 0.0f; 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) { entranceRoom = leaf; From 5dcb7bba9b9807464442b122a94c51c27b645a45 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 27 Jul 2018 14:50:42 +0300 Subject: [PATCH 3/6] Mirroring background sprite positions partially working. They spawn at the correct edge, but not at the correct position or rotation. --- .../Source/Map/Levels/BackgroundSpriteManager.cs | 8 +++++++- Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs index 565d8e90f..8d90ae775 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs @@ -243,7 +243,13 @@ namespace Barotrauma 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); - + + //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); }); + + /*System.Diagnostics.Debug.WriteLine("FindSpritePosition - prefab: "+System.IO.Path.GetFileNameWithoutExtension(prefab.Sprite.FilePath)+" cells: "+cells.Count+" spawnpos: "+ prefab.SpawnPos+" randompos: "+ randomPos); + System.Diagnostics.Debug.WriteLine(string.Join(", ",cells.Select(c => level.cells.IndexOf(c))));*/ + if (cells.Any()) { VoronoiCell cell = cells[Rand.Int(cells.Count, Rand.RandSync.Server)]; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index a8a394c14..5c46f7405 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -55,7 +55,8 @@ namespace Barotrauma //private float shaftHeight; //List bodies; - private List cells; + //TODO: change back to private + public List cells; //private VertexBuffer vertexBuffer; @@ -452,11 +453,16 @@ namespace Barotrauma 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); } From 1c1a1eb80e507c08df22b04dfed837c19d3a47f5 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 8 Aug 2018 15:12:24 +0300 Subject: [PATCH 4/6] Background sprites spawn at the correct position and rotation in mirrored levels. --- .../Source/Map/Levels/BackgroundSpriteManager.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs index 8d90ae775..5b657bab6 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs @@ -136,9 +136,8 @@ namespace Barotrauma for (int i = 0 ; i < amount; i++) { BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name); - GraphEdge selectedEdge = null; 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; @@ -148,7 +147,8 @@ namespace Barotrauma 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, 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); @@ -313,10 +313,12 @@ namespace Barotrauma edgeNormal = normals[index]; 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) From 99c76d00999d5eafed4077d50fb1535f2ace4c17 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 8 Aug 2018 15:16:53 +0300 Subject: [PATCH 5/6] Cleanup --- .../Map/Levels/BackgroundSpriteManager.cs | 5 +-- .../Source/Map/Levels/Level.cs | 45 ++++--------------- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs index 5b657bab6..8228bceff 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/BackgroundSpriteManager.cs @@ -246,10 +246,7 @@ namespace Barotrauma //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); }); - - /*System.Diagnostics.Debug.WriteLine("FindSpritePosition - prefab: "+System.IO.Path.GetFileNameWithoutExtension(prefab.Sprite.FilePath)+" cells: "+cells.Count+" spawnpos: "+ prefab.SpawnPos+" randompos: "+ randomPos); - System.Diagnostics.Debug.WriteLine(string.Join(", ",cells.Select(c => level.cells.IndexOf(c))));*/ - + if (cells.Any()) { VoronoiCell cell = cells[Rand.Int(cells.Count, Rand.RandSync.Server)]; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 5c46f7405..8c243c52e 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -199,7 +199,7 @@ namespace Barotrauma 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 = true) { Mirrored = mirror; @@ -389,21 +389,18 @@ namespace Barotrauma pathCells.AddRange(newPathCells); } - - Debug.WriteLine("path: " + sw2.ElapsedMilliseconds + " ms"); + sw2.Restart(); //---------------------------------------------------------------------------------- // remove unnecessary cells and create some holes at the bottom of the level //---------------------------------------------------------------------------------- - - System.Diagnostics.Debug.WriteLine("cellcount before cleaning: " + cells.Count); + cells = CleanCells(pathCells); pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle( (int)(borders.Width * 0.2f), 0, (int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f)))); - System.Diagnostics.Debug.WriteLine("cellcount after bottom holes: " + cells.Count); foreach (VoronoiCell cell in cells) { @@ -415,7 +412,6 @@ namespace Barotrauma // initialize the cells that are still left and insert them into the cell grid //---------------------------------------------------------------------------------- - System.Diagnostics.Debug.WriteLine("pathcells before init: " + cells.Count); foreach (VoronoiCell cell in pathCells) { cell.edges.ForEach(e => e.OutsideLevel = false); @@ -435,9 +431,7 @@ namespace Barotrauma //---------------------------------------------------------------------------------- // mirror if needed //---------------------------------------------------------------------------------- - - System.Diagnostics.Debug.WriteLine("cellcount: "+cells.Count); - System.Diagnostics.Debug.WriteLine("pathcellcount: " + pathCells.Count); + if (mirror) { HashSet mirroredEdges = new HashSet(); @@ -508,13 +502,9 @@ namespace Barotrauma ruins = new List(); for (int i = 0; i < generationParams.RuinCount; i++) { - System.Diagnostics.Debug.WriteLine("Generating ruin "+i+" *******************************************"); GenerateRuin(mainPath, mirror); } - - int testSync = Rand.Int(1000, Rand.RandSync.Server); - System.Diagnostics.Debug.WriteLine("TESTSYNC: " + testSync + " ---------------------------------------------",Color.White); - + //---------------------------------------------------------------------------------- // generate the bodies and rendered triangles of the cells //---------------------------------------------------------------------------------- @@ -897,20 +887,13 @@ namespace Barotrauma { 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; - - System.Diagnostics.Debug.WriteLine("Cell count " + cells.Count); - for (int i = 0; i Vector2.DistanceSquared(ruinPos, p.Center) < minDistSqr)) { @@ -946,8 +927,6 @@ namespace Barotrauma } ruinPos = weighedPathPos; - System.Diagnostics.Debug.WriteLine(iter+": " + ruinPos); - if (iter > 10000) break; } @@ -962,16 +941,10 @@ namespace Barotrauma closestDist = dist; } } - - System.Diagnostics.Debug.WriteLine("Final ruin pos: " + ruinPos); - int testSync = Rand.Int(1000, Rand.RandSync.Server); - System.Diagnostics.Debug.WriteLine("TESTSYNC2: " + testSync + " ---------------------------------------------", Color.White); + var ruin = new Ruin(closestPathCell, cells, new Rectangle(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize)), mirror); ruins.Add(ruin); - - testSync = Rand.Int(1000, Rand.RandSync.Server); - System.Diagnostics.Debug.WriteLine("TESTSYNC3: " + testSync + " ---------------------------------------------", Color.White); - + ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance)); for (int i = 0; i < 4; i++) { From 5100956baed640d48f4b0a277af226826ab927ef Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 8 Aug 2018 15:30:32 +0300 Subject: [PATCH 6/6] Levels are mirrored when traveling backwards through a connection in the campaign mode. Closes #519 --- .../BarotraumaClient/Source/Networking/GameClient.cs | 5 ++++- .../BarotraumaClient/Source/Screens/LobbyScreen.cs | 5 ++++- .../Source/GameSession/GameSession.cs | 11 +++++------ .../BarotraumaShared/Source/Map/Levels/Level.cs | 2 +- .../BarotraumaShared/Source/Networking/GameServer.cs | 5 ++++- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index c794bd446..47bc41491 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -761,7 +761,10 @@ namespace Barotrauma.Networking else { 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); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/LobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/LobbyScreen.cs index a8df21efa..8bd432931 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/LobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/LobbyScreen.cs @@ -190,7 +190,10 @@ namespace Barotrauma private IEnumerable 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(); yield return CoroutineStatus.Success; diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs index 91ded070f..2c8b94a96 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs @@ -182,7 +182,7 @@ namespace Barotrauma 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 GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null; @@ -210,11 +210,10 @@ namespace Barotrauma Submarine.MainSubs[1].Load(false); } } - + if (level != null) { - level.Generate(); - + level.Generate(mirrorLevel); submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f))); } @@ -229,9 +228,9 @@ namespace Barotrauma if (GameMode != null) { GameMode.MsgBox(); - if (GameMode is MultiPlayerCampaign campaign && GameMain.Server != null) + if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.Server != null) { - campaign.CargoManager.CreateItems(); + mpCampaign.CargoManager.CreateItems(); } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 8c243c52e..3137b9385 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -199,7 +199,7 @@ namespace Barotrauma return new Level(seed, Rand.Range(30.0f, 80.0f, Rand.RandSync.Server), LevelGenerationParams.GetRandom(seed)); } - public void Generate(bool mirror = true) + public void Generate(bool mirror) { Mirrored = mirror; diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index 6cd095e1a..30e6cc5be 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -1243,7 +1243,10 @@ namespace Barotrauma.Networking #if CLIENT if (GameMain.GameSession?.CrewManager != null) GameMain.GameSession.CrewManager.Reset(); #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 {