A separate class for parameters used by the level generator, different "level types" with configurable parameters
This commit is contained in:
@@ -136,6 +136,7 @@
|
|||||||
<Compile Include="Source\Map\EntityGrid.cs" />
|
<Compile Include="Source\Map\EntityGrid.cs" />
|
||||||
<Compile Include="Source\Map\FireSource.cs" />
|
<Compile Include="Source\Map\FireSource.cs" />
|
||||||
<Compile Include="Source\Map\Levels\CaveGenerator.cs" />
|
<Compile Include="Source\Map\Levels\CaveGenerator.cs" />
|
||||||
|
<Compile Include="Source\Map\Levels\LevelGenerationParams.cs" />
|
||||||
<Compile Include="Source\Map\Levels\LevelRenderer.cs" />
|
<Compile Include="Source\Map\Levels\LevelRenderer.cs" />
|
||||||
<Compile Include="Source\Map\Levels\Ruins\BTRoom.cs" />
|
<Compile Include="Source\Map\Levels\Ruins\BTRoom.cs" />
|
||||||
<Compile Include="Source\Map\Levels\Ruins\Corridor.cs" />
|
<Compile Include="Source\Map\Levels\Ruins\Corridor.cs" />
|
||||||
@@ -768,6 +769,10 @@
|
|||||||
<Content Include="Content\Map\iceWall.png">
|
<Content Include="Content\Map\iceWall.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Content\Map\LevelGenerationParameters.xml">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
<Content Include="Content\Map\locationNames.txt">
|
<Content Include="Content\Map\locationNames.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<LevelGenerationParameters>
|
||||||
|
<Default
|
||||||
|
width="150000"
|
||||||
|
height="60000"
|
||||||
|
VoronoiSiteInterval="2000,2000"
|
||||||
|
VoronoiSiteVariance="800,800"
|
||||||
|
MainPathNodeIntervalRange="10000,30000"
|
||||||
|
BackgroundColor="29,36,50"
|
||||||
|
SmallTunnelCount="5"
|
||||||
|
SmallTunnelLengthRange="5000,10000"
|
||||||
|
RuinCount="1"
|
||||||
|
BottomHoleProbability="0.4"
|
||||||
|
BackgroundSpriteAmount="1000"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Open
|
||||||
|
width="200000"
|
||||||
|
height="50000"
|
||||||
|
VoronoiSiteInterval="2000,2000"
|
||||||
|
VoronoiSiteVariance="800,800"
|
||||||
|
MainPathNodeIntervalRange="5000,10000"
|
||||||
|
BackgroundColor="55,61,72"
|
||||||
|
SmallTunnelCount="3"
|
||||||
|
SmallTunnelLengthRange="5000,10000"
|
||||||
|
RuinCount="1"
|
||||||
|
BottomHoleProbability="1"
|
||||||
|
BackgroundSpriteAmount="800"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pillars
|
||||||
|
width="100000"
|
||||||
|
height="80000"
|
||||||
|
VoronoiSiteInterval="1000,8000"
|
||||||
|
VoronoiSiteVariance="100,1400"
|
||||||
|
MainPathNodeIntervalRange="5000,10000"
|
||||||
|
BackgroundColor="55,72,58"
|
||||||
|
SmallTunnelCount="10"
|
||||||
|
SmallTunnelLengthRange="5000,10000"
|
||||||
|
RuinCount="1"
|
||||||
|
BottomHoleProbability="0.5"
|
||||||
|
BackgroundSpriteAmount="1000"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Slabs
|
||||||
|
width="150000"
|
||||||
|
height="50000"
|
||||||
|
VoronoiSiteInterval="8000,1000"
|
||||||
|
VoronoiSiteVariance="2000,400"
|
||||||
|
MainPathNodeIntervalRange="5000,10000"
|
||||||
|
BackgroundColor="55,72,58"
|
||||||
|
SmallTunnelCount="10"
|
||||||
|
SmallTunnelLengthRange="5000,10000"
|
||||||
|
RuinCount="1"
|
||||||
|
BottomHoleProbability="0.0"
|
||||||
|
BackgroundSpriteAmount="1000"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Maze
|
||||||
|
width="100000"
|
||||||
|
height="70000"
|
||||||
|
VoronoiSiteInterval="1500,1500"
|
||||||
|
VoronoiSiteVariance="700,700"
|
||||||
|
MainPathNodeIntervalRange="6000,10000"
|
||||||
|
BackgroundColor="50,46,20"
|
||||||
|
SmallTunnelCount="10"
|
||||||
|
SmallTunnelLengthRange="5000,50000"
|
||||||
|
RuinCount="3"
|
||||||
|
BottomHoleProbability="0.5"
|
||||||
|
BackgroundSpriteAmount="1000"
|
||||||
|
/>
|
||||||
|
</LevelGenerationParameters>
|
||||||
@@ -10,7 +10,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public enum ContentType
|
public enum ContentType
|
||||||
{
|
{
|
||||||
None, Jobs, Item, Character, Structure, Executable, LocationTypes, RandomEvents, Missions, BackgroundCreaturePrefabs, BackgroundSpritePrefabs
|
None,
|
||||||
|
Jobs,
|
||||||
|
Item,
|
||||||
|
Character,
|
||||||
|
Structure,
|
||||||
|
Executable,
|
||||||
|
LocationTypes,
|
||||||
|
LevelGenerationPresets,
|
||||||
|
RandomEvents,
|
||||||
|
Missions,
|
||||||
|
BackgroundCreaturePrefabs, BackgroundSpritePrefabs
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ContentPackage
|
public class ContentPackage
|
||||||
|
|||||||
@@ -493,10 +493,6 @@ namespace Barotrauma
|
|||||||
case "fire":
|
case "fire":
|
||||||
if (GameMain.Client == null) Hull.EditFire = !Hull.EditFire;
|
if (GameMain.Client == null) Hull.EditFire = !Hull.EditFire;
|
||||||
|
|
||||||
break;
|
|
||||||
case "generatelevel":
|
|
||||||
GameMain.Level = new Level("asdf", 50.0f, 500,500, 50);
|
|
||||||
GameMain.Level.Generate();
|
|
||||||
break;
|
break;
|
||||||
case "fixitems":
|
case "fixitems":
|
||||||
foreach (Item it in Item.ItemList)
|
foreach (Item it in Item.ItemList)
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Mission.Init();
|
Mission.Init();
|
||||||
MapEntityPrefab.Init();
|
MapEntityPrefab.Init();
|
||||||
|
LevelGenerationParams.LoadPresets();
|
||||||
TitleScreen.LoadState = 10.0f;
|
TitleScreen.LoadState = 10.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
|||||||
@@ -189,16 +189,18 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Site site = (i == 0) ? ge.site1 : ge.site2;
|
Site site = (i == 0) ? ge.site1 : ge.site2;
|
||||||
|
|
||||||
VoronoiCell cell = cellGrid[
|
int x = (int)(Math.Floor((site.coord.x-borders.X) / gridCellSize));
|
||||||
(int)Math.Floor((site.coord.x-borders.X) / gridCellSize),
|
int y = (int)(Math.Floor((site.coord.y-borders.Y) / gridCellSize));
|
||||||
(int)Math.Floor((site.coord.y-borders.Y) / gridCellSize)].Find(c => c.site == site);
|
|
||||||
|
x = MathHelper.Clamp(x, 0, cellGrid.GetLength(0)-1);
|
||||||
|
y = MathHelper.Clamp(y, 0, cellGrid.GetLength(1)-1);
|
||||||
|
|
||||||
|
VoronoiCell cell = cellGrid[x,y].Find(c => c.site == site);
|
||||||
|
|
||||||
if (cell == null)
|
if (cell == null)
|
||||||
{
|
{
|
||||||
cell = new VoronoiCell(site);
|
cell = new VoronoiCell(site);
|
||||||
cellGrid[
|
cellGrid[x, y].Add(cell);
|
||||||
(int)Math.Floor((cell.Center.X-borders.X) / gridCellSize),
|
|
||||||
(int)Math.Floor((cell.Center.Y - borders.Y) / gridCellSize)].Add(cell);
|
|
||||||
cells.Add(cell);
|
cells.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private string seed;
|
private string seed;
|
||||||
|
|
||||||
private int siteInterval;
|
|
||||||
|
|
||||||
public const int GridCellSize = 2000;
|
public const int GridCellSize = 2000;
|
||||||
private List<VoronoiCell>[,] cellGrid;
|
private List<VoronoiCell>[,] cellGrid;
|
||||||
|
|
||||||
@@ -77,6 +75,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Color backgroundColor;
|
private Color backgroundColor;
|
||||||
|
|
||||||
|
private LevelGenerationParams generationParams;
|
||||||
|
|
||||||
public Vector2 StartPosition
|
public Vector2 StartPosition
|
||||||
{
|
{
|
||||||
get { return startPosition; }
|
get { return startPosition; }
|
||||||
@@ -124,24 +124,22 @@ namespace Barotrauma
|
|||||||
get { return backgroundColor; }
|
get { return backgroundColor; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Level(string seed, float difficulty, int width, int height, int siteInterval)
|
public Level(string seed, float difficulty, LevelGenerationParams generationParams)
|
||||||
{
|
{
|
||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
|
|
||||||
this.siteInterval = siteInterval;
|
|
||||||
|
|
||||||
this.Difficulty = difficulty;
|
this.Difficulty = difficulty;
|
||||||
|
|
||||||
borders = new Rectangle(0, 0, width, height);
|
this.generationParams = generationParams;
|
||||||
|
|
||||||
|
borders = new Rectangle(0, 0, (int)generationParams.Width, (int)generationParams.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Level CreateRandom(LocationConnection locationConnection)
|
public static Level CreateRandom(LocationConnection locationConnection)
|
||||||
{
|
{
|
||||||
string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;
|
string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;
|
||||||
|
|
||||||
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
return new Level(seed, locationConnection.Difficulty, LevelGenerationParams.GetRandom(seed));
|
||||||
|
|
||||||
return new Level(seed, locationConnection.Difficulty, Rand.Range(80000, 120000, false), Rand.Range(40000, 60000, false), 2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Level CreateRandom(string seed = "")
|
public static Level CreateRandom(string seed = "")
|
||||||
@@ -153,10 +151,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
||||||
|
|
||||||
return new Level(seed, Rand.Range(30.0f, 80.0f, false), Rand.Range(80000, 120000, false), Rand.Range(40000, 60000, false), 2000);
|
return new Level(seed, Rand.Range(30.0f, 80.0f, false), LevelGenerationParams.GetRandom(seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Generate(bool mirror=false)
|
public void Generate(bool mirror = false)
|
||||||
{
|
{
|
||||||
Stopwatch sw = new Stopwatch();
|
Stopwatch sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
@@ -176,29 +174,32 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
||||||
|
|
||||||
float brightness = Rand.Range(1.0f, 1.3f, false);
|
backgroundColor = generationParams.BackgroundColor;
|
||||||
backgroundColor = Color.Lerp(new Color(11, 18, 26), new Color(50, 46, 20), Rand.Range(0.0f, 1.0f, false)) * brightness;
|
|
||||||
backgroundColor = new Color(backgroundColor, 1.0f);
|
|
||||||
|
|
||||||
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
|
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
|
||||||
GameMain.LightManager.AmbientLight = new Color(backgroundColor * (60.0f / avgValue), 1.0f);
|
GameMain.LightManager.AmbientLight = new Color(backgroundColor * (60.0f / avgValue), 1.0f);
|
||||||
|
|
||||||
float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height);
|
float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height);
|
||||||
minWidth = Math.Max(minWidth, 6500.0f);
|
minWidth = Math.Max(minWidth, 6500.0f);
|
||||||
|
|
||||||
startPosition = new Vector2(minWidth * 2, Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
|
startPosition = new Vector2(
|
||||||
endPosition = new Vector2(borders.Width - minWidth * 2, Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
|
Rand.Range(minWidth * 2, minWidth * 4, false),
|
||||||
|
Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
|
||||||
|
|
||||||
|
endPosition = new Vector2(
|
||||||
|
borders.Width - Rand.Range(minWidth * 2, minWidth * 4, false),
|
||||||
|
Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
|
||||||
|
|
||||||
List<Vector2> pathNodes = new List<Vector2>();
|
List<Vector2> pathNodes = new List<Vector2>();
|
||||||
Rectangle pathBorders = borders;// new Rectangle((int)minWidth, (int)minWidth, borders.Width - (int)minWidth * 2, borders.Height - (int)minWidth);
|
Rectangle pathBorders = borders;// new Rectangle((int)minWidth, (int)minWidth, borders.Width - (int)minWidth * 2, borders.Height - (int)minWidth);
|
||||||
pathBorders.Inflate(-minWidth*2, -minWidth*2);
|
pathBorders.Inflate(-minWidth*2, -minWidth*2);
|
||||||
|
|
||||||
|
|
||||||
pathNodes.Add(new Vector2(startPosition.X, borders.Height));
|
pathNodes.Add(new Vector2(startPosition.X, borders.Height));
|
||||||
pathNodes.Add(startPosition);
|
pathNodes.Add(startPosition);
|
||||||
|
|
||||||
|
|
||||||
for (float x = startPosition.X; x < endPosition.X; x += Rand.Range(5000.0f, 10000.0f, false))
|
for (float x = startPosition.X;
|
||||||
|
x < endPosition.X;
|
||||||
|
x += Rand.Range(generationParams.MainPathNodeIntervalRange.X, generationParams.MainPathNodeIntervalRange.Y, false))
|
||||||
{
|
{
|
||||||
pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, false)));
|
pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, false)));
|
||||||
}
|
}
|
||||||
@@ -206,16 +207,17 @@ namespace Barotrauma
|
|||||||
pathNodes.Add(endPosition);
|
pathNodes.Add(endPosition);
|
||||||
pathNodes.Add(new Vector2(endPosition.X, borders.Height));
|
pathNodes.Add(new Vector2(endPosition.X, borders.Height));
|
||||||
|
|
||||||
int smallTunnelCount = 5;
|
|
||||||
|
|
||||||
List<List<Vector2>> smallTunnels = new List<List<Vector2>>();
|
List<List<Vector2>> smallTunnels = new List<List<Vector2>>();
|
||||||
|
|
||||||
for (int i = 0; i < smallTunnelCount; i++)
|
for (int i = 0; i < generationParams.SmallTunnelCount; i++)
|
||||||
{
|
{
|
||||||
var tunnelStartPos = pathNodes[Rand.Range(2, pathNodes.Count - 2, false)];
|
var tunnelStartPos = pathNodes[Rand.Range(2, pathNodes.Count - 2, false)];
|
||||||
tunnelStartPos.X = MathHelper.Clamp(tunnelStartPos.X, pathBorders.X, pathBorders.Right);
|
tunnelStartPos.X = MathHelper.Clamp(tunnelStartPos.X, pathBorders.X, pathBorders.Right);
|
||||||
|
|
||||||
float tunnelLength = Rand.Range(5000.0f, 10000.0f, false);
|
float tunnelLength = Rand.Range(
|
||||||
|
generationParams.SmallTunnelLengthRange.X,
|
||||||
|
generationParams.SmallTunnelLengthRange.Y,
|
||||||
|
false);
|
||||||
|
|
||||||
var tunnelNodes = MathUtils.GenerateJaggedLine(
|
var tunnelNodes = MathUtils.GenerateJaggedLine(
|
||||||
tunnelStartPos,
|
tunnelStartPos,
|
||||||
@@ -232,20 +234,22 @@ namespace Barotrauma
|
|||||||
if (tunnel.Any()) smallTunnels.Add(tunnel);
|
if (tunnel.Any()) smallTunnels.Add(tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 siteInterval = generationParams.VoronoiSiteInterval;
|
||||||
|
Vector2 siteVariance = generationParams.VoronoiSiteVariance;
|
||||||
float siteVariance = siteInterval * 0.4f;
|
for (float x = siteInterval.X / 2; x < borders.Width; x += siteInterval.X)
|
||||||
for (int x = siteInterval / 2; x < borders.Width; x += siteInterval)
|
|
||||||
{
|
{
|
||||||
for (int y = siteInterval / 2; y < borders.Height; y += siteInterval)
|
for (float y = siteInterval.Y / 2; y < borders.Height; y += siteInterval.Y)
|
||||||
{
|
{
|
||||||
Vector2 site = new Vector2(x, y) + Rand.Vector(siteVariance, false);
|
Vector2 site = new Vector2(
|
||||||
|
x + Rand.Range(-siteVariance.X, siteVariance.X, false),
|
||||||
|
y + Rand.Range(-siteVariance.Y, siteVariance.Y, false));
|
||||||
|
|
||||||
if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval)))
|
if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval.Length())))
|
||||||
{
|
{
|
||||||
if (x < borders.Width - siteInterval) sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f);
|
//add some more sites around the small tunnels to generate more small voronoi cells
|
||||||
if (y < borders.Height - siteInterval) sites.Add(new Vector2(x, y) + Vector2.UnitY * siteInterval * 0.5f);
|
if (x < borders.Width - siteInterval.X) sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f);
|
||||||
if (x < borders.Width - siteInterval && y < borders.Height - siteInterval) sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f);
|
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;
|
if (mirror) site.X = borders.Width - site.X;
|
||||||
@@ -259,7 +263,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
List<GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height);
|
List<GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height);
|
||||||
|
|
||||||
|
|
||||||
Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
|
Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
|
||||||
sw2.Restart();
|
sw2.Restart();
|
||||||
|
|
||||||
@@ -272,7 +275,6 @@ 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.3f, mirror);
|
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.3f, mirror);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 2; i < mainPath.Count; i += 3)
|
for (int i = 2; i < mainPath.Count; i += 3)
|
||||||
{
|
{
|
||||||
positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath));
|
positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath));
|
||||||
@@ -315,9 +317,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
cells = CleanCells(pathCells);
|
cells = CleanCells(pathCells);
|
||||||
|
|
||||||
pathCells.AddRange(CreateBottomHoles(Rand.Range(0.1f,0.8f, false), new Rectangle(
|
pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle(
|
||||||
(int)(borders.Width * 0.2f), 0,
|
(int)(borders.Width * 0.2f), 0,
|
||||||
(int)(borders.Width * 0.6f), (int)(borders.Height * 0.3f))));
|
(int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f))));
|
||||||
|
|
||||||
foreach (VoronoiCell cell in pathCells)
|
foreach (VoronoiCell cell in pathCells)
|
||||||
{
|
{
|
||||||
@@ -408,76 +410,15 @@ namespace Barotrauma
|
|||||||
cellGrid[x, y].Add(cell);
|
cellGrid[x, y].Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i<generationParams.RuinCount; i++)
|
||||||
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, false), Rand.Range(5000.0f, 8000.0f, false));
|
|
||||||
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
|
|
||||||
|
|
||||||
Vector2 ruinPos = cells[Rand.Int(cells.Count, false)].Center;
|
|
||||||
|
|
||||||
int iter = 0;
|
|
||||||
|
|
||||||
while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius*2.0f))
|
|
||||||
{
|
{
|
||||||
Vector2 weighedPathPos = ruinPos;
|
GenerateRuin(mainPath);
|
||||||
iter++;
|
|
||||||
|
|
||||||
foreach (VoronoiCell pathCell in mainPath)
|
|
||||||
{
|
|
||||||
float dist = Vector2.Distance(pathCell.Center, ruinPos);
|
|
||||||
if (dist > 10000.0f) continue;
|
|
||||||
|
|
||||||
Vector2 moveAmount = Vector2.Normalize(ruinPos - pathCell.Center) * 100000.0f / dist;
|
|
||||||
|
|
||||||
//if (weighedPathPos.Y + moveAmount.Y > borders.Bottom - ruinSize.X)
|
|
||||||
//{
|
|
||||||
// moveAmount.X = (Math.Abs(moveAmount.Y) + Math.Abs(moveAmount.X))*Math.Sign(moveAmount.X);
|
|
||||||
// moveAmount.Y = 0.0f;
|
|
||||||
//}
|
|
||||||
|
|
||||||
weighedPathPos += moveAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
ruinPos = weighedPathPos;
|
|
||||||
|
|
||||||
if (iter > 10000) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
VoronoiCell closestPathCell = null;
|
|
||||||
float closestDist = 0.0f;
|
|
||||||
foreach (VoronoiCell pathCell in mainPath)
|
|
||||||
{
|
|
||||||
float dist = Vector2.Distance(pathCell.Center, ruinPos);
|
|
||||||
if (closestPathCell == null || dist < closestDist)
|
|
||||||
{
|
|
||||||
closestPathCell = pathCell;
|
|
||||||
closestDist = dist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ruin = new Ruin(closestPathCell, cells, new Rectangle((ruinPos - ruinSize * 0.5f).ToPoint(), ruinSize.ToPoint()));
|
|
||||||
|
|
||||||
ruins = new List<Ruin>();
|
|
||||||
ruins.Add(ruin);
|
|
||||||
|
|
||||||
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
|
|
||||||
for (int i = 0; i < 4; i++ )
|
|
||||||
{
|
|
||||||
positionsOfInterest.Add(new InterestingPosition(ruin.RuinShapes[i].Rect.Center.ToVector2(), PositionType.Ruin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startPosition.Y = borders.Height;
|
startPosition.Y = borders.Height;
|
||||||
endPosition.Y = borders.Height;
|
endPosition.Y = borders.Height;
|
||||||
|
|
||||||
List<VoronoiCell> cellsWithBody = new List<VoronoiCell>(cells);
|
List<VoronoiCell> cellsWithBody = new List<VoronoiCell>(cells);
|
||||||
foreach (RuinShape ruinShape in ruin.RuinShapes)
|
|
||||||
{
|
|
||||||
var tooClose = GetTooCloseCells(ruinShape.Rect.Center.ToVector2(), Math.Max(ruinShape.Rect.Width, ruinShape.Rect.Height));
|
|
||||||
|
|
||||||
tooClose.ForEach(c =>
|
|
||||||
{
|
|
||||||
if (c.edges.Any(e => ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2))) c.CellType = CellType.Empty;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
List<VertexPositionColor> bodyVertices;
|
List<VertexPositionColor> bodyVertices;
|
||||||
bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out bodyVertices);
|
bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out bodyVertices);
|
||||||
@@ -485,15 +426,17 @@ namespace Barotrauma
|
|||||||
renderer.SetBodyVertices(bodyVertices.ToArray());
|
renderer.SetBodyVertices(bodyVertices.ToArray());
|
||||||
renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells));
|
renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells));
|
||||||
|
|
||||||
renderer.PlaceSprites(1000);
|
renderer.PlaceSprites(generationParams.BackgroundSpriteAmount);
|
||||||
|
|
||||||
wrappingWalls = new WrappingWall[2, 2];
|
wrappingWalls = new WrappingWall[2, 2];
|
||||||
|
|
||||||
|
Rectangle ignoredArea = new Rectangle((int)startPosition.X, 0, (int)(endPosition.X - startPosition.X), borders.Height);
|
||||||
|
|
||||||
for (int side = 0; side < 2; side++)
|
for (int side = 0; side < 2; side++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
wrappingWalls[side, i] = new WrappingWall(pathCells, cells, borders.Height * 0.5f,
|
wrappingWalls[side, i] = new WrappingWall(pathCells, cells, ignoredArea,
|
||||||
(side == 0 ? -1 : 1) * (i + 1));
|
(side == 0 ? -1 : 1) * (i + 1));
|
||||||
|
|
||||||
List<VertexPositionColor> wrappingWallVertices;
|
List<VertexPositionColor> wrappingWallVertices;
|
||||||
@@ -532,15 +475,11 @@ namespace Barotrauma
|
|||||||
edge.site1 = null;
|
edge.site1 = null;
|
||||||
edge.site2 = null;
|
edge.site2 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms");
|
Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms");
|
||||||
sw2.Restart();
|
sw2.Restart();
|
||||||
|
|
||||||
//vertexBuffer = new VertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
|
||||||
//vertexBuffer.SetData(vertices);
|
|
||||||
|
|
||||||
if (mirror)
|
if (mirror)
|
||||||
{
|
{
|
||||||
Vector2 temp = startPosition;
|
Vector2 temp = startPosition;
|
||||||
@@ -548,11 +487,6 @@ namespace Barotrauma
|
|||||||
endPosition = temp;
|
endPosition = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//RuinGeneration.RuinGenerator.Draw(spriteBatch);
|
|
||||||
|
|
||||||
|
|
||||||
Debug.WriteLine("**********************************************************************************");
|
Debug.WriteLine("**********************************************************************************");
|
||||||
Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms");
|
Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms");
|
||||||
Debug.WriteLine("Seed: "+seed);
|
Debug.WriteLine("Seed: "+seed);
|
||||||
@@ -569,15 +503,26 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!limits.Contains(cell.Center)) continue;
|
if (!limits.Contains(cell.Center)) continue;
|
||||||
|
|
||||||
|
float closestDist = 0.0f;
|
||||||
|
WayPoint closestWayPoint = null;
|
||||||
|
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||||
|
{
|
||||||
|
if (wp.SpawnType != SpawnType.Path) continue;
|
||||||
|
|
||||||
|
float dist =Math.Abs(cell.Center.X - wp.WorldPosition.X);
|
||||||
|
if (closestWayPoint == null || dist < closestDist)
|
||||||
|
{
|
||||||
|
closestDist = dist;
|
||||||
|
closestWayPoint = wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestWayPoint.WorldPosition.Y < cell.Center.Y) continue;
|
||||||
|
|
||||||
toBeRemoved.Add(cell);
|
toBeRemoved.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
return toBeRemoved;
|
return toBeRemoved;
|
||||||
|
|
||||||
//foreach (VoronoiCell cell in toBeRemoved)
|
|
||||||
//{
|
|
||||||
// cells.Remove(cell);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnlargeMainPath(List<VoronoiCell> pathCells, float minWidth)
|
private void EnlargeMainPath(List<VoronoiCell> pathCells, float minWidth)
|
||||||
@@ -693,21 +638,6 @@ namespace Barotrauma
|
|||||||
if (tooClose && !tooCloseCells.Contains(cell)) tooCloseCells.Add(cell);
|
if (tooClose && !tooCloseCells.Contains(cell)) tooCloseCells.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (float x = -minDistance; x <= minDistance; x+=siteInterval)
|
|
||||||
//{
|
|
||||||
// for (float y = -minDistance; y <= minDistance; y += siteInterval)
|
|
||||||
// {
|
|
||||||
// Vector2 cornerPos = position + new Vector2(x,y);
|
|
||||||
|
|
||||||
// int cellIndex = CaveGenerator.FindCellIndex(cornerPos, cells, cellGrid, GridCellSize);
|
|
||||||
// if (cellIndex == -1) continue;
|
|
||||||
// if (!tooCloseCells.Contains(cells[cellIndex]))
|
|
||||||
// {
|
|
||||||
// tooCloseCells.Add(cells[cellIndex]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
return tooCloseCells;
|
return tooCloseCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,6 +661,76 @@ namespace Barotrauma
|
|||||||
return newCells;
|
return newCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenerateRuin(List<VoronoiCell> mainPath)
|
||||||
|
{
|
||||||
|
|
||||||
|
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, false), Rand.Range(5000.0f, 8000.0f, false));
|
||||||
|
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
|
||||||
|
|
||||||
|
Vector2 ruinPos = cells[Rand.Int(cells.Count, false)].Center;
|
||||||
|
|
||||||
|
int iter = 0;
|
||||||
|
|
||||||
|
while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius * 2.0f))
|
||||||
|
{
|
||||||
|
Vector2 weighedPathPos = ruinPos;
|
||||||
|
iter++;
|
||||||
|
|
||||||
|
foreach (VoronoiCell pathCell in mainPath)
|
||||||
|
{
|
||||||
|
float dist = Vector2.Distance(pathCell.Center, ruinPos);
|
||||||
|
if (dist > 10000.0f) continue;
|
||||||
|
|
||||||
|
Vector2 moveAmount = Vector2.Normalize(ruinPos - pathCell.Center) * 100000.0f / dist;
|
||||||
|
|
||||||
|
//if (weighedPathPos.Y + moveAmount.Y > borders.Bottom - ruinSize.X)
|
||||||
|
//{
|
||||||
|
// moveAmount.X = (Math.Abs(moveAmount.Y) + Math.Abs(moveAmount.X))*Math.Sign(moveAmount.X);
|
||||||
|
// moveAmount.Y = 0.0f;
|
||||||
|
//}
|
||||||
|
|
||||||
|
weighedPathPos += moveAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
ruinPos = weighedPathPos;
|
||||||
|
|
||||||
|
if (iter > 10000) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoronoiCell closestPathCell = null;
|
||||||
|
float closestDist = 0.0f;
|
||||||
|
foreach (VoronoiCell pathCell in mainPath)
|
||||||
|
{
|
||||||
|
float dist = Vector2.Distance(pathCell.Center, ruinPos);
|
||||||
|
if (closestPathCell == null || dist < closestDist)
|
||||||
|
{
|
||||||
|
closestPathCell = pathCell;
|
||||||
|
closestDist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ruin = new Ruin(closestPathCell, cells, new Rectangle((ruinPos - ruinSize * 0.5f).ToPoint(), ruinSize.ToPoint()));
|
||||||
|
|
||||||
|
ruins = new List<Ruin>();
|
||||||
|
ruins.Add(ruin);
|
||||||
|
|
||||||
|
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
positionsOfInterest.Add(new InterestingPosition(ruin.RuinShapes[i].Rect.Center.ToVector2(), PositionType.Ruin));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (RuinShape ruinShape in ruin.RuinShapes)
|
||||||
|
{
|
||||||
|
var tooClose = GetTooCloseCells(ruinShape.Rect.Center.ToVector2(), Math.Max(ruinShape.Rect.Width, ruinShape.Rect.Height));
|
||||||
|
|
||||||
|
tooClose.ForEach(c =>
|
||||||
|
{
|
||||||
|
if (c.edges.Any(e => ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2))) c.CellType = CellType.Empty;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float offsetFromWall = 10.0f)
|
public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float offsetFromWall = 10.0f)
|
||||||
{
|
{
|
||||||
if (!positionsOfInterest.Any()) return Size*0.5f;
|
if (!positionsOfInterest.Any()) return Size*0.5f;
|
||||||
@@ -889,7 +889,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
wrappingWalls[side, i].Dispose();
|
if (wrappingWalls[side, i] != null) wrappingWalls[side, i].Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,216 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class LevelGenerationParams : IPropertyObject
|
||||||
|
{
|
||||||
|
private static List<LevelGenerationParams> presets;
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float width, height;
|
||||||
|
|
||||||
|
private Vector2 voronoiSiteInterval;
|
||||||
|
//how much the sites are "scattered" on x- and y-axis
|
||||||
|
//if Vector2.Zero, the sites will just be placed in a regular grid pattern
|
||||||
|
private Vector2 voronoiSiteVariance;
|
||||||
|
|
||||||
|
//how far apart the nodes of the main path can be
|
||||||
|
//x = min interval, y = max interval
|
||||||
|
private Vector2 mainPathNodeIntervalRange;
|
||||||
|
|
||||||
|
private int smallTunnelCount;
|
||||||
|
//x = min length, y = max length
|
||||||
|
private Vector2 smallTunnelLengthRange;
|
||||||
|
|
||||||
|
//how large portion of the bottom of the level should be "carved out"
|
||||||
|
//if 0.0f, the bottom will be completely solid (making the abyss unreachable)
|
||||||
|
//if 1.0f, the bottom will be completely open
|
||||||
|
private float bottomHoleProbability;
|
||||||
|
|
||||||
|
private int ruinCount;
|
||||||
|
|
||||||
|
public Color BackgroundColor
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(1000, false)]
|
||||||
|
public int BackgroundSpriteAmount
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, ObjectProperty> ObjectProperties
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(100000.0f, false)]
|
||||||
|
public float Width
|
||||||
|
{
|
||||||
|
get { return width; }
|
||||||
|
set { width = Math.Max(value, 2000.0f); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(50000.0f, false)]
|
||||||
|
public float Height
|
||||||
|
{
|
||||||
|
get { return height; }
|
||||||
|
set { height = Math.Max(value, 2000.0f); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 VoronoiSiteInterval
|
||||||
|
{
|
||||||
|
get { return voronoiSiteInterval; }
|
||||||
|
set {
|
||||||
|
voronoiSiteInterval.X = MathHelper.Clamp(value.X, 100.0f, width/2);
|
||||||
|
voronoiSiteInterval.Y = MathHelper.Clamp(value.Y, 100.0f, height/2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 VoronoiSiteVariance
|
||||||
|
{
|
||||||
|
get { return voronoiSiteVariance; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
voronoiSiteVariance = new Vector2(
|
||||||
|
MathHelper.Clamp(value.X, 0, voronoiSiteInterval.X),
|
||||||
|
MathHelper.Clamp(value.Y, 0, voronoiSiteInterval.Y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 MainPathNodeIntervalRange
|
||||||
|
{
|
||||||
|
get { return mainPathNodeIntervalRange; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
mainPathNodeIntervalRange.X = MathHelper.Clamp(value.X, 100.0f, width / 2);
|
||||||
|
mainPathNodeIntervalRange.Y = MathHelper.Clamp(value.Y, mainPathNodeIntervalRange.X, width / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(5, false)]
|
||||||
|
public int SmallTunnelCount
|
||||||
|
{
|
||||||
|
get { return smallTunnelCount; }
|
||||||
|
set { smallTunnelCount = MathHelper.Clamp(value, 0, 100); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 SmallTunnelLengthRange
|
||||||
|
{
|
||||||
|
get { return smallTunnelLengthRange; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
smallTunnelLengthRange.X = MathHelper.Clamp(value.X, 100.0f, width);
|
||||||
|
smallTunnelLengthRange.Y = MathHelper.Clamp(value.Y, smallTunnelLengthRange.X, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(1, false)]
|
||||||
|
public int RuinCount
|
||||||
|
{
|
||||||
|
get { return ruinCount; }
|
||||||
|
set { ruinCount = MathHelper.Clamp(value, 0, 10); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(0.4f, false)]
|
||||||
|
public float BottomHoleProbability
|
||||||
|
{
|
||||||
|
get { return bottomHoleProbability; }
|
||||||
|
set { bottomHoleProbability = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||||
|
}
|
||||||
|
|
||||||
|
//public LevelGenerationParams()
|
||||||
|
//{
|
||||||
|
// Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
||||||
|
|
||||||
|
// width = 100000.0f;
|
||||||
|
// height = 50000.0f;
|
||||||
|
|
||||||
|
// voronoiSiteInterval = 2000.0f;
|
||||||
|
// voronoiSiteVariance = new Vector2(voronoiSiteInterval, voronoiSiteInterval) * 0.4f;
|
||||||
|
|
||||||
|
// mainPathNodeIntervalRange = new Vector2(5000.0f, 10000.0f);
|
||||||
|
|
||||||
|
// float brightness = Rand.Range(1.0f, 1.3f, false);
|
||||||
|
// BackgroundColor = Color.Lerp(new Color(11, 18, 26), new Color(50, 46, 20), Rand.Range(0.0f, 1.0f, false)) * brightness;
|
||||||
|
// BackgroundColor = new Color(BackgroundColor, 1.0f);
|
||||||
|
|
||||||
|
// smallTunnelCount = 5;
|
||||||
|
// smallTunnelLengthRange = new Vector2(5000.0f, 10000.0f);
|
||||||
|
|
||||||
|
// ruinCount = 1;
|
||||||
|
|
||||||
|
// bottomHoleProbability = Rand.Range(0.1f, 0.8f, false);
|
||||||
|
|
||||||
|
// BackgroundSpriteAmount = (int)((new Vector2(width, height)).Length() / 100);
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static LevelGenerationParams GetRandom(string seed)
|
||||||
|
{
|
||||||
|
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
||||||
|
|
||||||
|
if (presets == null || !presets.Any())
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Level generation presets not found - using default presets");
|
||||||
|
return new LevelGenerationParams(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return presets[Rand.Range(0, presets.Count, false)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private LevelGenerationParams(XElement element)
|
||||||
|
{
|
||||||
|
Name = element==null ? "default" : element.Name.ToString();
|
||||||
|
ObjectProperties = ObjectProperty.InitProperties(this, element);
|
||||||
|
|
||||||
|
Vector3 colorVector = ToolBox.GetAttributeVector3(element, "BackgroundColor", new Vector3(50, 46, 20));
|
||||||
|
BackgroundColor = new Color((int)colorVector.X, (int)colorVector.Y, (int)colorVector.Z);
|
||||||
|
|
||||||
|
VoronoiSiteInterval = ToolBox.GetAttributeVector2(element, "VoronoiSiteInterval", new Vector2(3000, 3000));
|
||||||
|
|
||||||
|
VoronoiSiteVariance = ToolBox.GetAttributeVector2(element, "VoronoiSiteVariance", new Vector2(voronoiSiteInterval.X, voronoiSiteInterval.Y) * 0.4f);
|
||||||
|
|
||||||
|
MainPathNodeIntervalRange = ToolBox.GetAttributeVector2(element, "MainPathNodeIntervalRange", new Vector2(5000.0f, 10000.0f));
|
||||||
|
|
||||||
|
SmallTunnelLengthRange = ToolBox.GetAttributeVector2(element, "SmallTunnelLengthRange", new Vector2(5000.0f, 10000.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoadPresets()
|
||||||
|
{
|
||||||
|
presets = new List<LevelGenerationParams>();
|
||||||
|
|
||||||
|
var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.LevelGenerationPresets);
|
||||||
|
if (!files.Any())
|
||||||
|
{
|
||||||
|
files.Add("Content/Map/LevelGenerationParameters.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
|
||||||
|
XDocument doc = ToolBox.TryLoadXml(file);
|
||||||
|
if (doc == null || doc.Root == null) return;
|
||||||
|
|
||||||
|
foreach (XElement element in doc.Root.Elements())
|
||||||
|
{
|
||||||
|
presets.Add(new LevelGenerationParams(element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,28 +48,16 @@ namespace Barotrauma
|
|||||||
get { return midPos; }
|
get { return midPos; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrappingWall(List<VoronoiCell> pathCells, List<VoronoiCell> mapCells, float maxY, int dir = -1)
|
public WrappingWall(List<VoronoiCell> pathCells, List<VoronoiCell> mapCells, Rectangle ignoredArea, int dir = -1)
|
||||||
{
|
{
|
||||||
cells = new List<VoronoiCell>();
|
cells = new List<VoronoiCell>();
|
||||||
|
|
||||||
VoronoiCell lowestPathCell = null;
|
|
||||||
foreach (VoronoiCell pathCell in pathCells)
|
|
||||||
{
|
|
||||||
if (lowestPathCell == null || pathCell.Center.Y < lowestPathCell.Center.Y)
|
|
||||||
{
|
|
||||||
lowestPathCell = pathCell;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float bottomY = Math.Max(lowestPathCell.Center.Y, maxY);
|
|
||||||
|
|
||||||
VoronoiCell edgeCell = null;
|
VoronoiCell edgeCell = null;
|
||||||
foreach (VoronoiCell cell in mapCells)
|
foreach (VoronoiCell cell in mapCells)
|
||||||
{
|
{
|
||||||
if (cell.Center.Y > bottomY) continue;
|
if (ignoredArea.Contains(cell.Center)) continue;
|
||||||
if (edgeCell == null
|
if (Math.Sign(cell.Center.X - ignoredArea.Center.X) != Math.Sign(dir)) continue;
|
||||||
|| (dir < 0 && cell.Center.X < edgeCell.Center.X)
|
if (edgeCell == null || cell.Center.Y < edgeCell.Center.Y)
|
||||||
|| (dir > 0 && cell.Center.X > edgeCell.Center.X))
|
|
||||||
{
|
{
|
||||||
edgeCell = cell;
|
edgeCell = cell;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static object GetAttributeObject(XElement element, string name)
|
public static object GetAttributeObject(XElement element, string name)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return null;
|
if (element == null || element.Attribute(name) == null) return null;
|
||||||
return GetAttributeObject(element.Attribute(name));
|
return GetAttributeObject(element.Attribute(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static string GetAttributeString(XElement element, string name, string defaultValue)
|
public static string GetAttributeString(XElement element, string name, string defaultValue)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return defaultValue;
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
return GetAttributeString(element.Attribute(name), defaultValue);
|
return GetAttributeString(element.Attribute(name), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static float GetAttributeFloat(XElement element, string name, float defaultValue)
|
public static float GetAttributeFloat(XElement element, string name, float defaultValue)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return defaultValue;
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
|
|
||||||
float val = defaultValue;
|
float val = defaultValue;
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static int GetAttributeInt(XElement element, string name, int defaultValue)
|
public static int GetAttributeInt(XElement element, string name, int defaultValue)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return defaultValue;
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
|
|
||||||
int val = defaultValue;
|
int val = defaultValue;
|
||||||
|
|
||||||
@@ -176,10 +176,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static bool GetAttributeBool(XElement element, string name, bool defaultValue)
|
public static bool GetAttributeBool(XElement element, string name, bool defaultValue)
|
||||||
{
|
{
|
||||||
var attribute = element.Attribute(name);
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
if (attribute == null) return defaultValue;
|
|
||||||
|
|
||||||
return GetAttributeBool(attribute, defaultValue);
|
return GetAttributeBool(element.Attribute(name), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool GetAttributeBool(XAttribute attribute, bool defaultValue)
|
public static bool GetAttributeBool(XAttribute attribute, bool defaultValue)
|
||||||
@@ -206,16 +205,25 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static Vector2 GetAttributeVector2(XElement element, string name, Vector2 defaultValue)
|
public static Vector2 GetAttributeVector2(XElement element, string name, Vector2 defaultValue)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return defaultValue;
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
|
|
||||||
string val = element.Attribute(name).Value;
|
string val = element.Attribute(name).Value;
|
||||||
|
|
||||||
return ParseToVector2(val);
|
return ParseToVector2(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector3 GetAttributeVector3(XElement element, string name, Vector3 defaultValue)
|
||||||
|
{
|
||||||
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
|
|
||||||
|
string val = element.Attribute(name).Value;
|
||||||
|
|
||||||
|
return ParseToVector3(val);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector4 GetAttributeVector4(XElement element, string name, Vector4 defaultValue)
|
public static Vector4 GetAttributeVector4(XElement element, string name, Vector4 defaultValue)
|
||||||
{
|
{
|
||||||
if (element.Attribute(name) == null) return defaultValue;
|
if (element == null || element.Attribute(name) == null) return defaultValue;
|
||||||
|
|
||||||
string val = element.Attribute(name).Value;
|
string val = element.Attribute(name).Value;
|
||||||
|
|
||||||
@@ -259,6 +267,26 @@ namespace Barotrauma
|
|||||||
return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture);
|
return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector3 ParseToVector3(string stringVector3, bool errorMessages = true)
|
||||||
|
{
|
||||||
|
string[] components = stringVector3.Split(',');
|
||||||
|
|
||||||
|
Vector3 vector = Vector3.Zero;
|
||||||
|
|
||||||
|
if (components.Length!=3)
|
||||||
|
{
|
||||||
|
if (!errorMessages) return vector;
|
||||||
|
DebugConsole.ThrowError("Failed to parse the string ''"+stringVector3+"'' to Vector3");
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
float.TryParse(components[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.X);
|
||||||
|
float.TryParse(components[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Y);
|
||||||
|
float.TryParse(components[2], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Z);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector4 ParseToVector4(string stringVector4, bool errorMessages = true)
|
public static Vector4 ParseToVector4(string stringVector4, bool errorMessages = true)
|
||||||
{
|
{
|
||||||
string[] components = stringVector4.Split(',');
|
string[] components = stringVector4.Split(',');
|
||||||
|
|||||||
Reference in New Issue
Block a user