v1.5.7.0 (Summer Update)
This commit is contained in:
@@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Voronoi2;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -430,6 +431,11 @@ namespace Barotrauma
|
||||
{
|
||||
get { return ForcedDifficulty ?? LevelData.Difficulty; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inclusive (matching the min an max values is accepted).
|
||||
/// </summary>
|
||||
public bool IsAllowedDifficulty(float minDifficulty, float maxDifficulty) => LevelData.IsAllowedDifficulty(minDifficulty, maxDifficulty);
|
||||
|
||||
public LevelData.LevelType Type
|
||||
{
|
||||
@@ -3718,7 +3724,7 @@ namespace Barotrauma
|
||||
return MathUtils.LineSegmentToPointDistanceSquared(endPosition, endExitPosition, position) < minDist * minDist;
|
||||
}
|
||||
|
||||
private Submarine SpawnSubOnPath(string subName, ContentFile contentFile, SubmarineType type)
|
||||
private Submarine SpawnSubOnPath(string subName, ContentFile contentFile, SubmarineType type, bool forceThalamus = false)
|
||||
{
|
||||
var tempSW = new Stopwatch();
|
||||
|
||||
@@ -3801,7 +3807,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
// Only spawn thalamus when the wreck has some thalamus items defined.
|
||||
if (Rand.Value(Rand.RandSync.ServerAndClient) <= Loaded.GenerationParams.ThalamusProbability && sub.GetItems(false).Any(i => i.Prefab.HasSubCategory("thalamus")))
|
||||
if ((forceThalamus || Rand.Value(Rand.RandSync.ServerAndClient) <= Loaded.GenerationParams.ThalamusProbability) && sub.GetItems(false).Any(i => i.Prefab.HasSubCategory("thalamus")))
|
||||
{
|
||||
if (!sub.CreateWreckAI())
|
||||
{
|
||||
@@ -4039,72 +4045,114 @@ namespace Barotrauma
|
||||
private readonly Dictionary<Submarine, List<Vector2>> wreckPositions = new Dictionary<Submarine, List<Vector2>>();
|
||||
private readonly Dictionary<Submarine, List<Rectangle>> blockedRects = new Dictionary<Submarine, List<Rectangle>>();
|
||||
|
||||
private readonly record struct PlaceableWreck(WreckFile WreckFile, WreckInfo WreckInfo)
|
||||
{
|
||||
public static Option<PlaceableWreck> TryCreate(WreckFile wreckFile)
|
||||
{
|
||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(i => i.FilePath == wreckFile.Path.Value);
|
||||
if (matchingSub?.WreckInfo is null)
|
||||
{
|
||||
DebugConsole.ThrowError($"No matching submarine info found for the wreck file {wreckFile.Path.Value}");
|
||||
return Option.None;
|
||||
}
|
||||
|
||||
return Option.Some(new PlaceableWreck(wreckFile, matchingSub.WreckInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWrecks()
|
||||
{
|
||||
var totalSW = new Stopwatch();
|
||||
totalSW.Start();
|
||||
|
||||
var wreckFiles = ContentPackageManager.EnabledPackages.All
|
||||
var placeableWrecks = ContentPackageManager.EnabledPackages.All
|
||||
.SelectMany(p => p.GetFiles<WreckFile>())
|
||||
.OrderBy(f => f.UintIdentifier).ToList();
|
||||
.OrderBy(f => f.UintIdentifier)
|
||||
.Select(PlaceableWreck.TryCreate)
|
||||
.Where(w => w.IsSome())
|
||||
.Select(o => o.TryUnwrap(out var w) ? w : throw new InvalidOperationException())
|
||||
.ToList();
|
||||
|
||||
for (int i = wreckFiles.Count - 1; i >= 0; i--)
|
||||
for (int i = placeableWrecks.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var wreckFile = wreckFiles[i];
|
||||
var wreckInfos = SubmarineInfo.SavedSubmarines.Where(i => i.IsWreck);
|
||||
var matchingInfo = wreckInfos.SingleOrDefault(info => info.FilePath == wreckFile.Path.Value);
|
||||
Debug.Assert(matchingInfo != null);
|
||||
if (matchingInfo?.WreckInfo is WreckInfo wreckInfo)
|
||||
var wreckInfo = placeableWrecks[i].WreckInfo;
|
||||
if (!IsAllowedDifficulty(wreckInfo.MinLevelDifficulty, wreckInfo.MaxLevelDifficulty))
|
||||
{
|
||||
if (Difficulty < wreckInfo.MinLevelDifficulty || Difficulty > wreckInfo.MaxLevelDifficulty)
|
||||
{
|
||||
wreckFiles.RemoveAt(i);
|
||||
}
|
||||
placeableWrecks.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
if (wreckFiles.None())
|
||||
if (placeableWrecks.None())
|
||||
{
|
||||
DebugConsole.ThrowError($"No wreck files found for the level difficulty {LevelData.Difficulty}!");
|
||||
Wrecks = new List<Submarine>();
|
||||
return;
|
||||
}
|
||||
wreckFiles.Shuffle(Rand.RandSync.ServerAndClient);
|
||||
placeableWrecks.Shuffle(Rand.RandSync.ServerAndClient);
|
||||
|
||||
int minWreckCount = Math.Min(Loaded.GenerationParams.MinWreckCount, wreckFiles.Count);
|
||||
int maxWreckCount = Math.Min(Loaded.GenerationParams.MaxWreckCount, wreckFiles.Count);
|
||||
int minWreckCount = Math.Min(Loaded.GenerationParams.MinWreckCount, placeableWrecks.Count);
|
||||
int maxWreckCount = Math.Min(Loaded.GenerationParams.MaxWreckCount, placeableWrecks.Count);
|
||||
int wreckCount = Rand.Range(minWreckCount, maxWreckCount + 1, Rand.RandSync.ServerAndClient);
|
||||
bool requireThalamus = false;
|
||||
|
||||
if (GameMain.GameSession?.GameMode?.Missions.Any(m => m.Prefab.RequireWreck) ?? false)
|
||||
{
|
||||
wreckCount = Math.Max(wreckCount, 1);
|
||||
}
|
||||
|
||||
if (GameMain.GameSession?.GameMode?.Missions.Any(static m => m.Prefab.RequireThalamusWreck) ?? false)
|
||||
{
|
||||
requireThalamus = true;
|
||||
}
|
||||
|
||||
if (LevelData.ForceWreck != null)
|
||||
{
|
||||
//force the desired wreck to be chosen first
|
||||
var matchingFile = wreckFiles.FirstOrDefault(w => w.Path == LevelData.ForceWreck.FilePath);
|
||||
if (matchingFile != null)
|
||||
var matchingFile = placeableWrecks.FirstOrDefault(w => w.WreckFile.Path == LevelData.ForceWreck.FilePath);
|
||||
if (matchingFile.WreckFile != null)
|
||||
{
|
||||
wreckFiles.Remove(matchingFile);
|
||||
wreckFiles.Insert(0, matchingFile);
|
||||
placeableWrecks.Remove(matchingFile);
|
||||
placeableWrecks.Insert(0, matchingFile);
|
||||
}
|
||||
wreckCount = Math.Max(wreckCount, 1);
|
||||
}
|
||||
|
||||
if (requireThalamus)
|
||||
{
|
||||
var thalamusWrecks = placeableWrecks
|
||||
.Where(static w => w.WreckInfo.WreckContainsThalamus == WreckInfo.HasThalamus.Yes)
|
||||
.ToList();
|
||||
|
||||
if (thalamusWrecks.Any())
|
||||
{
|
||||
thalamusWrecks.Shuffle(Rand.RandSync.ServerAndClient);
|
||||
|
||||
foreach (var wreck in thalamusWrecks)
|
||||
{
|
||||
placeableWrecks.Remove(wreck);
|
||||
placeableWrecks.Insert(0, wreck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Wrecks = new List<Submarine>(wreckCount);
|
||||
for (int i = 0; i < wreckCount; i++)
|
||||
{
|
||||
//how many times we'll try placing another sub before giving up
|
||||
const int MaxSubsToTry = 2;
|
||||
int attempts = 0;
|
||||
while (wreckFiles.Any() && attempts < MaxSubsToTry)
|
||||
while (placeableWrecks.Any() && attempts < MaxSubsToTry)
|
||||
{
|
||||
ContentFile contentFile = wreckFiles.First();
|
||||
wreckFiles.RemoveAt(0);
|
||||
if (contentFile == null) { continue; }
|
||||
string wreckName = System.IO.Path.GetFileNameWithoutExtension(contentFile.Path.Value);
|
||||
if (SpawnSubOnPath(wreckName, contentFile, SubmarineType.Wreck) != null)
|
||||
var placeableWreck = placeableWrecks.First();
|
||||
var wreckFile = placeableWreck.WreckFile;
|
||||
placeableWrecks.RemoveAt(0);
|
||||
if (wreckFile == null) { continue; }
|
||||
string wreckName = System.IO.Path.GetFileNameWithoutExtension(wreckFile.Path.Value);
|
||||
if (SpawnSubOnPath(wreckName, wreckFile, SubmarineType.Wreck, forceThalamus: requireThalamus) is { } wreck)
|
||||
{
|
||||
if (wreck.WreckAI is not null)
|
||||
{
|
||||
requireThalamus = false;
|
||||
}
|
||||
//placed successfully
|
||||
break;
|
||||
}
|
||||
@@ -4223,7 +4271,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (MapEntity entityToHide in MapEntity.MapEntityList.Where(me => me.Submarine == outpost && (me.Prefab?.HasSubCategory(categoryToHide) ?? false)))
|
||||
{
|
||||
entityToHide.HiddenInGame = true;
|
||||
entityToHide.IsLayerHidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4489,72 +4537,97 @@ namespace Barotrauma
|
||||
else if (GameMain.NetworkMember is not { IsClient: true })
|
||||
{
|
||||
bool allowDisconnectedWires = true;
|
||||
bool allowDamagedDevices = true;
|
||||
bool allowDamagedWalls = true;
|
||||
if (BeaconStation?.Info?.BeaconStationInfo is BeaconStationInfo info)
|
||||
{
|
||||
allowDisconnectedWires = info.AllowDisconnectedWires;
|
||||
allowDamagedWalls = info.AllowDamagedWalls;
|
||||
allowDamagedDevices = info.AllowDamagedDevices;
|
||||
}
|
||||
|
||||
//remove wires
|
||||
float removeWireMinDifficulty = 20.0f;
|
||||
float removeWireProbability = MathUtils.InverseLerp(removeWireMinDifficulty, 100.0f, LevelData.Difficulty) * 0.5f;
|
||||
if (removeWireProbability > 0.0f && allowDisconnectedWires)
|
||||
float disconnectWireMinDifficulty = 20.0f;
|
||||
float disconnectWireProbability = MathUtils.InverseLerp(disconnectWireMinDifficulty, 100.0f, LevelData.Difficulty) * 0.5f;
|
||||
if (disconnectWireProbability > 0.0f && allowDisconnectedWires)
|
||||
{
|
||||
foreach (Item item in beaconItems.Where(it => it.GetComponent<Wire>() != null).ToList())
|
||||
{
|
||||
if (item.NonInteractable || item.InvulnerableToDamage) { continue; }
|
||||
Wire wire = item.GetComponent<Wire>();
|
||||
if (wire.Locked) { continue; }
|
||||
if (wire.Connections[0] != null && (wire.Connections[0].Item.NonInteractable || wire.Connections[0].Item.GetComponent<ConnectionPanel>().Locked))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (wire.Connections[1] != null && (wire.Connections[1].Item.NonInteractable || wire.Connections[1].Item.GetComponent<ConnectionPanel>().Locked))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (Rand.Range(0f, 1.0f, Rand.RandSync.Unsynced) < removeWireProbability)
|
||||
{
|
||||
foreach (Connection connection in wire.Connections)
|
||||
{
|
||||
if (connection != null)
|
||||
{
|
||||
connection.ConnectionPanel.DisconnectedWires.Add(wire);
|
||||
wire.RemoveConnection(connection.Item);
|
||||
#if SERVER
|
||||
connection.ConnectionPanel.Item.CreateServerEvent(connection.ConnectionPanel);
|
||||
wire.CreateNetworkEvent();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DisconnectBeaconStationWires(disconnectWireProbability);
|
||||
}
|
||||
|
||||
if (allowDamagedDevices)
|
||||
{
|
||||
DamageBeaconStationDevices(breakDeviceProbability: 0.5f);
|
||||
}
|
||||
if (allowDamagedWalls)
|
||||
{
|
||||
//break powered items
|
||||
foreach (Item item in beaconItems.Where(it => it.Components.Any(c => c is Powered) && it.Components.Any(c => c is Repairable)))
|
||||
DamageBeaconStationWalls(damageWallProbability: 0.25f);
|
||||
}
|
||||
}
|
||||
SetLinkedSubCrushDepth(BeaconStation);
|
||||
}
|
||||
|
||||
public void DisconnectBeaconStationWires(float disconnectWireProbability)
|
||||
{
|
||||
if (disconnectWireProbability <= 0.0f) { return; }
|
||||
List<Item> beaconItems = Item.ItemList.FindAll(it => it.Submarine == BeaconStation);
|
||||
foreach (Item item in beaconItems.Where(it => it.GetComponent<Wire>() != null).ToList())
|
||||
{
|
||||
if (item.NonInteractable || item.InvulnerableToDamage) { continue; }
|
||||
Wire wire = item.GetComponent<Wire>();
|
||||
if (wire.Locked) { continue; }
|
||||
if (wire.Connections[0] != null && (wire.Connections[0].Item.NonInteractable || wire.Connections[0].Item.GetComponent<ConnectionPanel>().Locked))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (wire.Connections[1] != null && (wire.Connections[1].Item.NonInteractable || wire.Connections[1].Item.GetComponent<ConnectionPanel>().Locked))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (Rand.Range(0f, 1.0f, Rand.RandSync.Unsynced) < disconnectWireProbability)
|
||||
{
|
||||
foreach (Connection connection in wire.Connections)
|
||||
{
|
||||
if (item.NonInteractable || item.InvulnerableToDamage) { continue; }
|
||||
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < 0.5f)
|
||||
if (connection != null)
|
||||
{
|
||||
item.Condition *= Rand.Range(0.6f, 0.8f, Rand.RandSync.Unsynced);
|
||||
}
|
||||
}
|
||||
//poke holes in the walls
|
||||
foreach (Structure structure in Structure.WallList.Where(s => s.Submarine == BeaconStation))
|
||||
{
|
||||
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < 0.25f)
|
||||
{
|
||||
int sectionIndex = Rand.Range(0, structure.SectionCount - 1, Rand.RandSync.Unsynced);
|
||||
structure.AddDamage(sectionIndex, Rand.Range(structure.MaxHealth * 0.2f, structure.MaxHealth, Rand.RandSync.Unsynced));
|
||||
connection.ConnectionPanel.DisconnectedWires.Add(wire);
|
||||
wire.RemoveConnection(connection.Item);
|
||||
#if SERVER
|
||||
connection.ConnectionPanel.Item.CreateServerEvent(connection.ConnectionPanel);
|
||||
wire.CreateNetworkEvent();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetLinkedSubCrushDepth(BeaconStation);
|
||||
}
|
||||
|
||||
public void DamageBeaconStationDevices(float breakDeviceProbability)
|
||||
{
|
||||
if (breakDeviceProbability <= 0.0f) { return; }
|
||||
//break powered items
|
||||
List<Item> beaconItems = Item.ItemList.FindAll(it => it.Submarine == BeaconStation);
|
||||
foreach (Item item in beaconItems.Where(it => it.Components.Any(c => c is Powered) && it.Components.Any(c => c is Repairable)))
|
||||
{
|
||||
if (item.NonInteractable || item.InvulnerableToDamage) { continue; }
|
||||
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < breakDeviceProbability)
|
||||
{
|
||||
item.Condition *= Rand.Range(0.6f, 0.8f, Rand.RandSync.Unsynced);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DamageBeaconStationWalls(float damageWallProbability)
|
||||
{
|
||||
if (damageWallProbability <= 0.0f) { return; }
|
||||
//poke holes in the walls
|
||||
foreach (Structure structure in Structure.WallList.Where(s => s.Submarine == BeaconStation))
|
||||
{
|
||||
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < damageWallProbability)
|
||||
{
|
||||
int sectionIndex = Rand.Range(0, structure.SectionCount - 1, Rand.RandSync.Unsynced);
|
||||
structure.AddDamage(sectionIndex, Rand.Range(structure.MaxHealth * 0.2f, structure.MaxHealth, Rand.RandSync.Unsynced));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckBeaconActive()
|
||||
|
||||
@@ -99,6 +99,11 @@ namespace Barotrauma
|
||||
return Math.Max(Size.Y * Physics.DisplayToRealWorldRatio, Level.DefaultRealWorldCrushDepth);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inclusive (matching the min an max values is accepted).
|
||||
/// </summary>
|
||||
public bool IsAllowedDifficulty(float minDifficulty, float maxDifficulty) => Difficulty >= minDifficulty && Difficulty <= maxDifficulty;
|
||||
|
||||
public LevelData(string seed, float difficulty, float sizeFactor, LevelGenerationParams generationParams, Biome biome)
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Header("General")]
|
||||
[Serialize(LevelData.LevelType.LocationConnection, IsPropertySaveable.Yes), Editable]
|
||||
public LevelData.LevelType Type
|
||||
{
|
||||
@@ -88,42 +89,9 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("27,30,36", IsPropertySaveable.Yes), Editable]
|
||||
public Color AmbientLightColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("20,40,50", IsPropertySaveable.Yes), Editable]
|
||||
public Color BackgroundTextureColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("20,40,50", IsPropertySaveable.Yes), Editable]
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("255,255,255", IsPropertySaveable.Yes), Editable]
|
||||
public Color WallColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("255,255,255", IsPropertySaveable.Yes), Editable]
|
||||
public Color WaterParticleColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private Vector2 startPosition;
|
||||
|
||||
[Header("Layout")]
|
||||
[Serialize("0,0", IsPropertySaveable.Yes, "Start position of the level (relative to the size of the level. 0,0 = top left corner, 1,1 = bottom right corner)"), Editable(DecimalCount = 2)]
|
||||
public Vector2 StartPosition
|
||||
{
|
||||
@@ -169,32 +137,11 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes, "Should the generator force a hole to the bottom of the level to ensure there's a way to the abyss."), Editable]
|
||||
public bool CreateHoleToAbyss
|
||||
[Serialize(0.4f, IsPropertySaveable.Yes, description: "The probability for wall cells to be removed from the bottom of the map. A value of 0 will produce a completely enclosed tunnel and 1 will make the entire bottom of the level completely open."), Editable()]
|
||||
public float BottomHoleProbability
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "If enabled, no walls generate in the level. Can be useful for e.g. levels that are just supposed to consist of a pre-built outpost."), Editable]
|
||||
public bool NoLevelGeometry
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1000, IsPropertySaveable.Yes, description: "The total number of level objects (vegetation, vents, etc) in the level."), Editable(MinValueInt = 0, MaxValueInt = 100000)]
|
||||
public int LevelObjectAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(80, IsPropertySaveable.Yes, description: "The total number of decorative background creatures."), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
public int BackgroundCreatureAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return bottomHoleProbability; }
|
||||
set { bottomHoleProbability = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
}
|
||||
|
||||
[Serialize(100000, IsPropertySaveable.Yes), Editable]
|
||||
@@ -232,31 +179,10 @@ namespace Barotrauma
|
||||
set { initialDepthMax = Math.Max(value, initialDepthMin); }
|
||||
}
|
||||
|
||||
[Serialize(6500, IsPropertySaveable.Yes, description: "Minimum width of the main tunnel going through the level, in pixels. Can be automatically increased by the level editor if the submarine is larger than this."), Editable(MinValueInt = 5000, MaxValueInt = 1000000)]
|
||||
public int MinTunnelRadius
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Header("Level geometry")]
|
||||
|
||||
|
||||
[Serialize("0,1", IsPropertySaveable.Yes, description: "Amount of side tunnels in the level (min,max)."), Editable]
|
||||
public Point SideTunnelCount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(0.5f, IsPropertySaveable.Yes, description: "How much the side tunnels can \"zigzag\". 0 = completely straight tunnel, 1 = can go all the way from the top of the level to the bottom."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f)]
|
||||
public float SideTunnelVariance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("2000,6000", IsPropertySaveable.Yes, description: "Minimum width of the side tunnels, in pixels. Unlike the main tunnel, does not get adjusted based on the size of the submarine."), Editable]
|
||||
public Point MinSideTunnelRadius
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "If enabled, no walls generate in the level. Can be useful for e.g. levels that are just supposed to consist of a pre-built outpost."), Editable]
|
||||
public bool NoLevelGeometry
|
||||
{
|
||||
get;
|
||||
set;
|
||||
@@ -324,6 +250,37 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
[Header("Tunnels")]
|
||||
[Serialize(6500, IsPropertySaveable.Yes, description: "Minimum width of the main tunnel going through the level, in pixels. Can be automatically increased by the level editor if the submarine is larger than this."), Editable(MinValueInt = 5000, MaxValueInt = 1000000)]
|
||||
public int MinTunnelRadius
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize("0,1", IsPropertySaveable.Yes, description: "Amount of side tunnels in the level (min,max)."), Editable]
|
||||
public Point SideTunnelCount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(0.5f, IsPropertySaveable.Yes, description: "How much the side tunnels can \"zigzag\". 0 = completely straight tunnel, 1 = can go all the way from the top of the level to the bottom."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f)]
|
||||
public float SideTunnelVariance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("2000,6000", IsPropertySaveable.Yes, description: "Minimum width of the side tunnels, in pixels. Unlike the main tunnel, does not get adjusted based on the size of the submarine."), Editable]
|
||||
public Point MinSideTunnelRadius
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
|
||||
Serialize("5000, 10000", IsPropertySaveable.Yes, 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
|
||||
@@ -343,6 +300,22 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Header("Contents")]
|
||||
[Serialize(1000, IsPropertySaveable.Yes, description: "The total number of level objects (vegetation, vents, etc) in the level."), Editable(MinValueInt = 0, MaxValueInt = 100000)]
|
||||
public int LevelObjectAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(80, IsPropertySaveable.Yes, description: "The total number of decorative background creatures."), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
public int BackgroundCreatureAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Editable, Serialize(5, IsPropertySaveable.Yes, description: "The number of caves placed along the main path.")]
|
||||
public int CaveCount
|
||||
{
|
||||
@@ -406,6 +379,14 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Header("Abyss")]
|
||||
[Serialize(true, IsPropertySaveable.Yes, "Should the generator force a hole to the bottom of the level to ensure there's a way to the abyss."), Editable]
|
||||
public bool CreateHoleToAbyss
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(5, IsPropertySaveable.Yes, description: "Number of abyss islands in the level."), Editable(MinValueInt = 0, MaxValueInt = 20)]
|
||||
public int AbyssIslandCount
|
||||
{
|
||||
@@ -448,6 +429,7 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Header("Sea floor")]
|
||||
[Serialize(-300000, IsPropertySaveable.Yes, description: "How far below the level the sea floor is placed."), Editable(MinValueFloat = Level.MaxEntityDepth, MaxValueFloat = 0.0f)]
|
||||
public int SeaFloorDepth
|
||||
{
|
||||
@@ -506,6 +488,7 @@ namespace Barotrauma
|
||||
|
||||
public int GetMaxRuinCount() => UseRandomRuinCount() ? MaxRuinCount : RuinCount;
|
||||
|
||||
[Header("Ruins")]
|
||||
[Serialize(1, IsPropertySaveable.Yes, description: "The number of alien ruins in the level. Ignored, if both MinRuinCount and MaxRuinCount are defined."), Editable(MinValueInt = 0, MaxValueInt = 10)]
|
||||
public int RuinCount { get; set; }
|
||||
|
||||
@@ -517,6 +500,7 @@ namespace Barotrauma
|
||||
|
||||
// TODO: Move the wreck parameters under a separate class?
|
||||
#region Wreck parameters
|
||||
[Header("Wrecks")]
|
||||
[Serialize(1, IsPropertySaveable.Yes, description: "The minimum number of wrecks in the level. Note that this value cannot be higher than the amount of wreck prefabs (subs)."), Editable(MinValueInt = 0, MaxValueInt = 10)]
|
||||
public int MinWreckCount { get; set; }
|
||||
|
||||
@@ -545,13 +529,7 @@ namespace Barotrauma
|
||||
[Serialize("", IsPropertySaveable.Yes, description: "Should a beacon station always spawn in this type of level?")]
|
||||
public string ForceBeaconStation { get; set; }
|
||||
|
||||
[Serialize(0.4f, IsPropertySaveable.Yes, description: "The probability for wall cells to be removed from the bottom of the map. A value of 0 will produce a completely enclosed tunnel and 1 will make the entire bottom of the level completely open."), Editable()]
|
||||
public float BottomHoleProbability
|
||||
{
|
||||
get { return bottomHoleProbability; }
|
||||
set { bottomHoleProbability = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
}
|
||||
|
||||
[Header("Visuals")]
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes, description: "Scale of the water particle texture."), Editable]
|
||||
public float WaterParticleScale
|
||||
{
|
||||
@@ -595,6 +573,58 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(120.0f, IsPropertySaveable.Yes, description: "How far the level walls' edge texture portrudes outside the actual, \"physical\" edge of the cell."), Editable(minValue: 0.0f, maxValue: 1000.0f)]
|
||||
public float WallEdgeExpandOutwardsAmount
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(1000.0f, IsPropertySaveable.Yes, description: "How far inside the level walls the edge texture continues."), Editable(minValue: 0.0f, maxValue: 10000.0f)]
|
||||
public float WallEdgeExpandInwardsAmount
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Header("Colors")]
|
||||
[Serialize("27,30,36", IsPropertySaveable.Yes), Editable]
|
||||
public Color AmbientLightColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("20,40,50", IsPropertySaveable.Yes), Editable]
|
||||
public Color BackgroundTextureColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("20,40,50", IsPropertySaveable.Yes), Editable]
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("255,255,255", IsPropertySaveable.Yes), Editable]
|
||||
public Color WallColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("255,255,255", IsPropertySaveable.Yes), Editable]
|
||||
public Color WaterParticleColor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Header("Sounds")]
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Should the \"ambient noise\" of the biome play in this level if it's an outpost level."), Editable]
|
||||
public bool PlayNoiseLoopInOutpostLevel
|
||||
{
|
||||
@@ -609,19 +639,6 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(120.0f, IsPropertySaveable.Yes, description: "How far the level walls' edge texture portrudes outside the actual, \"physical\" edge of the cell."), Editable(minValue: 0.0f, maxValue: 1000.0f)]
|
||||
public float WallEdgeExpandOutwardsAmount
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(1000.0f, IsPropertySaveable.Yes, description: "How far inside the level walls the edge texture continues."), Editable(minValue: 0.0f, maxValue: 10000.0f)]
|
||||
public float WallEdgeExpandInwardsAmount
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Sprite BackgroundSprite { get; private set; }
|
||||
public Sprite BackgroundTopSprite { get; private set; }
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Structure structure in Structure.WallList)
|
||||
{
|
||||
if (!structure.HasBody || structure.HiddenInGame) { continue; }
|
||||
if (!structure.HasBody || structure.IsHidden) { continue; }
|
||||
|
||||
LevelObjectPrefab.SpawnPosType spawnPosType = LevelObjectPrefab.SpawnPosType.None;
|
||||
if (level.Ruins.Any(r => r.Submarine == structure.Submarine))
|
||||
|
||||
Reference in New Issue
Block a user