From 856f894203f247611735929f62883762c1ddf2a3 Mon Sep 17 00:00:00 2001 From: Markus Isberg <3e849f2e5c@pm.me> Date: Tue, 14 Jun 2022 04:14:47 +0900 Subject: [PATCH] Build 0.18.9.0 --- .../Events/Missions/AlienRuinMission.cs | 2 - .../ClientSource/GUI/GUICanvas.cs | 29 +- .../ClientSource/GUI/GUIStyle.cs | 16 + .../BarotraumaClient/ClientSource/GameMain.cs | 10 +- .../GameModes/MultiPlayerCampaign.cs | 5 +- .../GameModes/Tutorials/ScenarioTutorial.cs | 5 +- .../Map/Creatures/BallastFloraBehavior.cs | 13 + .../ClientSource/Networking/GameClient.cs | 7 + .../ClientSource/Screens/CampaignUI.cs | 12 +- .../ClientSource/Screens/MainMenuScreen.cs | 1 + .../ClientSource/Screens/SubEditorScreen.cs | 5 +- .../ClientSource/Steam/BulkDownloader.cs | 4 +- .../WorkshopMenu/Mutable/InstalledTab.cs | 6 +- .../Steam/WorkshopMenu/Mutable/ItemList.cs | 14 +- .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../ServerSource/Networking/RespawnManager.cs | 2 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- .../AI/Objectives/AIObjectivePumpWater.cs | 1 + .../SharedSource/DebugConsole.cs | 10 + .../SharedSource/Events/EventManager.cs | 8 + .../SharedSource/Events/EventSet.cs | 20 +- .../Events/Missions/AlienRuinMission.cs | 11 +- .../Events/Missions/CargoMission.cs | 142 ++++--- .../SharedSource/Events/ScriptedEvent.cs | 1 - .../GameSession/GameModes/CampaignMode.cs | 2 + .../SharedSource/GameSession/GameSession.cs | 4 +- .../Items/Components/ItemContainer.cs | 40 +- .../Items/Components/Projectile.cs | 4 + .../Map/Creatures/BallastFloraBehavior.cs | 26 +- .../SharedSource/Map/LinkedSubmarine.cs | 37 +- .../SharedSource/Screens/GameScreen.cs | 5 +- .../Serialization/SerializableProperty.cs | 2 +- .../SharedSource/Settings/GameSettings.cs | 17 +- .../SharedSource/Utils/TaskPool.cs | 10 +- Barotrauma/BarotraumaShared/changelog.txt | 353 ++++++------------ 39 files changed, 459 insertions(+), 377 deletions(-) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AlienRuinMission.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AlienRuinMission.cs index dbfd01ecc..f4a737254 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AlienRuinMission.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AlienRuinMission.cs @@ -20,14 +20,12 @@ namespace Barotrauma if (targetId == Entity.NullEntityID) { continue; } Entity target = Entity.FindEntityByID(targetId); if (target == null) { continue; } - existingTargets.Add(target); allTargets.Add(target); } ushort spawnedTargetsCount = msg.ReadUInt16(); for (int i = 0; i < spawnedTargetsCount; i++) { var enemy = Character.ReadSpawnData(msg); - existingTargets.Add(enemy); allTargets.Add(enemy); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUICanvas.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUICanvas.cs index c555ce055..d27e2c086 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUICanvas.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUICanvas.cs @@ -8,6 +8,8 @@ namespace Barotrauma { public class GUICanvas : RectTransform { + private static readonly object mutex = new object(); + protected GUICanvas() : base(size, parent: null) { } private static GUICanvas _instance; @@ -39,22 +41,25 @@ namespace Barotrauma private static void OnChildrenChanged(RectTransform _) { - //add weak reference if we don't have one yet - foreach (var child in _instance.Children) + lock (mutex) { - if (!_instance.childrenWeakRef.Any(c => c.TryGetTarget(out var existingChild) && existingChild == child)) + //add weak reference if we don't have one yet + foreach (var child in _instance.Children) { - _instance.childrenWeakRef.Add(new WeakReference(child)); + if (!_instance.childrenWeakRef.Any(c => c.TryGetTarget(out var existingChild) && existingChild == child)) + { + _instance.childrenWeakRef.Add(new WeakReference(child)); + } } - } - //get rid of strong references - _instance.children.Clear(); - //remove dead children - for (int i = _instance.childrenWeakRef.Count - 2; i >= 0; i--) - { - if (!_instance.childrenWeakRef[i].TryGetTarget(out var child) || child.Parent != _instance) + //get rid of strong references + _instance.children.Clear(); + //remove dead children + for (int i = _instance.childrenWeakRef.Count - 2; i >= 0; i--) { - _instance.childrenWeakRef.RemoveAt(i); + if (!_instance.childrenWeakRef[i].TryGetTarget(out var child) || child.Parent != _instance) + { + _instance.childrenWeakRef.RemoveAt(i); + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index d81ee4206..27be2752f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -207,5 +207,21 @@ namespace Barotrauma return ItemQualityColorNormal; } } + + public static void RecalculateFonts() + { + foreach (var font in Fonts.Values) + { + font.Prefabs.ForEach(p => p.LoadFont()); + } + } + + public static void RecalculateSizeRestrictions() + { + foreach (var componentStyle in ComponentStyles) + { + componentStyle.RefreshSize(); + } + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index 7f55a1968..6a926c4da 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -282,9 +282,9 @@ namespace Barotrauma screen.OnFileDropped(filePath, extension); } - public void ApplyGraphicsSettings() + public void ApplyGraphicsSettings(bool recalculateFontsAndStyles = false) { - void updateConfig() + static void updateConfig() { var config = GameSettings.CurrentConfig; config.Graphics.Width = GraphicsWidth; @@ -323,6 +323,12 @@ namespace Barotrauma defaultViewport = GraphicsDevice.Viewport; + if (recalculateFontsAndStyles) + { + GUIStyle.RecalculateFonts(); + GUIStyle.RecalculateSizeRestrictions(); + } + ResolutionChanged?.Invoke(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index 41d89b0d5..8fc431ad8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -745,7 +745,8 @@ namespace Barotrauma purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall)); } - if (ShouldApply(NetFlags.UpgradeManager, id, requireUpToDateSave: true)) + if (!Submarine.Unloading && !(Submarine.MainSub is { Loading: true }) && + ShouldApply(NetFlags.UpgradeManager, id, requireUpToDateSave: true)) { UpgradeStore.WaitForServerUpdate = false; campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades); @@ -761,7 +762,7 @@ namespace Barotrauma campaign.UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall, force: true); } } - foreach (Item item in Item.ItemList) + foreach (Item item in Item.ItemList.ToList()) { if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs index 01142cabe..7d72179b1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs @@ -1,10 +1,7 @@ using Barotrauma.Items.Components; using Microsoft.Xna.Framework; -using System; using System.Collections.Generic; -using Barotrauma.IO; using System.Linq; -using System.Xml.Linq; namespace Barotrauma.Tutorials { @@ -228,6 +225,8 @@ namespace Barotrauma.Tutorials { CoroutineManager.StopCoroutines(tutorialCoroutine); } + GUI.PreventPauseMenuToggle = false; + ContentRunning = false; infoBox = null; } else if (Character.Controlled.IsDead) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs index 264b5b2e7..0fc5d2c4f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs @@ -183,8 +183,21 @@ namespace Barotrauma.MapCreatures.Behavior Color branchColor = (branch.IsRoot || branch.IsRootGrowth) ? RootColor : Color.White; + if (GameMain.DebugDraw) { + if (branch.DisconnectedFromRoot && branch.ParentBranch == null) + { + branchColor = Color.Yellow; + } + else if (branch.DisconnectedFromRoot) + { + branchColor = Color.Cyan; + } + else if (branch.ParentBranch == null) + { + branchColor = Color.Magenta; + } #if DEBUG Vector2 basePos = Parent.WorldPosition; foreach (var (from, to) in debugSearchLines) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 2419901fd..fdb7451f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -1696,6 +1696,13 @@ namespace Barotrauma.Networking } } + if (clientPeer == null) + { + DebugConsole.ThrowError("There was an error initializing the round (disconnected during the StartGame coroutine.)"); + roundInitStatus = RoundInitStatus.Error; + yield return CoroutineStatus.Failure; + } + roundInitStatus = RoundInitStatus.WaitingForStartGameFinalize; DateTime? timeOut = null; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index 6cc459e40..3d0a30141 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -526,7 +526,7 @@ namespace Barotrauma tickBox.OnSelected += (GUITickBox tb) => { if (!Campaign.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap)) { return false; } - + if (tb.Selected) { Campaign.Map.CurrentLocation.SelectMission(mission); @@ -549,7 +549,7 @@ namespace Barotrauma { GameMain.Client?.SendCampaignState(); } - return true; + return true; }; missionTickBoxes.Add(tickBox); @@ -731,6 +731,14 @@ namespace Barotrauma if (submarineSelection == null) submarineSelection = new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform); submarineSelection.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true); break; + case CampaignMode.InteractionType.Map: + //refresh mission rewards (may have been changed by e.g. a pending submarine switch) + foreach (GUITextBlock rewardText in missionRewardTexts) + { + Mission mission = (Mission)rewardText.UserData; + rewardText.Text = mission.GetMissionRewardText(Submarine.MainSub); + } + break; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 14748954f..88691410e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -74,6 +74,7 @@ namespace Barotrauma { CreateHostServerFields(); CreateCampaignSetupUI(); + SettingsMenu.Create(menuTabs[Tab.Settings].RectTransform); if (remoteContentDoc?.Root != null) { remoteContentContainer.ClearChildren(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 4ba25491a..61a57a7ef 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1549,10 +1549,7 @@ namespace Barotrauma MapEntity.DeselectAll(); ClearUndoBuffer(); - GameMain.DebugDraw = false; - GameMain.LightManager.LightingEnabled = true; - Hull.EditWater = false; - Hull.EditFire = false; + DebugConsole.DeactivateCheats(); SetMode(Mode.Default); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs index b8f6328f8..ddac26c05 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/BulkDownloader.cs @@ -119,9 +119,11 @@ namespace Barotrauma.Steam onComplete?.Invoke(); } msgBox.Close(); + ContentPackageManager.WorkshopPackages.Refresh(); + ContentPackageManager.EnabledPackages.RefreshUpdatedMods(); if (SettingsMenu.Instance?.WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu) { - mutableWorkshopMenu.PopulateInstalledModLists(); + mutableWorkshopMenu.PopulateInstalledModLists(forceRefreshEnabled: true); } }); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs index 27689b385..2e5953ae5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs @@ -589,7 +589,7 @@ namespace Barotrauma.Steam isEnabled: true, onSelected: () => { - TaskPool.Add($"UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => SteamManager.Workshop.GetItem(m.SteamWorkshopId))), + TaskPool.AddIfNotFound($"UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => SteamManager.Workshop.GetItem(m.SteamWorkshopId))), t => { if (!t.TryGetResult(out Steamworks.Ugc.Item?[] items)) { return; } @@ -668,7 +668,7 @@ namespace Barotrauma.Steam { infoButton.Enabled = false; } - TaskPool.Add( + TaskPool.AddIfNotFound( $"DetermineUpdateRequired{mod.SteamWorkshopId}", mod.IsUpToDate(), t => @@ -709,7 +709,7 @@ namespace Barotrauma.Steam addRegularModsToList(enabledMods, enabledRegularModsList); if (refreshDisabled) { addRegularModsToList(disabledMods, disabledRegularModsList); } - TaskPool.Add( + TaskPool.AddIfNotFound( $"DetermineWorkshopModIcons", SteamManager.Workshop.GetPublishedItems(), t => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs index b739b3149..e4e155950 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/ItemList.cs @@ -418,7 +418,7 @@ namespace Barotrauma.Steam itemListBox.ClearChildren(); itemListBox.Deselect(); itemListBox.ScrollBar.BarScroll = 0.0f; - TaskPool.Add("PopulateTabWithItemList", items, + TaskPool.AddIfNotFound("PopulateTabWithItemList", items, (t) => { taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc; @@ -591,16 +591,16 @@ namespace Barotrauma.Steam bool reinstallAction(GUIButton button, object o) { - TaskPool.Add($"Reinstall{workshopItem.Id}", SteamManager.Workshop.Reinstall(workshopItem), t => + int prevIndex = ContentPackageManager.EnabledPackages.Regular.IndexOf(contentPackage); + TaskPool.AddIfNotFound($"Reinstall{workshopItem.Id}", + SteamManager.Workshop.Reinstall(workshopItem), t => { ContentPackageManager.WorkshopPackages.Refresh(); ContentPackageManager.EnabledPackages.RefreshUpdatedMods(); - var package = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id); - if (package is RegularPackage regular) + if (SettingsMenu.Instance?.WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu) { - ContentPackageManager.EnabledPackages.EnableRegular(regular); + mutableWorkshopMenu.PopulateInstalledModLists(forceRefreshEnabled: true); } - PopulateInstalledModLists(forceRefreshEnabled: true); }); return false; } @@ -615,7 +615,7 @@ namespace Barotrauma.Steam if (contentPackage != null) { - TaskPool.Add( + TaskPool.AddIfNotFound( $"DetermineUpdateRequired{contentPackage.SteamWorkshopId}", contentPackage.IsUpToDate(), t => diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 7e5c42815..dcb6b28f4 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 8c28ff5dd..dfc188b15 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 6db93f270..8043dbfaf 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 133bbd9d4..26ca8d0d6 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 961807808..883360337 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index 889820327..de685bebf 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -390,7 +390,7 @@ namespace Barotrauma.Networking characterInfos[i].ClearCurrentOrders(); bool forceSpawnInMainSub = false; - if (!bot && campaign != null) + if (!bot) { //the client has opted to change the name of their new character //when the character spawns, set the client's name to match diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 1005239b1..e1bf7a611 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.7.0 + 0.18.9.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs index 6377ef8a5..eb232b4f2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs @@ -26,6 +26,7 @@ namespace Barotrauma protected override bool Filter(Pump pump) { + if (pump?.Item == null || pump.Item.Removed) { return false; } if (pump.Item.IgnoreByAI(character)) { return false; } if (!pump.Item.IsInteractable(character)) { return false; } if (pump.IsAutoControlled) { return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 3722751b0..0b4ac4c1d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -2526,5 +2526,15 @@ namespace Barotrauma ThrowError("Saving debug console log to " + filePath + " failed", e); } } + + public static void DeactivateCheats() + { +#if CLIENT + GameMain.DebugDraw = false; + GameMain.LightManager.LightingEnabled = true; +#endif + Hull.EditWater = false; + Hull.EditFire = false; + } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs index 94b7d0c01..63dd365ef 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs @@ -408,6 +408,14 @@ namespace Barotrauma bool isPrefabSuitable(EventPrefab e) => e.BiomeIdentifier.IsEmpty || e.BiomeIdentifier == level.LevelData?.Biome?.Identifier; + + foreach (var subEventPrefab in eventSet.EventPrefabs) + { + foreach (Identifier missingId in subEventPrefab.GetMissingIdentifiers()) + { + DebugConsole.ThrowError($"Error in event set \"{eventSet.Identifier}\" ({eventSet.ContentFile?.ContentPackage?.Name ?? "null"}) - could not find an event prefab with the identifier \"{missingId}\"."); + } + } var suitablePrefabSubsets = eventSet.EventPrefabs.Where( e => e.EventPrefabs.Any(isPrefabSuitable)).ToArray(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs index ebd615008..3c2be4201 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventSet.cs @@ -142,11 +142,15 @@ namespace Barotrauma { foreach (var id in (Identifier[])PrefabOrIdentifier) { - yield return EventPrefab.Prefabs[id]; + if (EventPrefab.Prefabs.TryGet(id, out EventPrefab prefab)) + { + yield return prefab; + } } } } } + public readonly float? SelfCommonness; public float Commonness => SelfCommonness ?? EventPrefabs.MaxOrNull(p => p.Commonness) ?? 0.0f; @@ -159,6 +163,20 @@ namespace Barotrauma commonness = Commonness; probability = Probability; } + + public IEnumerable GetMissingIdentifiers() + { + if (PrefabOrIdentifier.TryCast(out var ids)) + { + foreach (var id in ids) + { + if (!EventPrefab.Prefabs.ContainsKey(id)) + { + yield return id; + } + } + } + } } public readonly ImmutableArray EventPrefabs; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs index 78ddfaed8..2ed692fa5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AlienRuinMission.cs @@ -125,10 +125,6 @@ namespace Barotrauma if (!AllTargetsEliminated()) { return; } State = 1; break; - case 1: - if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; } - State = 2; - break; } } @@ -166,11 +162,16 @@ namespace Barotrauma public override void End() { - if (State == 2) + bool exitingLevel = GameMain.GameSession?.GameMode is CampaignMode campaign ? + campaign.GetAvailableTransition() != CampaignMode.TransitionType.None : + Submarine.MainSub is { } sub && (sub.AtEndExit || sub.AtStartExit); + + if (State > 0 && exitingLevel) { GiveReward(); completed = true; } + failed = !completed && State > 0; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs index 8a02928df..58aae000c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs @@ -3,7 +3,6 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { @@ -23,15 +22,16 @@ namespace Barotrauma private int calculatedReward; private int maxItemCount; - private Submarine sub; - + private Submarine currentSub; + private SubmarineInfo nextRoundSubInfo; + private readonly List previouslySelectedMissions = new List(); public override LocalizedString Description { get { - if (Submarine.MainSub != sub) + if ((GameMain.GameSession?.Campaign?.PendingSubmarineSwitch ?? Submarine.MainSub?.Info) != nextRoundSubInfo) { string rewardText = $"‖color:gui.orange‖{string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:N0}", GetReward(Submarine.MainSub))}‖end‖"; if (descriptionWithoutReward != null) { description = descriptionWithoutReward.Replace("[reward]", rewardText); } @@ -43,7 +43,8 @@ namespace Barotrauma public CargoMission(MissionPrefab prefab, Location[] locations, Submarine sub) : base(prefab, locations, sub) { - this.sub = sub; + this.currentSub = sub; + this.nextRoundSubInfo = sub?.Info; itemConfig = prefab.ConfigElement.GetChildElement("Items"); requiredDeliveryAmount = Math.Min(prefab.ConfigElement.GetAttributeFloat("requireddeliveryamount", 0.98f), 1.0f); //this can get called between rounds when the client receives a campaign save @@ -57,39 +58,13 @@ namespace Barotrauma private void DetermineCargo() { - if (this.sub == null || itemConfig == null) + if (this.currentSub == null || itemConfig == null) { calculatedReward = Prefab.Reward; return; } itemsToSpawn.Clear(); - List<(ItemContainer container, int freeSlots)> containers = sub.GetCargoContainers(); - containers.Sort((c1, c2) => { return c2.container.Capacity.CompareTo(c1.container.Capacity); }); - - previouslySelectedMissions.Clear(); - if (GameMain.GameSession?.StartLocation?.SelectedMissions != null) - { - bool isPriorMission = true; - foreach (Mission mission in GameMain.GameSession.StartLocation.SelectedMissions) - { - if (!(mission is CargoMission otherMission)) { continue; } - if (mission == this) { isPriorMission = false; } - previouslySelectedMissions.Add(otherMission); - if (!isPriorMission) { continue; } - foreach (var (element, container) in otherMission.itemsToSpawn) - { - for (int i = 0; i < containers.Count; i++) - { - if (containers[i].container == container) - { - containers[i] = (containers[i].container, containers[i].freeSlots - 1); - break; - } - } - } - } - } maxItemCount = 0; foreach (var subElement in itemConfig.Elements()) @@ -98,18 +73,85 @@ namespace Barotrauma maxItemCount += maxCount; } - for (int i = 0; i < containers.Count; i++) + var pendingSubInfo = GameMain.GameSession?.Campaign?.PendingSubmarineSwitch; + if (pendingSubInfo != null && pendingSubInfo != currentSub.Info) { - foreach (var subElement in itemConfig.Elements()) + //if we've got a submarine switch pending, calculate the amount of cargo based on it's cargo capacity + //TODO: this isn't guaranteed to be accurate, because we don't take existing items in the new sub's cargo containers + //or items that might get transferred in them into account + maxItemCount = Math.Min(maxItemCount, pendingSubInfo.CargoCapacity); + previouslySelectedMissions.Clear(); + if (GameMain.GameSession?.StartLocation?.SelectedMissions != null) { - int maxCount = subElement.GetAttributeInt("maxcount", 10); - if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { continue; } - ItemPrefab itemPrefab = FindItemPrefab(subElement); - while (containers[i].freeSlots > 0 && containers[i].container.Inventory.CanBePut(itemPrefab)) + bool isPriorMission = true; + foreach (Mission mission in GameMain.GameSession.StartLocation.SelectedMissions) { - containers[i] = (containers[i].container, containers[i].freeSlots - 1); - itemsToSpawn.Add((subElement, containers[i].container)); - if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { break; } + if (!(mission is CargoMission otherMission)) { continue; } + if (mission == this) { isPriorMission = false; } + previouslySelectedMissions.Add(otherMission); + if (!isPriorMission) { continue; } + maxItemCount -= otherMission.itemsToSpawn.Count; + } + } + for (int i = 0; i < maxItemCount; i++) + { + foreach (var subElement in itemConfig.Elements()) + { + int maxCount = subElement.GetAttributeInt("maxcount", 10); + if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { continue; } + ItemPrefab itemPrefab = FindItemPrefab(subElement); + while (itemsToSpawn.Count < maxItemCount) + { + itemsToSpawn.Add((subElement, null)); + if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { break; } + } + } + } + maxItemCount = Math.Max(0, maxItemCount); + nextRoundSubInfo = pendingSubInfo; + } + else + { + List<(ItemContainer container, int freeSlots)> containers = currentSub.GetCargoContainers(); + containers.Sort((c1, c2) => { return c2.container.Capacity.CompareTo(c1.container.Capacity); }); + + previouslySelectedMissions.Clear(); + if (GameMain.GameSession?.StartLocation?.SelectedMissions != null) + { + bool isPriorMission = true; + foreach (Mission mission in GameMain.GameSession.StartLocation.SelectedMissions) + { + if (!(mission is CargoMission otherMission)) { continue; } + if (mission == this) { isPriorMission = false; } + previouslySelectedMissions.Add(otherMission); + if (!isPriorMission) { continue; } + foreach (var (element, container) in otherMission.itemsToSpawn) + { + for (int i = 0; i < containers.Count; i++) + { + if (containers[i].container == container) + { + containers[i] = (containers[i].container, containers[i].freeSlots - 1); + break; + } + } + } + } + } + + for (int i = 0; i < containers.Count; i++) + { + foreach (var subElement in itemConfig.Elements()) + { + int maxCount = subElement.GetAttributeInt("maxcount", 10); + if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { continue; } + ItemPrefab itemPrefab = FindItemPrefab(subElement); + while (containers[i].freeSlots > 0 && containers[i].container.Inventory.CanBePut(itemPrefab)) + { + containers[i] = (containers[i].container, containers[i].freeSlots - 1); + itemsToSpawn.Add((subElement, containers[i].container)); + if (itemsToSpawn.Count(it => it.element == subElement) >= maxCount) { break; } + } } } } @@ -135,7 +177,7 @@ namespace Barotrauma } if (rewardPerCrate.HasValue && rewardPerCrate < 0) { rewardPerCrate = null; } - string rewardText = $"‖color:gui.orange‖{string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:N0}", GetReward(sub))}‖end‖"; + string rewardText = $"‖color:gui.orange‖{string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:N0}", GetReward(currentSub))}‖end‖"; if (descriptionWithoutReward != null) { description = descriptionWithoutReward.Replace("[reward]", rewardText); } } @@ -167,18 +209,26 @@ namespace Barotrauma } } } - - if (sub != this.sub || missionsChanged) + + var pendingSubInfo = GameMain.GameSession?.Campaign?.PendingSubmarineSwitch; + if (pendingSubInfo != null && nextRoundSubInfo != pendingSubInfo) { - this.sub = sub; + this.nextRoundSubInfo = pendingSubInfo; DetermineCargo(); } + else if (sub != this.currentSub || missionsChanged) + { + this.currentSub = sub; + this.nextRoundSubInfo = sub.Info; + DetermineCargo(); + } + return calculatedReward; } private void InitItems() { - this.sub = Submarine.MainSub; + this.currentSub = Submarine.MainSub; DetermineCargo(); items.Clear(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEvent.cs index 8054a79ac..cbb841a31 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEvent.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index ea2e4ed68..9edca9159 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -507,6 +507,8 @@ namespace Barotrauma } } + public TransitionType GetAvailableTransition() => GetAvailableTransition(out _, out _); + /// /// Which submarine is at a position where it can leave the level and enter another one (if any). /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs index fe1f4fad2..68bfe6969 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs @@ -622,8 +622,6 @@ namespace Barotrauma return; } - var originalSubPos = Submarine.WorldPosition; - if (level.StartOutpost != null) { //start by placing the sub below the outpost @@ -706,7 +704,7 @@ namespace Barotrauma if (!ls.LoadSub || ls.Sub.DockedTo.Contains(Submarine)) { continue; } if (Submarine.Info.LeftBehindDockingPortIDs.Contains(ls.OriginalLinkedToID)) { continue; } if (ls.Sub.Info.SubmarineElement.Attribute("location") != null) { continue; } - ls.Sub.SetPosition(ls.Sub.WorldPosition + (Submarine.WorldPosition - originalSubPos)); + ls.SetPositionRelativeToMainSub(); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs index 58050a7ab..2b0e7db1d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs @@ -30,7 +30,7 @@ namespace Barotrauma.Items.Components class SlotRestrictions { public readonly int MaxStackSize; - public readonly List ContainableItems; + public List ContainableItems; public SlotRestrictions(int maxStackSize, List containableItems) { @@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components [Serialize(false, IsPropertySaveable.No)] public bool RemoveContainedItemsOnDeconstruct { get; set; } - private ImmutableArray slotRestrictions; + private readonly ImmutableArray slotRestrictions; readonly List targets = new List(); @@ -215,21 +215,13 @@ namespace Barotrauma.Items.Components public override bool RecreateGUIOnResolutionChange => true; - public List ContainableItems { get; private set; } + public List ContainableItems { get; } public ItemContainer(Item item, ContentXElement element) : base(item, element) - { - LoadContainableRestrictions(element); - InitProjSpecific(element); - } - - public void LoadContainableRestrictions(ContentXElement element) { int totalCapacity = capacity; - ContainableItems?.Clear(); - foreach (var subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -250,7 +242,7 @@ namespace Barotrauma.Items.Components } } Inventory = new ItemInventory(item, this, totalCapacity, SlotsPerRow); - + List newSlotRestrictions = new List(totalCapacity); for (int i = 0; i < capacity; i++) { @@ -261,7 +253,7 @@ namespace Barotrauma.Items.Components foreach (var subElement in element.Elements()) { if (subElement.Name.ToString().ToLowerInvariant() != "subcontainer") { continue; } - + int subCapacity = subElement.GetAttributeInt("capacity", 1); int subMaxStackSize = subElement.GetAttributeInt("maxstacksize", maxStackSize); @@ -289,6 +281,28 @@ namespace Barotrauma.Items.Components capacity = totalCapacity; slotRestrictions = newSlotRestrictions.ToImmutableArray(); System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length); + InitProjSpecific(element); + } + + public void ReloadContainableRestrictions(ContentXElement element) + { + int containableIndex = 0; + foreach (var subElement in element.GetChildElements("containable")) + { + RelatedItem containable = RelatedItem.Load(subElement, returnEmpty: false, parentDebugName: item.Name); + if (containable == null) + { + DebugConsole.ThrowError("Error when loading containable restrictions for \"" + item.Name + "\" - containable with no identifiers."); + continue; + } + ContainableItems[containableIndex] = containable; + containableIndex++; + if (containableIndex >= ContainableItems.Count) { break; } + } + for (int i = 0; i < capacity; i++) + { + slotRestrictions[i].ContainableItems = ContainableItems; + } } public int GetMaxStackSize(int slotIndex) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs index b72ea07b8..7ca7eff7d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs @@ -846,6 +846,10 @@ namespace Barotrauma.Items.Components } else if (target.Body.UserData is Limb limb) { + if (!FriendlyFire && User != null && limb.character.IsFriendly(User)) + { + return false; + } // when hitting limbs with piercing ammo, don't lose as much speed if (MaxTargetsToHit > 1) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs index ba2e0b3d3..2a961dcd8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs @@ -460,13 +460,14 @@ namespace Barotrauma.MapCreatures.Behavior { if (parentBranchId > -1) { - if (parentBranchId < Branches.Count) + var parentBranch = Branches.Find(b => b.ID == parentBranchId); + if (parentBranch == null) { - branch.ParentBranch = Branches[parentBranchId]; + DebugConsole.AddWarning($"Error while loading ballast flora: couldn't find a parent branch with the ID {parentBranchId}"); } else { - DebugConsole.AddWarning($"Error while loading ballast flora: parent branch ID {parentBranchId} out of range (total {Branches.Count} branches)"); + branch.ParentBranch = parentBranch; } } } @@ -790,7 +791,8 @@ namespace Barotrauma.MapCreatures.Behavior MaxHealth = RootHealth, Health = RootHealth, IsRoot = true, - CurrentHull = Parent + CurrentHull = Parent, + ID = CreateID() }; Branches.Add(root); @@ -1015,14 +1017,6 @@ namespace Barotrauma.MapCreatures.Behavior public void DamageBranch(BallastFloraBranch branch, float amount, AttackType type, Character? attacker = null) { float damage = amount; - if (damage > 0) - { - damage = Math.Min(damage, branch.Health); - } - else - { - damage = Math.Max(damage, branch.Health - branch.MaxHealth); - } if (type != AttackType.Other && type != AttackType.CutFromRoot) { @@ -1081,6 +1075,14 @@ namespace Barotrauma.MapCreatures.Behavior } } + if (damage > 0) + { + damage = Math.Min(damage, branch.Health); + } + else + { + damage = Math.Max(damage, branch.Health - branch.MaxHealth); + } branch.Health -= damage; #if SERVER diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index 5bdabf7cf..da8d88b14 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -1,12 +1,11 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Xml.Linq; -using Barotrauma.IO; -using Barotrauma.Extensions; -using System.Collections.Immutable; namespace Barotrauma { @@ -82,6 +81,8 @@ namespace Barotrauma private XElement saveElement; + private Vector2? positionRelativeToMainSub; + public override bool Linkable { get @@ -256,6 +257,15 @@ namespace Barotrauma } } + public void SetPositionRelativeToMainSub() + { + if (positionRelativeToMainSub.HasValue) + { + Sub.SetPosition(Submarine.WorldPosition + positionRelativeToMainSub.Value); + } + positionRelativeToMainSub = null; + } + public override void OnMapLoaded() { if (!loadSub) { return; } @@ -317,7 +327,19 @@ namespace Barotrauma { if (worldPos == Vector2.Zero) { - DebugConsole.ThrowError("Something went wrong when loading a linked submarine - the save didn't include either a world position or a linked port for the submarine."); + Vector2 relativePos = saveElement.GetAttributeVector2("posrelativetomainsub", Vector2.Zero); + if (relativePos != Vector2.Zero) + { + positionRelativeToMainSub = relativePos; + } + else + { + DebugConsole.ThrowError("Something went wrong when loading a linked submarine - the save didn't include a world position, a linked port or position relative to the main sub."); + } + } + else + { + sub.Submarine = Submarine; } return; } @@ -469,8 +491,9 @@ namespace Barotrauma } else { - if (saveElement.Attribute("location") != null) saveElement.Attribute("location").Remove(); - if (saveElement.Attribute("worldpos") != null) saveElement.Attribute("worldpos").Remove(); + if (saveElement.Attribute("location") != null) { saveElement.Attribute("location").Remove(); } + if (saveElement.Attribute("worldpos") != null) { saveElement.Attribute("worldpos").Remove(); } + saveElement.SetAttributeValue("posrelativetomainsub", XMLExtensions.Vector2ToString(sub.WorldPosition - Submarine.WorldPosition)); } saveElement.SetAttributeValue("pos", XMLExtensions.Vector2ToString(Position - Submarine.HiddenSubPosition)); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index eaedf8556..36743762a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -79,7 +79,6 @@ namespace Barotrauma public override void Deselect() { base.Deselect(); - #if CLIENT var config = GameSettings.CurrentConfig; config.CrewMenuOpen = CrewManager.PreferCrewMenuOpen; @@ -88,6 +87,10 @@ namespace Barotrauma GameSettings.SaveCurrentConfig(); GameMain.SoundManager.SetCategoryMuffle("default", false); GUI.ClearMessages(); + if (GameMain.GameSession?.GameMode is TestGameMode) + { + DebugConsole.DeactivateCheats(); + } #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs index 9e3417054..0cae07ba2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs @@ -1128,7 +1128,7 @@ namespace Barotrauma if (itemComponent is ItemContainer itemContainer && (componentElement.GetChildElement("containable") != null || componentElement.GetChildElement("subcontainer") != null)) { - itemContainer.LoadContainableRestrictions(componentElement); + itemContainer.ReloadContainableRestrictions(componentElement); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs index c95171170..c21422874 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs @@ -492,7 +492,11 @@ namespace Barotrauma #if CLIENT if (setGraphicsMode) { - GameMain.Instance.ApplyGraphicsSettings(); + GameMain.Instance.ApplyGraphicsSettings(recalculateFontsAndStyles: true); + } + else if (textScaleChanged) + { + GUIStyle.RecalculateFonts(); } if (audioOutputChanged) @@ -505,17 +509,6 @@ namespace Barotrauma VoipCapture.ChangeCaptureDevice(currentConfig.Audio.VoiceCaptureDevice); } - if (textScaleChanged || resolutionChanged) - { - foreach (var font in GUIStyle.Fonts.Values) - { - font.Prefabs.ForEach(p => p.LoadFont()); - } - foreach (var componentStyle in GUIStyle.ComponentStyles) - { - componentStyle.RefreshSize(); - } - } if (hudScaleChanged) { HUDLayoutSettings.CreateAreas(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/TaskPool.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/TaskPool.cs index 921725254..f2b0fceb6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/TaskPool.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/TaskPool.cs @@ -40,10 +40,14 @@ namespace Barotrauma } } - private static void AddInternal(string name, Task task, Action onCompletion, object userdata) + private static void AddInternal(string name, Task task, Action onCompletion, object userdata, bool addIfFound = true) { lock (taskActions) { + if (!addIfFound) + { + if (taskActions.Any(t => t.Name == name)) { return; } + } if (taskActions.Count >= MaxTasks) { throw new Exception( @@ -59,6 +63,10 @@ namespace Barotrauma { AddInternal(name, task, (Task t, object obj) => { onCompletion?.Invoke(t); }, null); } + public static void AddIfNotFound(string name, Task task, Action onCompletion) + { + AddInternal(name, task, (Task t, object obj) => { onCompletion?.Invoke(t); }, null, addIfFound: false); + } public static void Add(string name, Task task, U userdata, Action onCompletion) where U : class { diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 0a155659b..58186d997 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,241 +1,25 @@ --------------------------------------------------------------------------------------------------------- -v0.18.7.0 +v0.18.9.0 --------------------------------------------------------------------------------------------------------- -Unstable only: -- Reduced depth charge scale to fit in loader/racks better. -- Fixed ballast flora dying by itself client-side when transitioning to a new level. -- Disallow laying in vertically flipped normal bunks. -- Fixed broken door sprite stretching on the wrong axis when cutting a door. -- Fixed AI orders not working in multiplayer. -- Fixed tutorial characters starting with more items than they should. -- Fixed chat box closing when clicking any chat box elements after opening it with the keybind. -- Fixed submarine selection resetting when changing server settings in the campaign setup menu. -- Fixed "enable" and "disable" being wrong way around in the mod tab's context menus. -- Fixed sub editor always saving subs from a local mod in the root of that mod's folder instead of the actual location of that sub file. -- Fixed decoys not being containable in wrecked coilgun ammo shelves. -- Fixes and improvements to the new beacon stations and the enemies inside them. -- Fixed an issue during submarine switching when a drone / linked sub has been left behind (Regalis11/Barotrauma#9172): When you were switching back to a submarine whose drone you'd left behind, in the same level where you left the drone, the drone would get loaded and resaved during the item transfer, which caused it to no longer be considered "left behind". It also removed the drone's position from the save, and since it was not docked to anything either, positioning it failed at the beginning of the next round. - -Changes: -- Adding preview images to wrecks, beacon stations, outposts or enemy subs isn't allowed in the sub editor (unnecessarily bloats up their file size, as the preview images aren't visible anywhere). - -Fixes: -- Fixed server not refreshing the power grid when a client disconnects and reconnects a power wire. -- Fixed hull updates not being sent if the water/oxygen/fire in the hull doesn't change server-side, preventing the hull's status from getting corrected if a client somehow ends up out of sync. -- Fixed keybinds shown in the controls tab not refreshing when resetting the binds. -- Hopefully fixed colonies sometimes not including some modules (most often the armory module). -- Fixed ready checks sometimes ending at a slightly different time client-side compared to the server, allowing you to answer the prompt even though the time to answer already ended server-side. -- Fixed large terminal welcome messages going slightly outside the bounds of the listbox. -- Fixed overlapping in the tab menu's mission tab when there's more than one mission selected. -- Fixed fabricators and deconstructors playing the sounds even if they're out of power. -- Fixed occasional "hash mismatch for downloaded mod" errors on Linux. -- Fixed clients occasionally spawning as the old character after they've opted to create a new one. Only happened if the client hadn't died and was still controlling the old character at the end of the round. -- When a client creates a character with a new name, the client's name is changed to match it after they spawn as that character. -- Fixed enabled mods getting disabled when updating them in the mods menu. -- Fixed a rounding error in Sprite.DrawTiled that sometimes caused an extra 1-pixel line on some scaled and flipped structures (e.g. certain wall pieces scaled to 0.6). -- Fixed Orca 2 still using the old chaingun charge time. +- Updated translations. +- Fixed crashing when a mod includes event sets that reference a non-existent event. +- Backwards compatibility: readded some mission events we'd removed since the previous update. --------------------------------------------------------------------------------------------------------- -v0.18.6.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed crashing during outpost generation. - ---------------------------------------------------------------------------------------------------------- -v0.18.5.0 ---------------------------------------------------------------------------------------------------------- - -Chat improvements: -- Chat mode (radio/local) can be toggled using a dropdown next to the chat box or with a dedicated "ToggleChatMode" keybind (R by default). -- Voice chat now has only one push-to-talk keybind (V by default) which respects the selected chat mode. -- There's now a dedicated "ActiveChat" keybind (T by default) to open the chat using the currently active chat mode. -- If you want to keep the chat keybinds the way they were (separate keybinds for local and radio), you can rebind the "Chat" and "RadioChat" inputs back to T and R and the new "ToggleChatMode" and "ActiveChat" inputs to something else. - -Changes: -- Optimized bot AIs: in particular, the cleanup, repair, pump water and load items objectives. Should significantly improve performance when the bots are doing these objectives when there's a large number of items in the sub. -- Optimized entity culling logic (determines which items/structures are currently visible in the screen). -- Optimized a bunch of textures. -- Improved the performance statistics view that's enabled with the "showperf" console command: more fine-grained stats and easier-to-read visuals. -- Added UI volume slider. -- Depth charges can be stored in coilgun ammo shelves. - -Fixes: -- Fixed ballast flora branches that have been disconnected from the root not being considered disconnected after a level transition (allowing them to keep growing). -- Fixed "set default bindings" not doing anything in the settings menu. -- Fixed door/hatch gaps not getting moved when snapping to grid in the sub editor. -- Vertically mirrored beds can't be laid on. -- Fixed wrecked reactors being forced to non-interactable even if made interactable in the sub editor. - -Unstable only: -- Fixed crashing when you try to edit beacon station settings on a station you haven't saved yet. -- Fixed level difficulties being incorrect in the "normal" difficulty setting (levels were set to the minimum difficulty of the biome, instead of a linear increase across the biome). -- Misc fixes and improvements to the new beacon stations. -- Fixed "max missions per round" value not being restricted in the UI. -- Fixed items not getting transferred to/from linked subs. - -Modding: -- Doors and hatches can now be mirrored in the sub editor (making them open from top to bottom, or from right to left). - ---------------------------------------------------------------------------------------------------------- -v0.18.4.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Option to select whether to automatically transfer the items from the old sub to a new one when switching the sub. -- Fixed Physicorium Chaingun Ammunition Box having an incorrect sprite. -- Fixed crashing when trying to load a save that includes ItemContainers with different kinds of inventory slots (e.g. PUCS). -- Disposable suits no longer protect from pressure when broken. -- Made disposable suits play a sound and their lights flicker when the suit is about to break. -- Fixed inability to access the character tab when your character is dead in non-campaign modes, fixed creating a new character not doing anything mid-round. -- Fixed sprite editor crashing if you try to reload a texture twice. -- Fixed drone/shuttles getting left behind in the outpost when you buy and switch to a sub that has a one. -- Fixed crashing when closing the submarine preview window. -- Disallowed mirroring beds vertically. - -Changes: -- Added some new campaign settings: starting balance, amount of starting items and difficulty. -- Added two new beacon stations. -- Made the descriptions of some materials (that used to just say "useful for crafting") more descriptive. -- Increased oxygen generator output in some vanilla subs. -- Made handheld sonar beacon sound less grating. -- The client who initiated a vote cannot take part in that vote (except if they're the only client who can vote, in which case the vote automatically passes). -- Made flashlight flicker before the battery runs out. -- Added some lootable money to corpses found in wrecks. -- Removed the small equipment indicators next to the character portrait. -- Added a bunch of new UI sounds (tickbox toggling, confirming transactions, increase/decrease sounds for number inputs, cart sound for adding/removing items in store interfaces, selecting/clicking components, sliders and modlist). -- Optimized many status effects by making them only execute once per second instead of every frame (most importantly, diving suits and volatile fuel rods). -- Optimized talents: buffs are applied to characters periodically instead of every frame. -- Optimized the logic that bots use to determine the safety of hulls. -- Optimized items: stop updating items that don't need to be updated more aggressively. -- Weapon holders now use the tag "mountableweapon" instead of "weapon" to determine which items can be placed in them. Allows tagging non-weapon items as mountable in the holder, without making bots consider it a weapon due to the "weapon" tag. Also allows to keep some weapons not-mountable. -- Ammunition Shelf can now also store Depth Charges ("depthchargeammo" tag added) - -Fixes: -- Split campaign state networking messages into multiple ones. Previously all the campaign-related data (map state, reputation, upgrades, purchased items, selected missions) was included in the same message, and whenever anything in the data changed, the server would send all of it to clients. This would cause performance and bandwidth issues in some situations, for example when reputation was changing rapidly. -- Fixed some pumps in Kastrull working without power. -- Fixed quick-reloading working incorrectly when trying to reload from a stack that doesn't fully fit in the weapon (e.g. when double clicking on a full stack of revolver rounds with a half-loaded revolver in hand). -- Fixed inability to quick-reload weapons with more than 1 inventory slot (e.g. autoshotgun). -- Fixed outpost NPCs having x3 more health than they should. -- Fixed morbusine not killing NPCs with higher-than-default health. -- Fixed crashing with the error message "couldn't find a valid ICU package installed on the system" on some Linux distributions. -- Fixed graphics errors when using Razer Cortex overlay. -- Fixed bots being unable to repair Winterhalter's top hatch. -- Fixed server crashing if you disable all mission types and try to start a mission round. -- Fixed Chinese/Japanese/Korean text not wrapping properly on terminals. -- Fixed bots sometimes walking towards a wall or holding the ladders when they are idling. -- Fixed "main docking port" property not being taken into account when placing outposts (= the outpost was placed with the assumption that the docking port closest to the sub's center is the main docking port). Sometimes caused the outpost to be placed too close to the level walls, preventing the sub from docking with it. -- Fixed ladders not being visible in the sub preview. -- Fixed some UI elements being too large when switching from a large resolution to a smaller one, or vice versa. -- Fixed weapon holder sprite depth. -- Fixed level editor's test mode generating a different level than the editor itself. - -Modding: -- Added "mod lists" which can be used to enable/disable sets of mods more easily. -- Option to choose which local mod(s) to add a submarine to when saving one in the submarine editor. -- Mods can be unsubscribed from by right-clicking on them in the mod list, and it's possible to unsubscribe from multiple ones at the same time by using ctrl+click or shift+click to select more than one. -- Local mods can be merged in the mod list by selecting the ones you want to merge and selecting "merge all selected" from the right-click context menu. -- Better filtering in the mod list: option to only show local mods, Workshop mods, published mods, submarines and/or item assemblies. -- Added "SameInventory" spawn position type to status effects (allows spawning items in the same inventory the entity applying the effect is in). -- Added support for multiple light components in wearables. - ---------------------------------------------------------------------------------------------------------- -v0.18.3.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed submarine not getting saved between levels in the multiplayer campaign. -- Fixed clients sometimes unnecessarily showing the "trying to automatically dock with the outpost" prompt even when the docking is being done manually. -- Added a new texture and icon for shotgun rubber shell. -- Added sprite for disposable suit on shelf. - -Changes: -- TriggerComponent now supports negative forces: negative force value will cause the it to pull triggerers towards it. - -Modding: -- Multiple TriggerComponent properties can now be modified through signals and CustomInterface components. - ---------------------------------------------------------------------------------------------------------- -v0.18.2.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed "submarine equality check failed" errors in non-campaign multiplayer game modes. -- Fixed occasional crashes when exiting the sub editor. -- Fixed diving suit lights being on when not worn. -- Fixed research stations not working. -- Adjusted the layout of server settings gameplay tab to prevent overlaps on small resolutions. -- Fixed ignore orders not being loaded correctly in singleplayer. - -Changes: -- Lighting optimization: now some unimportant (dim and small) lights are hidden when there's lots of light sources visible on the screen at the same time. The maximum number of visible lights can be adjusted in the game settings. -- Lighting optimization: the number of light recalculations per frame is limited, meaning that when there's lots of moving, shadow-casting lights visible, the game doesn't try to recalculate the shadows all at the same time. -- Lighting optimization: simplify the light rendering when zoomed very far out (e.g. when looking through a periscope). -- Optimized status effects that modify items' conditions every frame (for example, oxygen tank shelves that fill up oxygen tanks). -- Hide AppData path from tooltips in the sub editor to prevent exposing the user's name. -- Reduce nausea chance of energy drink to 25%. -- Changes to the campaign progression in general. -- Changes to the level generation parameters, especially in Cold Caverns and the Ridge. -- Changes to the level resources distribution. -- Changes to the event manager settings (that affect the monster spawns). -- Adjusted and normalized the item loadouts for all the jobs. -- Changes to the items that always spawn with the sub at the beginning of the game (start items). -- Adjustments to the preferred containers (= where things are spawned and where they should be placed). -- Changes to the existing missions and how they are distributed. Added new missions. -- Reduced the costs for unlocking the biomes. -- Minor adjustments to the monster spawns. -- Changes to the item "gating". Some items don't appear early in the game anymore. -- Adjustments to the mission specific variants of the monsters. -- Added a large Crawler variant for some missions (removed the Swarmcrawler that was used for crawler missions). -- Halved Mudraptors' priority for eating dead bodies. - -Fixes: -- Fixed abyss area being very small in the Aphotic Plateau, preventing the abyss monster from reaching you if you go deep enough. -- Fixed status monitor displaying small amounts of water as 1% even though water detectors output 0%. -- Fixed autopilot conflicting with VELOCITY_IN inputs (now signals override the autopilot for 1 second). -- Fixed ConversationAction getting interrupted when opening an input-blocking menu in single player. -- Fixed sprite bleed in chaingun ammunition boxes. -- Fixed appearance of specific named NPCs being inconsistent (e.g. Captain Hognose sometimes being a woman or not having an eyepatch). -- Fixed certain scripted events getting stuck if you switch characters in single player (e.g. the events that require you to interact with fliers on the wall). -- Fixed crashing when the source of a rope is removed (e.g. when a latcher despawns while latched on to the sub). -- Fixed votes always going through if no-one votes. -- Fixed energy drink giving x10 more haste when used via the health interface. -- Fixed the monster spawns for the new game plus not working (currently a placeholder set). -- Fixed monsters spawning from missions not avoiding the engines. - -Modding: -- Level object, cave and mineral commonness can be defined based on the biome instead of the level generation parameters (= no need to define commonness for "coldcavernsbasic", "coldcavernsmaze" etc separately). -- Option to define ConversationAction texts directly in the event xml (instead of having to always define them in a spearate text file). -- Extended CustomInterface functionality with NumberInput elements that allow using float values ("numbertype") and defining the increment size ("step") the number of decimal places ("decimalplaces"). (Thanks, mLuby!) -- Implemented element for removing all the child elements of an element in a variant file. - ---------------------------------------------------------------------------------------------------------- -v0.18.1.0 ---------------------------------------------------------------------------------------------------------- - -Unstable only: -- Fixed crashing when someone respawns while the tab menu is open. -- Fixed level equality errors in multiplayer game modes other than the campaign. -- Fixed headsets from pre-0.18 saves being unusable due to still having the battery requirement but no inventory to hold one. -- Fixed inability to put disposable diving suits in diving suit lockers. -- Fixed clients without money management permissions not being able to request money. -- Fixed context menus rendering behind the debug console. - ---------------------------------------------------------------------------------------------------------- -v0.18.0.0 +v0.18.8.0 --------------------------------------------------------------------------------------------------------- Balancing: +- Added some new campaign settings: starting balance, amount of starting items and difficulty. - Cargo mission reward of construction materials has been reduced to be less balance-breaking. -- Many fabrication and deconstruction recipes changed to prevent infinite construction loops. +- Revisited all item spawns. Drastically reduced and adjusted the spawns everywhere. Disabled some spawns in campaign. All the subs should now start with a bare minimum in the campaign. - Reduced selling price to ~25% of base price to avoid getting too rich from looting too early/easily - Increased effect of "Requested Goods" to be 2x to compensate for the decreased selling price. - Alien artifacts and trinkets can still be sold for a high price at research stations. (2x modifier, to compensate for the reduced selling price) - Removed batteries from Headset, to reduce the value of selling/deconstructing these. - Duffelbag deteriorates over time when in use, and now is carried with both hands. - All items now deconstruct into less materials than it takes to construct them. Avoiding infinite construction/deconstruction loops for easy skill leveling. -- Revisited all item spawns (WIP). Drastically reduced and adjusted the spawns everywhere. Disabled some spawns in campaign. All the subs should now start with a bare minimum in the campaign. - (Temporarily?) Removed most hand-placed items from the vanilla subs to make balancing and debugging the auto item placement easier. - Revisited crew corpse spawns. The id cards are no longer manually placed. The cards found from the crew now actually work. - Minor adjustments to bandit loadouts. @@ -244,15 +28,34 @@ Balancing: - Adjusted the armor penetration of all turrets. - Made location evolution take a little longer, colonies cannot be formed closer than three steps to another colony. - Made wreck missions a little more common. +- Adjustments to the preferred containers (= where things are spawned and where they should be placed). +- Changes to the existing missions and how they are distributed. Added new missions. +- Reduced the costs for unlocking the biomes. +- Adjustments to the monster spawns. +- Changes to the item "gating". Some items don't appear early in the game anymore. +- Adjustments to the mission specific variants of the monsters. +- Added a large Crawler variant for some missions (removed the Swarmcrawler that was used for crawler missions). +- Halved Mudraptors' priority for eating dead bodies. +- Reduce nausea chance of energy drink to 25%. +- Changes to the campaign progression in general. +- Changes to the level generation parameters, especially in Cold Caverns and the Ridge. +- Changes to the level resources distribution. +- Changes to the event manager settings (that affect the monster spawns). +- Adjusted and normalized the item loadouts for all the jobs. + +Chat improvements: +- Chat mode (radio/local) can be toggled using a dropdown next to the chat box or with a dedicated "ToggleChatMode" keybind (R by default). +- Voice chat now has only one push-to-talk keybind (V by default) which respects the selected chat mode. +- There's now a dedicated "ActiveChat" keybind (T by default) to open the chat using the currently active chat mode. +- If you want to keep the chat keybinds the way they were (separate keybinds for local and radio), you can rebind the "Chat" and "RadioChat" inputs back to T and R and the new "ToggleChatMode" and "ActiveChat" inputs to something else. Changes and additions: - Added damage overlays to characters (characters who've taken damage look damaged). +- Added two new beacon stations. +- Added a bunch of new UI sounds (tickbox toggling, confirming transactions, increase/decrease sounds for number inputs, cart sound for adding/removing items in store interfaces, selecting/clicking components, sliders and modlist). +- Added UI volume slider. - Show a verification prompt if an automated circuit tries to make the submarine undock from or dock with an outpost. Prevents campaign getting softlocked if someone rewires the docking port in a way that makes it dock/undock immediately at the start of around. - Color subs in the sub editor's list to indicate whether they're vanilla, workshop or local subs, added a tooltip that explains why some of them cannot be deleted through the editor. -- Optimized AI pathfinding when they're trying to find a safe hull. Particularly noticeable in colonies when the NPCs are fleeing from something. -- Optimized character status effects (e.g. health regen and other constant damage reductions). -- Optimized watcher's acid clouds. -- Optimized loading submarines. Reduces loading times especially when there's lots of items in the sub. - ID cards can now be purchased from outposts. The card gets assigned the appropriate tags for the character doing the purchase. - Clients need to wait 1 minute if their vote gets rejected before they can start another vote of the same type. - Increased the priority of explosion particles to make it less likely for them to not appear when the particle limit has been reached. @@ -270,10 +73,41 @@ Changes and additions: - Prevented selling items from submarine containers tagged with "dontsellitems", instead of "donttakeitems". - Removed merchant balance effect on item prices. - Replaced "item sell value" with the location reputation effect on the store interface. +- Hide AppData path from tooltips in the sub editor to prevent exposing the user's name. +- Made the descriptions of some materials (that used to just say "useful for crafting") more descriptive. +- Increased oxygen generator output in some vanilla subs. +- Made handheld sonar beacon sound less grating. +- The client who initiated a vote cannot take part in that vote (except if they're the only client who can vote, in which case the vote automatically passes). +- Made flashlight flicker before the battery runs out. +- Added some lootable money to corpses found in wrecks. +- Removed the small equipment indicators next to the character portrait. +- Weapon holders now use the tag "mountableweapon" instead of "weapon" to determine which items can be placed in them. Allows tagging non-weapon items as mountable in the holder, without making bots consider it a weapon due to the "weapon" tag. Also allows to keep some weapons not-mountable. +- Ammunition Shelf can now also store Depth Charges ("depthchargeammo" tag added) +- Doors and hatches can now be mirrored in the sub editor (making them open from top to bottom, or from right to left). +- Depth charges can be stored in coilgun ammo shelves. +- Adding preview images to wrecks, beacon stations, outposts or enemy subs isn't allowed in the sub editor (unnecessarily bloats up their file size, as the preview images aren't visible anywhere). + +Performance: +- Improved the performance statistics view that's enabled with the "showperf" console command: more fine-grained stats and easier-to-read visuals. +- Optimized AI pathfinding when they're trying to find a safe hull. Particularly noticeable in colonies when the NPCs are fleeing from something. +- Optimized character status effects (e.g. health regen and other constant damage reductions). +- Optimized watcher's acid clouds. +- Optimized loading submarines. Reduces loading times especially when there's lots of items in the sub. +- Lighting optimization: now some unimportant (dim and small) lights are hidden when there's lots of light sources visible on the screen at the same time. The maximum number of visible lights can be adjusted in the game settings. +- Lighting optimization: the number of light recalculations per frame is limited, meaning that when there's lots of moving, shadow-casting lights visible, the game doesn't try to recalculate the shadows all at the same time. +- Lighting optimization: simplify the light rendering when zoomed very far out (e.g. when looking through a periscope). +- Optimized status effects that modify items' conditions every frame (for example, oxygen tank shelves that fill up oxygen tanks). +- Optimized many status effects by making them only execute once per second instead of every frame (most importantly, diving suits and volatile fuel rods). +- Optimized talents: buffs are applied to characters periodically instead of every frame. +- Optimized the logic that bots use to determine the safety of hulls. +- Optimized items: stop updating items that don't need to be updated more aggressively. +- Optimized bot AIs: in particular, the cleanup, repair, pump water and load items objectives. Should significantly improve performance when the bots are doing these objectives when there's a large number of items in the sub. +- Optimized entity culling logic (determines which items/structures are currently visible in the screen). +- Optimized a bunch of textures. Fixes: -- Fixed an issue where the client was adding mission rewards into the bank on their screen causing desync. -- Fixed item sets failing to load when the system language is set to Turkish, causing NPCs to spawn without any items. +- Fixed server not refreshing the power grid when a client disconnects and reconnects a power wire. +- Fixed hull updates not being sent if the water/oxygen/fire in the hull doesn't change server-side, preventing the hull's status from getting corrected if a client somehow ends up out of sync. - Fixed ballast flora sometimes becoming unkillable in multiplayer. - Attempt to fix tab menu crew list sometimes getting stuck to a broken state at the beginning of a round. - Fixed inability to access the character tab in the tab menu when dead (preventing you from creating a new character). @@ -287,6 +121,7 @@ Fixes: - Fixed level floor not being visible on the sonar. - Fixed bots being unable to shoot with a turret whose line of sight is blocked by another turret (even though the projectiles can go through the turret). - Fixed switching a sub making its preview image disappear from the submarine switch menu. +- Fixed an issue where the client was adding mission rewards into the bank on their screen causing desync. - Fixed item assemblies still getting misaligned when saving. - Fixed crashing when there's no audio device available (no speakers/headset connected) and a character enters water. - Fixed crashing when trying to save an item assembly with a space at the end of the name. @@ -299,12 +134,72 @@ Fixes: - Signal components' and terminals' sprites don't mirror horizontally in mirrored subs (what's a DNA, RO, ROX or XEGER component??). - Fixed inability to rewire any docking ports in outpost levels, even if the port is not docked with anything (should only apply to the port docked with the outpost). - Fixed "Ignore This" orders being wiped when loading an existing multiplayer campaign save. +- Fixed abyss area being very small in the Aphotic Plateau, preventing the abyss monster from reaching you if you go deep enough. +- Fixed status monitor displaying small amounts of water as 1% even though water detectors output 0%. +- Fixed autopilot conflicting with VELOCITY_IN inputs (now signals override the autopilot for 1 second). +- Fixed ConversationAction getting interrupted when opening an input-blocking menu in single player. +- Fixed sprite bleed in chaingun ammunition boxes. +- Fixed appearance of specific named NPCs being inconsistent (e.g. Captain Hognose sometimes being a woman or not having an eyepatch). +- Fixed certain scripted events getting stuck if you switch characters in single player (e.g. the events that require you to interact with fliers on the wall). +- Fixed crashing when the source of a rope is removed (e.g. when a latcher despawns while latched on to the sub). +- Fixed votes always going through if no-one votes. +- Fixed energy drink giving x10 more haste when used via the health interface. +- Fixed the monster spawns for the new game plus not working (currently a placeholder set). +- Fixed monsters spawning from missions not avoiding the engines. +- Split campaign state networking messages into multiple ones. Previously all the campaign-related data (map state, reputation, upgrades, purchased items, selected missions) was included in the same message, and whenever anything in the data changed, the server would send all of it to clients. This would cause performance and bandwidth issues in some situations, for example when reputation was changing rapidly. +- Fixed some pumps in Kastrull working without power. +- Fixed quick-reloading working incorrectly when trying to reload from a stack that doesn't fully fit in the weapon (e.g. when double clicking on a full stack of revolver rounds with a half-loaded revolver in hand). +- Fixed inability to quick-reload weapons with more than 1 inventory slot (e.g. autoshotgun). +- Fixed outpost NPCs having x3 more health than they should. +- Fixed morbusine not killing NPCs with higher-than-default health. +- Fixed crashing with the error message "couldn't find a valid ICU package installed on the system" on some Linux distributions. +- Fixed graphics errors when using Razer Cortex overlay. +- Fixed bots being unable to repair Winterhalter's top hatch. +- Fixed server crashing if you disable all mission types and try to start a mission round. +- Fixed Chinese/Japanese/Korean text not wrapping properly on terminals. +- Fixed bots sometimes walking towards a wall or holding the ladders when they are idling. +- Fixed "main docking port" property not being taken into account when placing outposts (= the outpost was placed with the assumption that the docking port closest to the sub's center is the main docking port). Sometimes caused the outpost to be placed too close to the level walls, preventing the sub from docking with it. +- Fixed ladders not being visible in the sub preview. +- Fixed some UI elements being too large when switching from a large resolution to a smaller one, or vice versa. +- Fixed weapon holder sprite depth. +- Fixed level editor's test mode generating a different level than the editor itself. +- Fixed ballast flora branches that have been disconnected from the root not being considered disconnected after a level transition (allowing them to keep growing). +- Fixed "set default bindings" not doing anything in the settings menu. +- Fixed door/hatch gaps not getting moved when snapping to grid in the sub editor. +- Vertically mirrored beds can't be laid on. +- Fixed wrecked reactors being forced to non-interactable even if made interactable in the sub editor. +- Fixed keybinds shown in the controls tab not refreshing when resetting the binds. +- Hopefully fixed colonies sometimes not including some modules (most often the armory module). +- Fixed ready checks sometimes ending at a slightly different time client-side compared to the server, allowing you to answer the prompt even though the time to answer already ended server-side. +- Fixed large terminal welcome messages going slightly outside the bounds of the listbox. +- Fixed overlapping in the tab menu's mission tab when there's more than one mission selected. +- Fixed fabricators and deconstructors playing the sounds even if they're out of power. +- Fixed occasional "hash mismatch for downloaded mod" errors on Linux. +- Fixed clients occasionally spawning as the old character after they've opted to create a new one. Only happened if the client hadn't died and was still controlling the old character at the end of the round. +- When a client creates a character with a new name, the client's name is changed to match it after they spawn as that character. +- Fixed enabled mods getting disabled when updating them in the mods menu. +- Fixed a rounding error in Sprite.DrawTiled that sometimes caused an extra 1-pixel line on some scaled and flipped structures (e.g. certain wall pieces scaled to 0.6). +- Fixed Orca 2 still using the old chaingun charge time. Modding: +- Added "mod lists" which can be used to enable/disable sets of mods more easily. +- Option to choose which local mod(s) to add a submarine to when saving one in the submarine editor. +- Mods can be unsubscribed from by right-clicking on them in the mod list, and it's possible to unsubscribe from multiple ones at the same time by using ctrl+click or shift+click to select more than one. +- Local mods can be merged in the mod list by selecting the ones you want to merge and selecting "merge all selected" from the right-click context menu. +- Better filtering in the mod list: option to only show local mods, Workshop mods, published mods, submarines and/or item assemblies. +- Added "SameInventory" spawn position type to status effects (allows spawning items in the same inventory the entity applying the effect is in). +- Added support for multiple light components in wearables. - Fixed permanent stats given by talents not getting synced to clients in multiplayer (doesn't affect any vanilla talents). - Fixed nullref exception when trying to trigger a location type change to a type that doesn't exist (doesn't happen in the vanilla game). - Added an extra tag to the "canned heat" talent to make it easier to add custom upgradeable tanks that aren't compatible with vanilla tools. - Option to make status effects drop the items contained inside the target item (usage example in the duffel bag). +- Level object, cave and mineral commonness can be defined based on the biome instead of the level generation parameters (= no need to define commonness for "coldcavernsbasic", "coldcavernsmaze" etc separately). +- Option to define ConversationAction texts directly in the event xml (instead of having to always define them in a spearate text file). +- Extended CustomInterface functionality with NumberInput elements that allow using float values ("numbertype") and defining the increment size ("step") the number of decimal places ("decimalplaces"). (Thanks, mLuby!) +- Implemented element for removing all the child elements of an element in a variant file. +- TriggerComponent now supports negative forces: negative force value will cause the it to pull triggerers towards it. +- Multiple TriggerComponent properties can now be modified through signals and CustomInterface components. + --------------------------------------------------------------------------------------------------------- v0.17.16.0