Unstable v0.1300.0.2

This commit is contained in:
Markus Isberg
2021-03-12 15:57:04 +02:00
parent 0f6de8ada9
commit 874616027b
145 changed files with 1897 additions and 939 deletions
@@ -202,6 +202,12 @@ namespace Barotrauma
get { return startPosition.ToVector2(); }
}
private Vector2 startExitPosition;
public Vector2 StartExitPosition
{
get { return startExitPosition; }
}
public Point Size
{
get { return LevelData.Size; }
@@ -212,6 +218,12 @@ namespace Barotrauma
get { return endPosition.ToVector2(); }
}
private Vector2 endExitPosition;
public Vector2 EndExitPosition
{
get { return endExitPosition; }
}
public int BottomPos
{
get;
@@ -424,31 +436,36 @@ namespace Barotrauma
SeaFloorTopPos = GenerationParams.SeaFloorDepth + GenerationParams.MountainHeightMax + GenerationParams.SeaFloorVariance;
int minWidth = Math.Min(GenerationParams.MinTunnelRadius, MaxSubmarineWidth);
int minMainPathWidth = Math.Min(GenerationParams.MinTunnelRadius, MaxSubmarineWidth);
int minWidth = 500;
if (Submarine.MainSub != null)
{
Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders();
dockedSubBorders.Inflate(dockedSubBorders.Size.ToVector2() * 0.15f);
minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height));
minWidth = Math.Min(minWidth, MaxSubmarineWidth);
minWidth = Math.Max(dockedSubBorders.Width, dockedSubBorders.Height);
minMainPathWidth = Math.Max(minMainPathWidth, minWidth);
minMainPathWidth = Math.Min(minMainPathWidth, MaxSubmarineWidth);
}
minWidth = Math.Min(minWidth, borders.Width / 5);
LevelData.MinMainPathWidth = minWidth;
minMainPathWidth = Math.Min(minMainPathWidth, borders.Width / 5);
LevelData.MinMainPathWidth = minMainPathWidth;
Rectangle pathBorders = borders;
pathBorders.Inflate(
-Math.Min(Math.Min(minWidth * 2, MaxSubmarineWidth), borders.Width / 5),
-Math.Min(minWidth, borders.Height / 5));
-Math.Min(Math.Min(minMainPathWidth * 2, MaxSubmarineWidth), borders.Width / 5),
-Math.Min(minMainPathWidth, borders.Height / 5));
if (pathBorders.Width <= 0) { throw new InvalidOperationException($"The width of the level's path area is invalid ({pathBorders.Width})"); }
if (pathBorders.Height <= 0) { throw new InvalidOperationException($"The height of the level's path area is invalid ({pathBorders.Height})"); }
startPosition = new Point(
(int)MathHelper.Lerp(minWidth, borders.Width - minWidth, GenerationParams.StartPosition.X),
(int)MathHelper.Lerp(borders.Bottom - minWidth, borders.Y + minWidth, GenerationParams.StartPosition.Y));
(int)MathHelper.Lerp(minMainPathWidth, borders.Width - minMainPathWidth, GenerationParams.StartPosition.X),
(int)MathHelper.Lerp(borders.Bottom - Math.Max(minMainPathWidth, ExitDistance * 1.5f), borders.Y + minMainPathWidth, GenerationParams.StartPosition.Y));
startExitPosition = new Vector2(startPosition.X, borders.Bottom);
endPosition = new Point(
(int)MathHelper.Lerp(minWidth, borders.Width - minWidth, GenerationParams.EndPosition.X),
(int)MathHelper.Lerp(borders.Bottom - minWidth, borders.Y + minWidth, GenerationParams.EndPosition.Y));
(int)MathHelper.Lerp(minMainPathWidth, borders.Width - minMainPathWidth, GenerationParams.EndPosition.X),
(int)MathHelper.Lerp(borders.Bottom - Math.Max(minMainPathWidth, ExitDistance * 1.5f), borders.Y + minMainPathWidth, GenerationParams.EndPosition.Y));
endExitPosition = new Vector2(endPosition.X, borders.Bottom);
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.Server));
@@ -459,14 +476,32 @@ namespace Barotrauma
Tunnel mainPath = new Tunnel(
TunnelType.MainPath,
GeneratePathNodes(startPosition, endPosition, pathBorders, null, GenerationParams.MainPathVariance),
minWidth, parentTunnel: null);
minMainPathWidth, parentTunnel: null);
Tunnels.Add(mainPath);
Tunnel startPath = null, endPath = null;
if (Mirrored ? !HasEndOutpost() : !HasStartOutpost())
{
startPath = new Tunnel(
TunnelType.SidePath,
new List<Point>() { startExitPosition.ToPoint(), startPosition },
minWidth / 2, parentTunnel: mainPath);
Tunnels.Add(startPath);
}
if (Mirrored ? !HasStartOutpost() : !HasEndOutpost())
{
endPath = new Tunnel(
TunnelType.SidePath,
new List<Point>() { endPosition, endExitPosition.ToPoint() },
minWidth / 2, parentTunnel: mainPath);
Tunnels.Add(endPath);
}
int sideTunnelCount = Rand.Range(GenerationParams.SideTunnelCount.X, GenerationParams.SideTunnelCount.Y + 1, Rand.RandSync.Server);
for (int j = 0; j < sideTunnelCount; j++)
{
if (mainPath.Nodes.Count < 4) { break; }
var validTunnels = Tunnels.FindAll(t => t.Type != TunnelType.Cave);
var validTunnels = Tunnels.FindAll(t => t.Type != TunnelType.Cave && t != startPath && t != endPath);
Tunnel tunnelToBranchOff = validTunnels[Rand.Int(validTunnels.Count, Rand.RandSync.Server)];
if (tunnelToBranchOff == null) { tunnelToBranchOff = mainPath; }
@@ -650,7 +685,7 @@ namespace Barotrauma
var potentialIslands = new List<VoronoiCell>();
foreach (var cell in pathCells)
{
if (GetDistToTunnel(cell.Center, mainPath) < minWidth) { continue; }
if (GetDistToTunnel(cell.Center, mainPath) < minMainPathWidth) { continue; }
if (cell.Edges.Any(e => e.AdjacentCell(cell)?.CellType != CellType.Path || e.NextToCave)) { continue; }
potentialIslands.Add(cell);
}
@@ -672,6 +707,7 @@ namespace Barotrauma
}
startPosition.X = (int)pathCells[0].Site.Coord.X;
startExitPosition.X = startPosition.X;
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.Server));
@@ -691,7 +727,7 @@ namespace Barotrauma
});
int xPadding = borders.Width / 5;
pathCells.AddRange(CreateHoles(GenerationParams.BottomHoleProbability, new Rectangle(xPadding, 0, borders.Width - xPadding * 2, Size.Y / 2), minWidth));
pathCells.AddRange(CreateHoles(GenerationParams.BottomHoleProbability, new Rectangle(xPadding, 0, borders.Width - xPadding * 2, Size.Y / 2), minMainPathWidth));
foreach (VoronoiCell cell in cells)
{
@@ -801,6 +837,9 @@ namespace Barotrauma
startPosition.X = borders.Width - startPosition.X;
endPosition.X = borders.Width - endPosition.X;
startExitPosition.X = borders.Width - startExitPosition.X;
endExitPosition.X = borders.Width - endExitPosition.X;
CalculateTunnelDistanceField(density: 1000);
}
@@ -863,8 +902,8 @@ namespace Barotrauma
{
if (pos.PositionType != PositionType.MainPath && pos.PositionType != PositionType.SidePath) { continue; }
if (pos.Position.X < 5000 || pos.Position.X > Size.X - 5000) { continue; }
if (Math.Abs(pos.Position.X - StartPosition.X) < minWidth * 2 || Math.Abs(pos.Position.X - EndPosition.X) < minWidth * 2) { continue; }
if (GetTooCloseCells(pos.Position.ToVector2(), minWidth * 0.7f).Count > 0) { continue; }
if (Math.Abs(pos.Position.X - StartPosition.X) < minMainPathWidth * 2 || Math.Abs(pos.Position.X - EndPosition.X) < minMainPathWidth * 2) { continue; }
if (GetTooCloseCells(pos.Position.ToVector2(), minMainPathWidth * 0.7f).Count > 0) { continue; }
iceChunkPositions.Add(pos.Position);
}
@@ -875,7 +914,7 @@ namespace Barotrauma
float chunkRadius = Rand.Range(500.0f, 1000.0f, Rand.RandSync.Server);
var vertices = CaveGenerator.CreateRandomChunk(chunkRadius, 8, chunkRadius * 0.8f);
var chunk = CreateIceChunk(vertices, selectedPos.ToVector2());
chunk.MoveAmount = new Vector2(0.0f, minWidth * 0.7f);
chunk.MoveAmount = new Vector2(0.0f, minMainPathWidth * 0.7f);
chunk.MoveSpeed = Rand.Range(100.0f, 200.0f, Rand.RandSync.Server);
ExtraWalls.Add(chunk);
iceChunkPositions.Remove(selectedPos);
@@ -1039,17 +1078,23 @@ namespace Barotrauma
if (mirror)
{
Point temp = startPosition;
Point tempP = startPosition;
startPosition = endPosition;
endPosition = temp;
endPosition = tempP;
Vector2 tempV = startExitPosition;
startExitPosition = endExitPosition;
endExitPosition = tempV;
}
if (StartOutpost != null)
{
startPosition = new Point((int)StartOutpost.WorldPosition.X, (int)StartOutpost.WorldPosition.Y);
startExitPosition = StartOutpost.WorldPosition;
startPosition = startExitPosition.ToPoint();
}
if (EndOutpost != null)
{
endPosition = new Point((int)EndOutpost.WorldPosition.X, (int)EndOutpost.WorldPosition.Y);
endExitPosition = EndOutpost.WorldPosition;
endPosition = endExitPosition.ToPoint();
}
CreateWrecks();
@@ -1971,6 +2016,7 @@ namespace Barotrauma
}
}
public List<ClusterLocation> AbyssResources { get; } = new List<ClusterLocation>();
public struct ClusterLocation
{
public VoronoiCell Cell { get; }
@@ -2055,6 +2101,7 @@ namespace Barotrauma
}
//place some of the least common resources in the abyss
AbyssResources.Clear();
for (int j = 0; j < levelResources.Count && j < 5; j++)
{
for (int i = 0; i < 10; i++)
@@ -2066,12 +2113,14 @@ namespace Barotrauma
if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; }
l.InitializeResources();
return l.Resources.Count <= GetMaxResourcesOnEdge(itemPrefab, l, out _);
}, randSync: Rand.RandSync.Server);
if (location.Cell == null || location.Edge == null) { break; }
int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y, Rand.RandSync.Server);
PlaceResources(itemPrefab, clusterSize, location, out _);
PlaceResources(itemPrefab, clusterSize, location, out var abyssResources);
var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true);
abyssClusterLocation.Resources.AddRange(abyssResources);
AbyssResources.Add(abyssClusterLocation);
var locationIndex = allValidLocations.FindIndex(l => l.Equals(location));
allValidLocations.RemoveAt(locationIndex);
}
@@ -3212,6 +3261,40 @@ namespace Barotrauma
Debug.WriteLine($"{Wrecks.Count} wrecks created in { totalSW.ElapsedMilliseconds.ToString()} (ms)");
}
private bool HasStartOutpost()
{
if (preSelectedStartOutpost != null) { return true; }
if (LevelData.Type != LevelData.LevelType.Outpost)
{
//only create a starting outpost in campaign and tutorial modes
#if CLIENT
if (Screen.Selected != GameMain.LevelEditorScreen && !IsModeStartOutpostCompatible())
{
return false;
}
#else
if (!IsModeStartOutpostCompatible())
{
return false;
}
#endif
}
if (StartLocation != null && !StartLocation.Type.HasOutpost)
{
return false;
}
return true;
}
private bool HasEndOutpost()
{
if (preSelectedStartOutpost != null) { return true; }
//don't create an end outpost for locations
if (LevelData.Type == LevelData.LevelType.Outpost) { return false; }
if (EndLocation != null && !EndLocation.Type.HasOutpost) { return false; }
return true;
}
private void CreateOutposts()
{
var outpostFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost).ToList();
@@ -3231,28 +3314,11 @@ namespace Barotrauma
bool isStart = (i == 0) == !Mirrored;
if (isStart)
{
if (LevelData.Type != LevelData.LevelType.Outpost)
{
//only create a starting outpost in campaign and tutorial modes
#if CLIENT
if (Screen.Selected != GameMain.LevelEditorScreen && !IsModeStartOutpostCompatible())
{
continue;
}
#else
if (!IsModeStartOutpostCompatible())
{
continue;
}
#endif
}
if (StartLocation != null && !StartLocation.Type.HasOutpost) { continue; }
if (!HasStartOutpost()) { continue; }
}
else
{
//don't create an end outpost for locations
if (LevelData.Type == LevelData.LevelType.Outpost) { continue; }
if (EndLocation != null && !EndLocation.Type.HasOutpost) { continue; }
if (!HasEndOutpost()) { continue; }
}
SubmarineInfo outpostInfo;
@@ -29,7 +29,7 @@ namespace Barotrauma
public bool HasBeaconStation;
public bool IsBeaconActive;
public bool HasHuntingGrounds;
public bool HasHuntingGrounds, OriginallyHadHuntingGrounds;
public OutpostGenerationParams ForceOutpostGenerationParams;
@@ -89,6 +89,7 @@ namespace Barotrauma
IsBeaconActive = element.GetAttributeBool("isbeaconactive", false);
HasHuntingGrounds = element.GetAttributeBool("hashuntinggrounds", false);
OriginallyHadHuntingGrounds = element.GetAttributeBool("originallyhadhuntinggrounds", HasHuntingGrounds);
string generationParamsId = element.GetAttributeString("generationparams", "");
GenerationParams = LevelGenerationParams.LevelParams.Find(l => l.Identifier == generationParamsId || l.OldIdentifier == generationParamsId);
@@ -231,8 +232,12 @@ namespace Barotrauma
if (HasHuntingGrounds)
{
newElement.Add(
new XAttribute("hashuntinggrounds", HasHuntingGrounds.ToString()));
new XAttribute("hashuntinggrounds", true));
}
if (HasHuntingGrounds || OriginallyHadHuntingGrounds)
{
newElement.Add(
new XAttribute("originallyhadhuntinggrounds", true));
}
if (Type == LevelType.Outpost)
@@ -326,7 +326,7 @@ namespace Barotrauma
sub.SetPosition((linkedPort.Item.WorldPosition - portDiff) - offset);
myPort.Dock(linkedPort);
myPort.Dock(linkedPort);
myPort.Lock(isNetworkMessage: true, applyEffects: false);
}
}
@@ -402,14 +402,14 @@ namespace Barotrauma
bool leaveBehind = false;
if (!sub.DockedTo.Contains(Submarine.MainSub))
{
System.Diagnostics.Debug.Assert(Submarine.MainSub.AtEndPosition || Submarine.MainSub.AtStartPosition);
if (Submarine.MainSub.AtEndPosition)
System.Diagnostics.Debug.Assert(Submarine.MainSub.AtEndExit || Submarine.MainSub.AtStartExit);
if (Submarine.MainSub.AtEndExit)
{
leaveBehind = sub.AtEndPosition != Submarine.MainSub.AtEndPosition;
leaveBehind = sub.AtEndExit != Submarine.MainSub.AtEndExit;
}
else
{
leaveBehind = sub.AtStartPosition != Submarine.MainSub.AtStartPosition;
leaveBehind = sub.AtStartExit != Submarine.MainSub.AtStartExit;
}
}
@@ -68,8 +68,6 @@ namespace Barotrauma
public (LocationTypeChange typeChange, int delay, MissionPrefab parentMission)? PendingLocationTypeChange;
public int LocationTypeChangeCooldown;
public readonly int ZoneIndex;
public string BaseName { get => baseName; }
public string Name { get; private set; }
@@ -80,6 +78,8 @@ namespace Barotrauma
public LocationType Type { get; private set; }
public LocationType OriginalType { get; private set; }
public LevelData LevelData { get; set; }
public int PortraitId { get; private set; }
@@ -248,7 +248,7 @@ namespace Barotrauma
public Location(Vector2 mapPosition, int? zone, Random rand, bool requireOutpost = false, LocationType? forceLocationType = null, IEnumerable<Location> existingLocations = null)
{
Type = forceLocationType ?? LocationType.Random(rand, zone, requireOutpost);
Type = OriginalType = forceLocationType ?? LocationType.Random(rand, zone, requireOutpost);
Name = RandomName(Type, rand, existingLocations);
MapPosition = mapPosition;
PortraitId = ToolBox.StringToInt(Name);
@@ -262,12 +262,27 @@ namespace Barotrauma
bool typeNotFound = false;
if (Type == null)
{
DebugConsole.AddWarning($"Could not find location type \"{locationType}\". Using location type \"None\" instead.");
Type = LocationType.List.Find(lt => lt.Identifier.Equals("None", StringComparison.OrdinalIgnoreCase));
Type ??= LocationType.List.First();
//turn lairs into abandoned outposts
if (locationType.Equals("lair", StringComparison.OrdinalIgnoreCase))
{
Type ??= LocationType.List.Find(lt => lt.Identifier.Equals("Abandoned", StringComparison.OrdinalIgnoreCase));
}
if (Type == null)
{
DebugConsole.AddWarning($"Could not find location type \"{locationType}\". Using location type \"None\" instead.");
Type ??= LocationType.List.Find(lt => lt.Identifier.Equals("None", StringComparison.OrdinalIgnoreCase));
Type ??= LocationType.List.First();
}
if (Type != null)
{
element.SetAttributeValue("type", Type.Identifier);
}
typeNotFound = true;
}
string originalLocationType = element.GetAttributeString("originaltype", locationType);
OriginalType = LocationType.List.Find(lt => lt.Identifier.Equals(locationType, StringComparison.OrdinalIgnoreCase));
baseName = element.GetAttributeString("basename", "");
Name = element.GetAttributeString("name", "");
MapPosition = element.GetAttributeVector2("position", Vector2.Zero);
@@ -1015,6 +1030,7 @@ namespace Barotrauma
{
var locationElement = new XElement("location",
new XAttribute("type", Type.Identifier),
new XAttribute("originaltype", (Type ?? OriginalType).Identifier),
new XAttribute("basename", BaseName),
new XAttribute("name", Name),
new XAttribute("discovered", Discovered),
@@ -39,7 +39,7 @@ namespace Barotrauma
{
get
{
availableMissions.RemoveAll(m => m.Completed || (m.Failed && m.Prefab.AllowRetry));
availableMissions.RemoveAll(m => m.Completed || (m.Failed && !m.Prefab.AllowRetry));
return availableMissions;
}
}
@@ -77,6 +77,9 @@ namespace Barotrauma
{
Seed = element.GetAttributeString("seed", "a");
Rand.SetSyncedSeed(ToolBox.StringToInt(Seed));
bool lairsFound = false;
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -87,6 +90,7 @@ namespace Barotrauma
{
Locations.Add(null);
}
lairsFound |= subElement.GetAttributeString("type", "").Equals("lair", StringComparison.OrdinalIgnoreCase);
Locations[i] = new Location(subElement);
break;
case "radiation":
@@ -103,6 +107,7 @@ namespace Barotrauma
Locations[i].Reputation ??= new Reputation(campaign.CampaignMetadata, $"location.{i}", -100, 100, Rand.Range(-10, 10, Rand.RandSync.Server));
}
List<XElement> connectionElements = new List<XElement>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -125,6 +130,7 @@ namespace Barotrauma
LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.OldIdentifier == biomeId) ??
LevelGenerationParams.GetBiomes().First();
Connections.Add(connection);
connectionElements.Add(subElement);
break;
}
}
@@ -163,6 +169,17 @@ namespace Barotrauma
}
}
//backwards compatibility: if the map contained the now-removed lairs and has no hunting grounds, create some hunting grounds
if (lairsFound && !Connections.Any(c => c.LevelData.HasHuntingGrounds))
{
for (int i = 0; i < Connections.Count; i++)
{
float maxHuntingGroundsProbability = 0.3f;
Connections[i].LevelData.HasHuntingGrounds = Rand.Range(0.0f, 1.0f) < Connections[i].Difficulty / 100.0f * maxHuntingGroundsProbability;
connectionElements[i].SetAttributeValue("hashuntinggrounds", true);
}
}
InitProjectSpecific();
}
@@ -504,7 +521,7 @@ namespace Barotrauma
foreach (LocationConnection connection in Connections)
{
if (connection.Biome != null) { continue; }
connection.Biome = connection.Locations[0].Biome;
connection.Biome = connection.Locations[0].MapPosition.X > connection.Locations[1].MapPosition.X ? connection.Locations[0].Biome : connection.Locations[1].Biome;
}
System.Diagnostics.Debug.Assert(Locations.All(l => l.Biome != null));
@@ -805,7 +822,7 @@ namespace Barotrauma
continue;
}
if (location == CurrentLocation || location == SelectedLocation) { continue; }
if (location == CurrentLocation || location == SelectedLocation || location.IsGateBetweenBiomes) { continue; }
ProgressLocationTypeChanges(location);
@@ -193,7 +193,7 @@ namespace Barotrauma
}
}
public bool AtEndPosition
public bool AtEndExit
{
get
{
@@ -202,11 +202,11 @@ namespace Barotrauma
{
return true;
}
return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.EndPosition) < Level.ExitDistance * Level.ExitDistance);
return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.EndExitPosition) < Level.ExitDistance * Level.ExitDistance);
}
}
public bool AtStartPosition
public bool AtStartExit
{
get
{
@@ -215,7 +215,7 @@ namespace Barotrauma
{
return true;
}
return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.StartPosition) < Level.ExitDistance * Level.ExitDistance);
return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.StartExitPosition) < Level.ExitDistance * Level.ExitDistance);
}
}
@@ -95,8 +95,9 @@ namespace Barotrauma
public OutpostModuleInfo OutpostModuleInfo { get; set; }
public bool IsOutpost => Type == SubmarineType.Outpost;
public bool IsOutpost => Type == SubmarineType.Outpost || Type == SubmarineType.OutpostModule;
public bool IsWreck => Type == SubmarineType.Wreck;
public bool IsBeacon => Type == SubmarineType.BeaconStation;
public bool IsPlayer => Type == SubmarineType.Player;
public bool IsCampaignCompatible => IsPlayer && !HasTag(SubmarineTag.Shuttle) && !HasTag(SubmarineTag.HideInMenus) && SubmarineClass != SubmarineClass.Undefined;