v1.5.7.0 (Summer Update)

This commit is contained in:
Regalis11
2024-06-18 16:49:51 +03:00
parent 4a63dacbce
commit 230d1b6e78
263 changed files with 7792 additions and 2845 deletions
@@ -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; }
@@ -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))