(5a377a8ee) Unstable v0.9.1000.0

This commit is contained in:
Juan Pablo Arce
2020-05-13 12:55:42 -03:00
parent b143329701
commit a1ca41aa5d
426 changed files with 14384 additions and 5708 deletions
@@ -27,19 +27,19 @@ namespace Barotrauma
foreach (GraphEdge ge in graphEdges)
{
if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.001f) continue;
if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.001f) { continue; }
for (int i = 0; i < 2; i++)
{
Site site = (i == 0) ? ge.Site1 : ge.Site2;
int x = (int)(Math.Floor((site.Coord.X-borders.X) / gridCellSize));
int y = (int)(Math.Floor((site.Coord.Y-borders.Y) / gridCellSize));
int x = (int)(Math.Floor((site.Coord.X - borders.X) / gridCellSize));
int y = (int)(Math.Floor((site.Coord.Y - borders.Y) / gridCellSize));
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);
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)
{
@@ -60,14 +60,62 @@ namespace Barotrauma
}
}
//add edges to the borders of the graph
foreach (var cell in cells)
{
Vector2? point1 = null, point2 = null;
foreach (GraphEdge ge in cell.Edges)
{
if (MathUtils.NearlyEqual(ge.Point1.X, borders.X) || MathUtils.NearlyEqual(ge.Point1.X, borders.Right) ||
MathUtils.NearlyEqual(ge.Point1.Y, borders.Y) || MathUtils.NearlyEqual(ge.Point1.Y, borders.Bottom))
{
if (point1 == null)
{
point1 = ge.Point1;
}
else if (point2 == null)
{
if (MathUtils.NearlyEqual(point1.Value, ge.Point1)) { continue; }
point2 = ge.Point1;
}
}
if (MathUtils.NearlyEqual(ge.Point2.X, borders.X) || MathUtils.NearlyEqual(ge.Point2.X, borders.Right) ||
MathUtils.NearlyEqual(ge.Point2.Y, borders.Y) || MathUtils.NearlyEqual(ge.Point2.Y, borders.Bottom))
{
if (point1 == null)
{
point1 = ge.Point2;
}
else
{
if (MathUtils.NearlyEqual(point1.Value, ge.Point2)) { continue; }
point2 = ge.Point2;
}
}
if (point1.HasValue && point2.HasValue)
{
Debug.Assert(point1 != point2);
var newEdge = new GraphEdge(point1.Value, point2.Value)
{
Cell1 = cell,
IsSolid = true,
Site1 = cell.Site,
OutsideLevel = true
};
cell.Edges.Add(newEdge);
break;
}
}
}
return cells;
}
private static Vector2 GetEdgeNormal(GraphEdge edge, VoronoiCell cell = null)
{
if (cell == null) cell = edge.AdjacentCell(null);
if (cell == null) return Vector2.UnitX;
if (cell == null) { cell = edge.AdjacentCell(null); }
if (cell == null) { return Vector2.UnitX; }
CompareCCW compare = new CompareCCW(cell.Center);
if (compare.Compare(edge.Point1, edge.Point2) == -1)
@@ -77,9 +125,7 @@ namespace Barotrauma
edge.Point2 = temp;
}
Vector2 normal = Vector2.Zero;
normal = Vector2.Normalize(edge.Point2 - edge.Point1);
Vector2 normal = Vector2.Normalize(edge.Point2 - edge.Point1);
Vector2 diffToCell = Vector2.Normalize(cell.Center - edge.Point2);
normal = new Vector2(-normal.Y, normal.X);
@@ -148,7 +194,7 @@ namespace Barotrauma
foreach (GraphEdge edge in currentCell.Edges)
{
var adjacentCell = edge.AdjacentCell(currentCell);
if (limits.Contains(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y))
if (adjacentCell != null && limits.Contains(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y))
{
allowedEdges.Add(edge);
}
@@ -161,6 +207,7 @@ namespace Barotrauma
for (int i = 0; i < currentCell.Edges.Count; i++)
{
var adjacentCell = currentCell.Edges[i].AdjacentCell(currentCell);
if (adjacentCell == null) { continue; }
double dist = MathUtils.Distance(
adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y,
targetCells[currentTargetIndex].Site.Coord.X, targetCells[currentTargetIndex].Site.Coord.Y);
@@ -18,6 +18,10 @@ namespace Barotrauma
//all entities are disabled after they reach this depth
public const int MaxEntityDepth = -300000;
public const float ShaftHeight = 1000.0f;
/// <summary>
/// The level generator won't try to adjust the width of the main path above this limit.
/// </summary>
public const int MaxSubmarineWidth = 16000;
public static Level Loaded
{
@@ -141,8 +145,6 @@ namespace Barotrauma
get { return positionsOfInterest; }
}
public readonly List<InterestingPosition> UsedPositions = new List<InterestingPosition>();
public Submarine StartOutpost { get; private set; }
public Submarine EndOutpost { get; private set; }
@@ -166,6 +168,11 @@ namespace Barotrauma
private set;
}
public List<Entity> EntitiesBeforeGenerate { get; private set; } = new List<Entity>();
public int EntityCountBeforeGenerate { get; private set; }
public int EntityCountAfterGenerate { get; private set; }
public float Difficulty
{
get;
@@ -281,8 +288,11 @@ namespace Barotrauma
public void Generate(bool mirror)
{
if (loaded != null) loaded.Remove();
if (loaded != null) { loaded.Remove(); }
loaded = this;
EntitiesBeforeGenerate = GetEntityList();
EntityCountBeforeGenerate = EntitiesBeforeGenerate.Count();
levelObjectManager = new LevelObjectManager();
@@ -316,26 +326,25 @@ namespace Barotrauma
SeaFloorTopPos = generationParams.SeaFloorDepth + generationParams.MountainHeightMax + generationParams.SeaFloorVariance;
int minWidth = 6500;
int maxWidth = 50000;
if (Submarine.MainSub != null)
{
Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders();
dockedSubBorders.Inflate(dockedSubBorders.Size.ToVector2() * 0.05f);
dockedSubBorders.Inflate(dockedSubBorders.Size.ToVector2() * 0.15f);
minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height));
minWidth = Math.Min(minWidth, maxWidth);
minWidth = Math.Min(minWidth, MaxSubmarineWidth);
}
Rectangle pathBorders = borders;
pathBorders.Inflate(-minWidth * 2, -minWidth);
pathBorders.Inflate(-Math.Min(minWidth * 2, MaxSubmarineWidth), -minWidth);
Debug.Assert(pathBorders.Width > 0 && pathBorders.Height > 0, "The size of the level's path area was negative.");
startPosition = new Point(
Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server),
minWidth,
Rand.Range(borders.Height / 2, borders.Height - minWidth * 2, Rand.RandSync.Server));
endPosition = new Point(
borders.Width - Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server),
borders.Width - minWidth,
Rand.Range(borders.Height / 2, borders.Height - minWidth * 2, Rand.RandSync.Server));
//----------------------------------------------------------------------------------
@@ -348,19 +357,25 @@ namespace Barotrauma
Point nodeInterval = generationParams.MainPathNodeIntervalRange;
for (int x = startPosition.X + nodeInterval.X;
x < endPosition.X - nodeInterval.X;
x < endPosition.X - nodeInterval.X;
x += Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server))
{
pathNodes.Add(new Point(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, Rand.RandSync.Server)));
}
pathNodes.Add(new Point(endPosition.X, borders.Height));
if (pathNodes.Count <= 2)
if (pathNodes.Count == 1)
{
pathNodes.Insert(1, borders.Center);
pathNodes.Add(new Point(pathBorders.Center.X, pathBorders.Y));
}
//if all nodes ended up high up in the level, move one down to make sure we utilize the full height of the level
else if (pathNodes.GetRange(1, pathNodes.Count - 1).All(p => p.Y > pathBorders.Y + pathBorders.Height * 0.25f))
{
int nodeIndex = Rand.Range(1, pathNodes.Count, Rand.RandSync.Server);
pathNodes[nodeIndex] = new Point(pathNodes[nodeIndex].X, pathBorders.Y);
}
pathNodes.Add(new Point(endPosition.X, borders.Height));
GenerateTunnels(pathNodes, minWidth);
//----------------------------------------------------------------------------------
@@ -539,21 +554,21 @@ namespace Barotrauma
{
foreach (GraphEdge edge in cell.Edges)
{
if (mirroredEdges.Contains(edge)) continue;
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))
if (edge.Site1 != null && !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 % 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 != null && !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 % GridCellSize >= 0.0f) { edge.Site2.Coord.X += 1.0f; }
edge.Site2.Coord.X = borders.Width - edge.Site2.Coord.X;
mirroredSites.Add(edge.Site2);
}
@@ -759,6 +774,8 @@ namespace Barotrauma
DebugConsole.NewMessage("Generated level with the seed " + seed + " (type: " + generationParams.Name + ")", Color.White);
}
EntityCountAfterGenerate = Entity.GetEntityList().Count();
//assign an ID to make entity events work
ID = FindFreeID();
}
@@ -1531,6 +1548,13 @@ namespace Barotrauma
return tempCells;
}
public string GetWreckIDTag(string originalTag, Submarine wreck)
{
string shortSeed = ToolBox.StringToInt(seed + wreck.Info.Name).ToString();
if (shortSeed.Length > 6) { shortSeed = shortSeed.Substring(0, 6); }
return originalTag + "_" + shortSeed;
}
// For debugging
private readonly Dictionary<Submarine, List<Vector2>> wreckPositions = new Dictionary<Submarine, List<Vector2>>();
private readonly Dictionary<Submarine, List<Rectangle>> blockedRects = new Dictionary<Submarine, List<Rectangle>>();
@@ -1546,6 +1570,7 @@ namespace Barotrauma
return;
}
wreckFiles.Shuffle(Rand.RandSync.Server);
int wreckCount = Math.Min(Loaded.GenerationParams.WreckCount, wreckFiles.Count);
// Min distance between a wreck and the start/end/other wreck.
float minDistance = Sonar.DefaultSonarRange;
@@ -1610,7 +1635,6 @@ namespace Barotrauma
Type = SubmarineInfo.SubmarineType.Wreck
};
Submarine wreck = new Submarine(info);
//wreck.Load(unloadPrevious: false);
wreck.MakeWreck();
tempSW.Stop();
Debug.WriteLine($"Wreck {wreck.Info.Name} loaded in { tempSW.ElapsedMilliseconds.ToString()} (ms)");
@@ -1626,17 +1650,18 @@ namespace Barotrauma
hull.WaterVolume = hull.Volume * Rand.Range(Loaded.GenerationParams.WreckFloodingHullMinWaterPercentage, Loaded.GenerationParams.WreckFloodingHullMaxWaterPercentage, Rand.RandSync.Server);
}
}
if (Rand.Value(Rand.RandSync.Server) <= Loaded.GenerationParams.ThalamusProbability)
// Only spawn thalamus when the wreck has some thalamus items defined.
if (Rand.Value(Rand.RandSync.Server) <= Loaded.GenerationParams.ThalamusProbability && wreck.GetItems(false).Any(i => i.Prefab.Category == MapEntityCategory.Thalamus))
{
if (!wreck.CreateThalamus())
if (!wreck.CreateWreckAI())
{
DebugConsole.NewMessage($"Failed to create thalamus inside {wreckName}.", Color.Red);
wreck.DisableThalamus();
DebugConsole.NewMessage($"Failed to create wreck AI inside {wreckName}.", Color.Red);
wreck.DisableWreckAI();
}
}
else
{
wreck.DisableThalamus();
wreck.DisableWreckAI();
}
}
else
@@ -1959,13 +1984,13 @@ namespace Barotrauma
int corpseCount = Rand.Range(Loaded.GenerationParams.MinCorpseCount, Loaded.GenerationParams.MaxCorpseCount);
var allSpawnPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == wreck && wp.CurrentHull != null);
var pathPoints = allSpawnPoints.FindAll(wp => wp.SpawnType == SpawnType.Path);
pathPoints.Shuffle(Rand.RandSync.Unsynced);
var corpsePoints = allSpawnPoints.FindAll(wp => wp.SpawnType == SpawnType.Corpse);
var spawnPoints = corpsePoints.Union(pathPoints).ToList();
spawnPoints.Shuffle(Rand.RandSync.Unsynced);
corpsePoints.Shuffle(Rand.RandSync.Unsynced);
int spawnCounter = 0;
for (int j = 0; j < corpseCount; j++)
{
WayPoint sp = spawnPoints.FirstOrDefault();
WayPoint sp = corpsePoints.FirstOrDefault() ?? pathPoints.FirstOrDefault();
JobPrefab job = sp?.AssignedJob;
CorpsePrefab selectedPrefab;
if (job == null)
@@ -1979,18 +2004,19 @@ namespace Barotrauma
selectedPrefab = GetCorpsePrefab(p => p.SpawnPosition == PositionType.Wreck && (p.Job == "any" || p.Job == job.Identifier));
if (selectedPrefab == null)
{
spawnPoints.Remove(sp);
sp = spawnPoints.FirstOrDefault(sp => sp.AssignedJob == null);
corpsePoints.Remove(sp);
pathPoints.Remove(sp);
sp = corpsePoints.FirstOrDefault(sp => sp.AssignedJob == null) ?? pathPoints.FirstOrDefault(sp => sp.AssignedJob == null);
// Deduce the job from the selected prefab
selectedPrefab = GetCorpsePrefab(p => p.SpawnPosition == PositionType.Wreck);
job = GetJobPrefab();
}
}
if (selectedPrefab == null) { continue; }
Vector2 pos;
Vector2 worldPos;
if (sp == null)
{
if (!TryGetExtraSpawnPoint(out pos))
if (!TryGetExtraSpawnPoint(out worldPos))
{
break;
}
@@ -1998,15 +2024,17 @@ namespace Barotrauma
}
else
{
pos = sp.WorldPosition;
spawnPoints.Remove(sp);
worldPos = sp.WorldPosition;
corpsePoints.Remove(sp);
pathPoints.Remove(sp);
}
if (job == null) { continue; }
var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: job);
var corpse = Character.Create(CharacterPrefab.HumanConfigFile, pos, ToolBox.RandomSeed(8), characterInfo, hasAi: true, createNetworkEvent: true);
var corpse = Character.Create(CharacterPrefab.HumanConfigFile, worldPos, ToolBox.RandomSeed(8), characterInfo, hasAi: true, createNetworkEvent: true);
corpse.AnimController.FindHull(worldPos, true);
corpse.TeamID = Character.TeamType.None;
corpse.EnableDespawn = false;
selectedPrefab.GiveItems(corpse);
selectedPrefab.GiveItems(corpse, wreck);
corpse.Kill(CauseOfDeathType.Unknown, causeOfDeathAffliction: null, log: false);
spawnCounter++;
@@ -2018,9 +2046,9 @@ namespace Barotrauma
JobPrefab GetJobPrefab() => selectedPrefab.Job != null && selectedPrefab.Job != "any" ? JobPrefab.Get(selectedPrefab.Job) : JobPrefab.Random();
}
#if DEBUG
DebugConsole.NewMessage($"{spawnCounter}/{corpseCount} corpses spawned in {wreck.Info.Name}.", spawnCounter == corpseCount ? Color.Green : Color.Yellow);
#endif
bool TryGetExtraSpawnPoint(out Vector2 point)
{
point = Vector2.Zero;
@@ -238,7 +238,8 @@ namespace Barotrauma
}
[Editable, Serialize("5000, 10000", true, description: "The distance between the nodes that are used to generate the main path through the level (min, max). Larger values produce a straighter path.")]
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
Serialize("5000, 10000", true, description: "The distance between the nodes that are used to generate the main path through the level (min, max). Larger values produce a straighter path.")]
public Point MainPathNodeIntervalRange
{
get { return mainPathNodeIntervalRange; }
@@ -256,7 +257,8 @@ namespace Barotrauma
set { smallTunnelCount = MathHelper.Clamp(value, 0, 100); }
}
[Editable, Serialize("5000, 10000", true, description: "The minimum and maximum length of small tunnels placed along the main path.")]
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
Serialize("5000, 10000", true, description: "The minimum and maximum length of small tunnels placed along the main path.")]
public Point SmallTunnelLengthRange
{
get { return smallTunnelLengthRange; }
@@ -349,8 +351,7 @@ namespace Barotrauma
[Serialize(5, true, description: "The maximum number of corpses per wreck."), Editable(MinValueInt = 0, MaxValueInt = 20)]
public int MaxCorpseCount { get; set; }
// TODO: default to 0
[Serialize(1f, true, description: "How likely is it that a Thalamus inhabits a wreck. Percentage from 0 to 1 per wreck."), Editable(MinValueFloat = 0, MaxValueFloat = 1)]
[Serialize(0.0f, true, description: "How likely is it that a Thalamus inhabits a wreck. Percentage from 0 to 1 per wreck."), Editable(MinValueFloat = 0, MaxValueFloat = 1)]
public float ThalamusProbability { get; set; }
[Serialize(0.5f, true, description: "How likely the water level of a hull inside a wreck is randomly set."), Editable(MinValueFloat = 0, MaxValueFloat = 1)]
@@ -358,19 +358,23 @@ namespace Barotrauma
return;
}
//check if there are any other contacts with the entity
//check if there are contacts with any other fixture of the trigger
//(the OnSeparation callback happens when two fixtures separate,
//e.g. if a body stops touching the circular fixture at the end of a capsule-shaped body)
ContactEdge contactEdge = fixtureA.Body.ContactList;
while (contactEdge != null)
{
if (contactEdge.Contact != null &&
contactEdge.Contact.Enabled &&
contactEdge.Contact.IsTouching)
{
var otherEntity = GetEntity(contactEdge.Contact.FixtureB == fixtureB ?
contactEdge.Contact.FixtureB :
contactEdge.Contact.FixtureA);
if (otherEntity == entity) return;
if (contactEdge.Contact.FixtureA != fixtureA && contactEdge.Contact.FixtureB != fixtureA)
{
var otherEntity = GetEntity(contactEdge.Contact.FixtureB == fixtureB ?
contactEdge.Contact.FixtureB :
contactEdge.Contact.FixtureA);
if (otherEntity == entity) { return; }
}
}
contactEdge = contactEdge.Next;
}
@@ -418,10 +422,20 @@ namespace Barotrauma
public void Update(float deltaTime)
{
if (ParentTrigger != null && !ParentTrigger.IsTriggered) return;
if (ParentTrigger != null && !ParentTrigger.IsTriggered) { return; }
triggerers.RemoveWhere(t => t.Removed);
if (physicsBody != null)
{
//failsafe to ensure triggerers get removed when they're far from the trigger
float maxExtent = Math.Max(ConvertUnits.ToDisplayUnits(physicsBody.GetMaxExtent() * 5), 5000.0f);
triggerers.RemoveWhere(t =>
{
return Vector2.Distance(t.WorldPosition, WorldPosition) > maxExtent;
});
}
bool isNotClient = true;
#if CLIENT
isNotClient = GameMain.Client == null;
@@ -511,6 +525,7 @@ namespace Barotrauma
ApplyForce(character.AnimController.Collider, deltaTime);
foreach (Limb limb in character.AnimController.Limbs)
{
if (limb.IsSevered) { continue; }
ApplyForce(limb.body, deltaTime);
}
}
@@ -1,8 +1,8 @@
using Microsoft.Xna.Framework;
using Barotrauma.IO;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma.RuinGeneration
@@ -174,7 +174,7 @@ namespace Barotrauma.RuinGeneration
public static void SaveAll()
{
XmlWriterSettings settings = new XmlWriterSettings
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
NewLineOnAttributes = true
@@ -654,13 +654,14 @@ namespace Barotrauma.RuinGeneration
{
connectionPanel.Locked = true;
connectionPanel.CanBeSelected = false;
connectionPanel.Item.ShouldBeSaved = false;
}
// Hide wires for now
// Hide wires
if (ic is Wire wire)
{
wire.Hidden = true;
wire.CanBeSelected = false;
wire.Item.ShouldBeSaved = false;
}
}
}