Build 0.18.4.0

This commit is contained in:
Markus Isberg
2022-05-31 23:13:05 +09:00
parent 077917fa5d
commit 64db1a6a44
175 changed files with 4916 additions and 2393 deletions
@@ -10,7 +10,7 @@ namespace Barotrauma
{
public static bool OutputDebugInfo = false;
public static void SpawnItems()
public static void SpawnItems(Identifier? startItemSet = null)
{
if (GameMain.NetworkMember != null && !GameMain.NetworkMember.IsServer) { return; }
@@ -23,7 +23,7 @@ namespace Barotrauma
var sub = Submarine.MainSubs[i];
if (sub == null || sub.Info.InitialSuppliesSpawned || !sub.Info.IsPlayer) { continue; }
//1st pass: items defined in the start item set, only spawned in the main sub (not drones/shuttles or other linked subs)
SpawnStartItems(sub);
SpawnStartItems(sub, startItemSet);
//2nd pass: items defined using preferred containers, spawned in the main sub and all the linked subs (drones, shuttles etc)
var subs = sub.GetConnectedSubs().Where(s => s.TeamID == sub.TeamID);
CreateAndPlace(subs);
@@ -62,17 +62,23 @@ namespace Barotrauma
CreateAndPlace(sub.ToEnumerable(), regeneratedContainer: regeneratedContainer);
}
public static Identifier StartItemSet = new Identifier("normal");
public static Identifier DefaultStartItemSet = new Identifier("normal");
/// <summary>
/// Spawns the items defined in the start item set in the specified sub.
/// </summary>
private static void SpawnStartItems(Submarine sub)
private static void SpawnStartItems(Submarine sub, Identifier? startItemSet)
{
if (!Barotrauma.StartItemSet.Sets.TryGet(StartItemSet, out StartItemSet itemSet))
Identifier setIdentifier = startItemSet ?? DefaultStartItemSet;
if (!StartItemSet.Sets.TryGet(setIdentifier, out StartItemSet itemSet))
{
DebugConsole.AddWarning($"Couldn't find a start item set matching the identifier \"{StartItemSet}\"!");
return;
DebugConsole.AddWarning($"Couldn't find a start item set matching the identifier \"{setIdentifier}\"!");
if (!StartItemSet.Sets.TryGet(DefaultStartItemSet, out StartItemSet defaultSet))
{
DebugConsole.ThrowError($"Couldn't find the default start item set \"{DefaultStartItemSet}\"!");
return;
}
itemSet = defaultSet;
}
WayPoint wp = WayPoint.GetRandom(SpawnType.Cargo, null, sub);
ISpatialEntity initialSpawnPos;
@@ -164,7 +170,7 @@ namespace Barotrauma
var itemPrefabs = ItemPrefab.Prefabs.OrderBy(p => p.UintIdentifier);
foreach (ItemPrefab ip in itemPrefabs)
{
if (!ip.PreferredContainers.Any()) { continue; }
if (ip.PreferredContainers.None()) { continue; }
if (ip.ConfigElement.Elements().Any(e => string.Equals(e.Name.ToString(), typeof(ItemContainer).Name.ToString(), StringComparison.OrdinalIgnoreCase)) && itemPrefabs.Any(ip2 => CanSpawnIn(ip2, ip)))
{
prefabsItemsCanSpawnIn.Add(ip);
@@ -10,63 +10,6 @@ using System.Xml.Linq;
namespace Barotrauma
{
internal struct CampaignSettings
{
public static CampaignSettings Empty => new CampaignSettings();
// Anything that uses this field I wasn't sure if actually needed the proper campaign settings to be passed down
public static CampaignSettings Unsure => Empty;
public bool RadiationEnabled { get; set; }
public int TotalMaxMissionCount => MaxMissionCount + GetAddedMissionCount();
private int maxMissionCount;
public int MaxMissionCount
{
get { return maxMissionCount; }
set { maxMissionCount = MathHelper.Clamp(value, MinMissionCountLimit, MaxMissionCountLimit); }
}
public const int DefaultMaxMissionCount = 2;
public const int MaxMissionCountLimit = 10;
public const int MinMissionCountLimit = 1;
public CampaignSettings(IReadMessage inc)
{
maxMissionCount = DefaultMaxMissionCount;
RadiationEnabled = inc.ReadBoolean();
MaxMissionCount = inc.ReadRangedInteger(MinMissionCountLimit, MaxMissionCountLimit);
}
public CampaignSettings(XElement element)
{
maxMissionCount = DefaultMaxMissionCount;
RadiationEnabled = element.GetAttributeBool(nameof(RadiationEnabled).ToLowerInvariant(), true);
MaxMissionCount = element.GetAttributeInt(nameof(MaxMissionCount).ToLowerInvariant(), DefaultMaxMissionCount);
}
public void Serialize(IWriteMessage msg)
{
msg.Write(RadiationEnabled);
msg.WriteRangedInteger(MaxMissionCount, MinMissionCountLimit, MaxMissionCountLimit);
}
public int GetAddedMissionCount()
{
int count = 0;
foreach (Character character in GameSession.GetSessionCrewCharacters(CharacterType.Both))
{
count += (int)character.GetStatValue(StatTypes.ExtraMissionCount);
}
return count;
}
public XElement Save()
{
return new XElement(nameof(CampaignSettings), new XAttribute(nameof(RadiationEnabled).ToLowerInvariant(), RadiationEnabled), new XAttribute(nameof(MaxMissionCount).ToLowerInvariant(), MaxMissionCount));
}
}
abstract partial class CampaignMode : GameMode
{
[NetworkSerialize]
@@ -149,9 +92,8 @@ namespace Barotrauma
//key = dialog flag, double = Timing.TotalTime when the line was last said
private readonly Dictionary<string, double> dialogLastSpoken = new Dictionary<string, double>();
public bool PurchasedHullRepairs, PurchasedLostShuttles, PurchasedItemRepairs;
public SubmarineInfo PendingSubmarineSwitch;
public bool TransferItemsOnSubSwitch { get; set; }
protected Map map;
public Map Map
@@ -189,12 +131,16 @@ namespace Barotrauma
protected set;
}
protected CampaignMode(GameModePreset preset)
public virtual bool PurchasedHullRepairs { get; set; }
public virtual bool PurchasedLostShuttles { get; set; }
public virtual bool PurchasedItemRepairs { get; set; }
protected CampaignMode(GameModePreset preset, CampaignSettings settings)
: base(preset)
{
Bank = new Wallet(Option<Character>.None())
{
Balance = InitialMoney
Balance = settings.InitialMoney
};
CargoManager = new CargoManager(this);
@@ -596,6 +542,7 @@ namespace Barotrauma
if (Level.Loaded.StartOutpost == null)
{
Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartExitPosition, ignoreOutposts: true, ignoreRespawnShuttle: true, teamType: leavingPlayers.FirstOrDefault()?.TeamID);
if (closestSub == null) { return null; }
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
}
else
@@ -729,7 +676,6 @@ namespace Barotrauma
}
}
public void EndCampaign()
{
foreach (Character c in Character.CharacterList)
@@ -741,7 +687,7 @@ namespace Barotrauma
}
foreach (LocationConnection connection in Map.Connections)
{
connection.Difficulty = MathHelper.Lerp(connection.Difficulty, 100.0f, 0.25f);
connection.Difficulty = connection.Biome.MaxDifficulty;
connection.LevelData = new LevelData(connection)
{
IsBeaconActive = false
@@ -750,6 +696,7 @@ namespace Barotrauma
}
foreach (Location location in Map.Locations)
{
location.LevelData = new LevelData(location, location.Biome.MaxDifficulty);
location.Reset();
}
Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation));
@@ -873,7 +820,7 @@ namespace Barotrauma
const float MaxDist = 3000.0f;
const float MinDist = 2500.0f;
if (!Level.IsLoadedOutpost) { return; }
if (!Level.IsLoadedFriendlyOutpost) { return; }
Rectangle worldBorders = Submarine.MainSub.GetDockedBorders();
worldBorders.Location += Submarine.MainSub.WorldPosition.ToPoint();
@@ -1058,7 +1005,10 @@ namespace Barotrauma
public SubmarineInfo SwitchSubs()
{
TransferItemsBetweenSubs();
if (TransferItemsOnSubSwitch)
{
TransferItemsBetweenSubs();
}
RefreshOwnedSubmarines();
PendingSubmarineSwitch = null;
return GameMain.GameSession.SubmarineInfo;
@@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Xml.Linq;
namespace Barotrauma
{
internal static class CampaignModePresets
{
public static readonly ImmutableArray<CampaignSettings> List;
public static readonly ImmutableDictionary<Identifier, CampaignSettingDefinitions> Definitions;
private static readonly string fileListPath = Path.Combine("Data", "campaignsettings.xml");
static CampaignModePresets()
{
if (!File.Exists(fileListPath) || !(XMLExtensions.TryLoadXml(fileListPath)?.Root is { } docRoot))
{
List = ImmutableArray<CampaignSettings>.Empty;
return;
}
List<CampaignSettings> list = new List<CampaignSettings>();
Dictionary<Identifier, CampaignSettingDefinitions> definitions = new Dictionary<Identifier, CampaignSettingDefinitions>();
foreach (XElement element in docRoot.Elements())
{
Identifier name = element.NameAsIdentifier();
if (name == CampaignSettings.LowerCaseSaveElementName)
{
list.Add(new CampaignSettings(element));
}
else if (name == nameof(CampaignSettingDefinitions))
{
foreach (XElement subElement in element.Elements())
{
definitions.Add(subElement.NameAsIdentifier(), new CampaignSettingDefinitions(subElement));
}
}
}
List = list.ToImmutableArray();
Definitions = definitions.ToImmutableDictionary();
}
}
internal readonly struct CampaignSettingDefinitions
{
// Definitely not the best way to do this
private readonly ImmutableDictionary<Identifier, Either<int, float>> values;
public CampaignSettingDefinitions(XElement element)
{
var definitions = new Dictionary<Identifier, Either<int, float>>();
foreach (XAttribute attribute in element.Attributes())
{
Identifier name = attribute.NameAsIdentifier();
if (attribute.Value.Contains('.'))
{
definitions.Add(name, element.GetAttributeFloat(name.Value, 0));
}
else
{
definitions.Add(name, element.GetAttributeInt(name.Value, 0));
}
}
values = definitions.ToImmutableDictionary();
}
public float GetFloat(Identifier identifier)
{
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out float range) ? range : 0.0f;
}
public int GetInt(Identifier identifier)
{
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out int integer) ? integer : 0;
}
}
}
@@ -0,0 +1,114 @@
#nullable enable
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma
{
internal class CampaignSettings : INetSerializableStruct, ISerializableEntity
{
public static CampaignSettings Empty => new CampaignSettings(element: null);
public string Name => "CampaignSettings";
public const string LowerCaseSaveElementName = "campaignsettings";
[Serialize("", IsPropertySaveable.Yes)]
public string PresetName { get; set; } = string.Empty;
[Serialize(false, IsPropertySaveable.Yes), NetworkSerialize]
public bool RadiationEnabled { get; set; }
private int maxMissionCount;
[Serialize(DefaultMaxMissionCount, IsPropertySaveable.Yes), NetworkSerialize(MinValueInt = MinMissionCountLimit, MaxValueInt = MaxMissionCountLimit)]
public int MaxMissionCount
{
get => maxMissionCount;
set => maxMissionCount = MathHelper.Clamp(value, MinMissionCountLimit, MaxMissionCountLimit);
}
public int TotalMaxMissionCount => MaxMissionCount + GetAddedMissionCount();
[Serialize(StartingBalanceAmount.Medium, IsPropertySaveable.Yes), NetworkSerialize]
public StartingBalanceAmount StartingBalanceAmount { get; set; }
[Serialize(GameDifficulty.Medium, IsPropertySaveable.Yes), NetworkSerialize]
public GameDifficulty Difficulty { get; set; }
[Serialize("normal", IsPropertySaveable.Yes), NetworkSerialize]
public Identifier StartItemSet { get; set; }
public int InitialMoney
{
get
{
if (CampaignModePresets.Definitions.TryGetValue(nameof(StartingBalanceAmount).ToIdentifier(), out var definition))
{
return definition.GetInt(StartingBalanceAmount.ToIdentifier());
}
return 8000;
}
}
public float ExtraEventManagerDifficulty
{
get
{
if (CampaignModePresets.Definitions.TryGetValue(nameof(ExtraEventManagerDifficulty).ToIdentifier(), out var definition))
{
return definition.GetFloat(Difficulty.ToIdentifier());
}
return 0;
}
}
public float LevelDifficultyMultiplier
{
get
{
if (CampaignModePresets.Definitions.TryGetValue(nameof(LevelDifficultyMultiplier).ToIdentifier(), out var definition))
{
return definition.GetFloat(Difficulty.ToIdentifier());
}
return 1.0f;
}
}
public const int DefaultMaxMissionCount = 2;
public const int MaxMissionCountLimit = 10;
public const int MinMissionCountLimit = 1;
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; private set; }
// required for INetSerializableStruct
public CampaignSettings()
{
SerializableProperties = SerializableProperty.GetProperties(this);
}
public CampaignSettings(XElement? element = null)
{
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
}
public XElement Save()
{
XElement saveElement = new XElement(LowerCaseSaveElementName);
SerializableProperty.SerializeProperties(this, saveElement, saveIfDefault: true);
return saveElement;
}
private static int GetAddedMissionCount()
{
int count = 0;
foreach (Character character in GameSession.GetSessionCrewCharacters(CharacterType.Both))
{
count += (int)character.GetStatValue(StatTypes.ExtraMissionCount);
}
return count;
}
}
}
@@ -29,7 +29,11 @@ namespace Barotrauma
: base(preset)
{
Location[] locations = { GameMain.GameSession.StartLocation, GameMain.GameSession.EndLocation };
missions.Add(Mission.LoadRandom(locations, seed, false, missionType));
var mission = Mission.LoadRandom(locations, seed, false, missionType);
if (mission != null)
{
missions.Add(mission);
}
}
protected static IEnumerable<MissionPrefab> ValidateMissionPrefabs(IEnumerable<MissionPrefab> missionPrefabs, Dictionary<MissionType, Type> missionClasses)
@@ -12,19 +12,60 @@ namespace Barotrauma
{
public const int MinimumInitialMoney = 500;
private UInt16 lastUpdateID;
public UInt16 LastUpdateID
[Flags]
public enum NetFlags : UInt16
{
get
{
#if SERVER
if (GameMain.Server != null && lastUpdateID < 1) { lastUpdateID++; }
#endif
return lastUpdateID;
}
set { lastUpdateID = value; }
Misc = 0x1,
MapAndMissions = 0x2,
UpgradeManager = 0x4,
SubList = 0x8,
ItemsInBuyCrate = 0x10,
ItemsInSellFromSubCrate = 0x20,
PurchasedItems = 0x80,
SoldItems = 0x100,
Reputation = 0x200,
CharacterInfo = 0x800
}
private readonly Dictionary<NetFlags, UInt16> lastUpdateID;
public UInt16 GetLastUpdateIdForFlag(NetFlags flag)
{
if (!ValidateFlag(flag)) { return 0; }
return lastUpdateID[flag];
}
public void SetLastUpdateIdForFlag(NetFlags flag, UInt16 id)
{
if (!ValidateFlag(flag)) { return; }
lastUpdateID[flag] = id;
}
public void IncrementLastUpdateIdForFlag(NetFlags flag)
{
if (!ValidateFlag(flag)) { return; }
if (!lastUpdateID.ContainsKey(flag)) { lastUpdateID[flag] = 0; }
lastUpdateID[flag]++;
}
public void IncrementAllLastUpdateIds()
{
foreach (NetFlags flag in Enum.GetValues(typeof(NetFlags)))
{
if (!lastUpdateID.ContainsKey(flag)) { lastUpdateID[flag] = 0; }
lastUpdateID[flag]++;
}
}
private bool ValidateFlag(NetFlags flag)
{
if (MathHelper.IsPowerOfTwo((int)flag)) { return true; }
#if DEBUG
throw new InvalidOperationException($"\"{flag}\" is not a valid campaign update flag.");
#else
return false;
#endif
}
private UInt16 lastSaveID;
public UInt16 LastSaveID
{
@@ -35,11 +76,11 @@ namespace Barotrauma
#endif
return lastSaveID;
}
set
set
{
#if SERVER
//trigger a campaign update to notify the clients of the changed save ID
lastUpdateID++;
IncrementLastUpdateIdForFlag(NetFlags.Misc);
#endif
lastSaveID = value;
}
@@ -52,23 +93,33 @@ namespace Barotrauma
get; set;
}
private MultiPlayerCampaign() : base(GameModePreset.MultiPlayerCampaign)
private MultiPlayerCampaign(CampaignSettings settings) : base(GameModePreset.MultiPlayerCampaign, settings)
{
currentCampaignID++;
lastUpdateID = new Dictionary<NetFlags, ushort>();
foreach (NetFlags flag in Enum.GetValues(typeof(NetFlags)))
{
#if SERVER
//server starts from a higher ID to ensure we send the initial state
lastUpdateID[flag] = 1;
#else
lastUpdateID[flag] = 0;
#endif
}
CampaignID = currentCampaignID;
CampaignMetadata = new CampaignMetadata(this);
UpgradeManager = new UpgradeManager(this);
InitCampaignData();
}
public static MultiPlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub, CampaignSettings settings)
public static MultiPlayerCampaign StartNew(string mapSeed, CampaignSettings settings)
{
MultiPlayerCampaign campaign = new MultiPlayerCampaign();
MultiPlayerCampaign campaign = new MultiPlayerCampaign(settings);
//only the server generates the map, the clients load it from a save file
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
campaign.map = new Map(campaign, mapSeed, settings);
campaign.Settings = settings;
campaign.map = new Map(campaign, mapSeed);
}
campaign.InitProjSpecific();
return campaign;
@@ -76,7 +127,7 @@ namespace Barotrauma
public static MultiPlayerCampaign LoadNew(XElement element)
{
MultiPlayerCampaign campaign = new MultiPlayerCampaign();
MultiPlayerCampaign campaign = new MultiPlayerCampaign(CampaignSettings.Empty);
campaign.Load(element);
campaign.InitProjSpecific();
campaign.IsFirstRound = false;
@@ -124,18 +175,17 @@ namespace Barotrauma
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "campaignsettings":
case CampaignSettings.LowerCaseSaveElementName:
Settings = new CampaignSettings(subElement);
#if CLIENT
GameMain.NetworkMember.ServerSettings.MaxMissionCount = Settings.MaxMissionCount;
GameMain.NetworkMember.ServerSettings.RadiationEnabled = Settings.RadiationEnabled;
GameMain.NetworkMember.ServerSettings.CampaignSettings = Settings;
#endif
break;
case "map":
if (map == null)
{
//map not created yet, loading this campaign for the first time
map = Map.Load(this, subElement, Settings);
map = Map.Load(this, subElement);
}
else
{
@@ -72,7 +72,7 @@ namespace Barotrauma
get
{
if (Map != null) { return Map.CurrentLocation; }
if (dummyLocations == null) { CreateDummyLocations(); }
if (dummyLocations == null) { dummyLocations = CreateDummyLocations(LevelData?.Seed ?? string.Empty); }
if (dummyLocations == null) { throw new NullReferenceException("dummyLocations is null somehow!"); }
return dummyLocations[0];
}
@@ -83,7 +83,7 @@ namespace Barotrauma
get
{
if (Map != null) { return Map.SelectedLocation; }
if (dummyLocations == null) { CreateDummyLocations(); }
if (dummyLocations == null) { dummyLocations = CreateDummyLocations(LevelData?.Seed ?? string.Empty); }
if (dummyLocations == null) { throw new NullReferenceException("dummyLocations is null somehow!"); }
return dummyLocations[1];
}
@@ -207,7 +207,7 @@ namespace Barotrauma
}
else if (gameModePreset.GameModeType == typeof(MultiPlayerCampaign))
{
var campaign = MultiPlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), selectedSub, settings);
var campaign = MultiPlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), settings);
if (selectedSub != null)
{
campaign.Bank.Deduct(selectedSub.Price);
@@ -218,7 +218,7 @@ namespace Barotrauma
#if CLIENT
else if (gameModePreset.GameModeType == typeof(SinglePlayerCampaign))
{
var campaign = SinglePlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), selectedSub, settings);
var campaign = SinglePlayerCampaign.StartNew(seed ?? ToolBox.RandomSeed(8), settings);
if (selectedSub != null)
{
campaign.Bank.TryDeduct(selectedSub.Price);
@@ -245,25 +245,15 @@ namespace Barotrauma
}
}
private void CreateDummyLocations(LocationType? forceLocationType = null)
public static Location[] CreateDummyLocations(string seed, LocationType? forceLocationType = null)
{
dummyLocations = new Location[2];
string seed = "";
if (GameMain.GameSession != null && GameMain.GameSession.Level != null)
{
seed = GameMain.GameSession.Level.Seed;
}
else if (GameMain.NetLobbyScreen != null)
{
seed = GameMain.NetLobbyScreen.LevelSeed;
}
var dummyLocations = new Location[2];
MTRandom rand = new MTRandom(ToolBox.StringToInt(seed));
for (int i = 0; i < 2; i++)
{
dummyLocations[i] = Location.CreateRandom(new Vector2((float)rand.NextDouble() * 10000.0f, (float)rand.NextDouble() * 10000.0f), null, rand, requireOutpost: true, forceLocationType: forceLocationType);
}
return dummyLocations;
}
public void LoadPreviousSave()
@@ -275,7 +265,7 @@ namespace Barotrauma
/// <summary>
/// Switch to another submarine. The sub is loaded when the next round starts.
/// </summary>
public void SwitchSubmarine(SubmarineInfo newSubmarine, int cost, Client? client = null)
public void SwitchSubmarine(SubmarineInfo newSubmarine, bool transferItems, int cost, Client? client = null)
{
if (!OwnedSubmarines.Any(s => s.Name == newSubmarine.Name))
{
@@ -299,6 +289,7 @@ namespace Barotrauma
}
GameAnalyticsManager.AddMoneySpentEvent(cost, GameAnalyticsManager.MoneySink.SubmarineSwitch, newSubmarine.Name);
Campaign!.PendingSubmarineSwitch = newSubmarine;
Campaign!.TransferItemsOnSubSwitch = transferItems;
}
public void PurchaseSubmarine(SubmarineInfo newSubmarine, Client? client = null)
@@ -309,6 +300,9 @@ namespace Barotrauma
{
GameAnalyticsManager.AddMoneySpentEvent(newSubmarine.Price, GameAnalyticsManager.MoneySink.SubmarinePurchase, newSubmarine.Name);
OwnedSubmarines.Add(newSubmarine);
#if SERVER
(Campaign as MultiPlayerCampaign)?.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.SubList);
#endif
}
}
@@ -345,7 +339,7 @@ namespace Barotrauma
!missionPrefab.AllowedConnectionTypes.Any())
{
LocationType? locationType = LocationType.Prefabs.FirstOrDefault(lt => missionPrefab.AllowedLocationTypes.Any(m => m == lt.Identifier));
CreateDummyLocations(locationType);
dummyLocations = CreateDummyLocations(levelSeed, locationType);
randomLevel = LevelData.CreateRandom(levelSeed, difficulty, levelGenerationParams, requireOutpost: true);
break;
}
@@ -430,7 +424,7 @@ namespace Barotrauma
Level? level = null;
if (levelData != null)
{
level = Level.Generate(levelData, mirrorLevel, startOutpost, endOutpost);
level = Level.Generate(levelData, mirrorLevel, StartLocation, EndLocation, startOutpost, endOutpost);
}
InitializeLevel(level);
@@ -603,7 +597,7 @@ namespace Barotrauma
Level.SpawnCorpses();
Level.PrepareBeaconStation();
}
AutoItemPlacer.SpawnItems();
AutoItemPlacer.SpawnItems(Campaign?.Settings.StartItemSet);
}
if (GameMode is MultiPlayerCampaign mpCampaign)
{