diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs index 63eb50462..47d184dd0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs @@ -202,7 +202,7 @@ namespace Barotrauma OnSelected = (tb) => transferItemsOnSwitch = tb.Selected }; transferItemsTickBox.RectTransform.Resize(new Point(Math.Min((int)transferItemsTickBox.ContentWidth, transferInfoFrame.Rect.Width), transferItemsTickBox.Rect.Height)); - itemTransferInfoBlock = new GUITextBlock(new RectTransform(Vector2.One, transferInfoFrame.RectTransform, Anchor.CenterRight), null) + itemTransferInfoBlock = new GUITextBlock(new RectTransform(Vector2.One, transferInfoFrame.RectTransform, Anchor.CenterRight), null, wrap: true) { TextAlignment = Alignment.CenterRight, Visible = false @@ -473,7 +473,10 @@ namespace Barotrauma subsToShow.Sort((x, y) => x.SubmarineClass.CompareTo(y.SubmarineClass)); } - if (transferService) SetConfirmButtonState(selectedSubmarine != null && selectedSubmarine.Name != CurrentOrPendingSubmarine().Name); + if (transferService) + { + SetConfirmButtonState(selectedSubmarine != null && selectedSubmarine.Name != CurrentOrPendingSubmarine().Name); + } subsToShow.Sort((x, y) => x.SubmarineClass.CompareTo(y.SubmarineClass)); pageCount = Math.Max(1, (int)Math.Ceiling(subsToShow.Count / (float)submarinesPerPage)); @@ -606,12 +609,6 @@ namespace Barotrauma UpdateItemTransferInfoFrame(); } - private bool ForceItemTransfer() - { - if (selectedSubmarine == null) { return false; } - return !selectedSubmarine.IsManuallyOutfitted && !GameMain.GameSession.IsSubmarineOwned(selectedSubmarine); - } - private bool IsSelectedSubCurrentSub => Submarine.MainSub?.Info?.Name == selectedSubmarine?.Name; private void UpdateItemTransferInfoFrame() @@ -625,13 +622,6 @@ namespace Barotrauma itemTransferInfoBlock.Visible = confirmButton.Enabled; itemTransferInfoBlock.Text = TextManager.Get("switchingbacktocurrentsub"); } - else if (ForceItemTransfer()) - { - TransferItemsOnSwitch = true; - transferItemsTickBox.Visible = false; - itemTransferInfoBlock.Visible = true; - itemTransferInfoBlock.Text = TransferItemsOnSwitch ? TextManager.Get("itemtransferenabledreminder") : TextManager.Get("itemtransferdisabledreminder"); - } else if (GameMain.GameSession?.Campaign?.PendingSubmarineSwitch?.Name == selectedSubmarine.Name) { transferItemsTickBox.Visible = false; @@ -730,6 +720,11 @@ namespace Barotrauma { return ShowConfirmationPopup(TextManager.Get("noitemsheader"), TextManager.Get("noitemswarning")); } + if (!GameMain.GameSession.IsSubmarineOwned(selectedSubmarine) && !selectedSubmarine.IsManuallyOutfitted) + { + var (header, body) = GetItemTransferWarningText(); + return ShowConfirmationPopup(header, body); + } if (selectedSubmarine.LowFuel) { return ShowConfirmationPopup(TextManager.Get("lowfuelheader"), TextManager.Get("lowfuelwarning")); @@ -771,6 +766,13 @@ namespace Barotrauma } } + private (LocalizedString header, LocalizedString body) GetItemTransferWarningText() + { + var header = TextManager.Get("itemtransferheader").Fallback("lowfuelheader"); + var body = TextManager.Get("itemtransferwarning").Fallback("lowfuelwarning"); + return (header, body); + } + private void ShowBuyPrompt(bool purchaseOnly) { if (!GameMain.GameSession.Campaign.CanAfford(selectedSubmarine.Price)) @@ -782,7 +784,6 @@ namespace Barotrauma } GUIMessageBox msgBox; - if (!purchaseOnly) { var text = TextManager.GetWithVariables("purchaseandswitchsubmarinetext", @@ -794,6 +795,39 @@ namespace Barotrauma msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), text, messageBoxOptions); msgBox.Buttons[0].OnClicked = (applyButton, obj) => + { + if (!TransferItemsOnSwitch && !IsSelectedSubCurrentSub) + { + if (selectedSubmarine.NoItems) + { + ShowConfirmationPopup(TextManager.Get("noitemsheader"), TextManager.Get("noitemswarning")); + return false; + } + if (!GameMain.GameSession.IsSubmarineOwned(selectedSubmarine) && !selectedSubmarine.IsManuallyOutfitted) + { + var (header, body) = GetItemTransferWarningText(); + ShowConfirmationPopup(header, body); + return false; + } + if (selectedSubmarine.LowFuel) + { + ShowConfirmationPopup(TextManager.Get("lowfuelheader"), TextManager.Get("lowfuelwarning")); + return false; + } + } + return Confirm(); + }; + + void ShowConfirmationPopup(LocalizedString header, LocalizedString textBody) + { + msgBox.Close(); + var extraConfirmationBox = new GUIMessageBox(header, textBody, new LocalizedString[2] { TextManager.Get("ok"), TextManager.Get("cancel") }); + extraConfirmationBox.Buttons[0].OnClicked = (b, o) => Confirm(); + extraConfirmationBox.Buttons[0].OnClicked += extraConfirmationBox.Close; + extraConfirmationBox.Buttons[1].OnClicked += extraConfirmationBox.Close; + } + + bool Confirm() { if (GameMain.Client == null) { @@ -806,7 +840,7 @@ namespace Barotrauma GameMain.Client.InitiateSubmarineChange(selectedSubmarine, TransferItemsOnSwitch, Networking.VoteType.PurchaseAndSwitchSub); } return true; - }; + } } else { @@ -842,10 +876,7 @@ namespace Barotrauma return $"\n\n{TextManager.Get("switchingbacktocurrentsub")}"; } var s = "\n\n" + TextManager.Get(TransferItemsOnSwitch ? "itemswillbetransferred" : "itemswontbetransferred"); - if (!ForceItemTransfer()) - { - s += $" {TextManager.Get("toggleitemtransferprompt")}"; - } + s += $" {TextManager.Get("toggleitemtransferprompt")}"; return s; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs index aeb6b6010..54d942d3b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs @@ -330,7 +330,8 @@ namespace Barotrauma { Submarine.MainSub.CheckFuel(); SubmarineInfo nextSub = PendingSubmarineSwitch ?? Submarine.MainSub.Info; - if (Level.IsLoadedFriendlyOutpost && nextSub.LowFuel && CargoManager.PurchasedItems.None(i => i.Value.Any(pi => pi.ItemPrefab.Tags.Contains("reactorfuel")))) + bool lowFuel = nextSub.Name == Submarine.MainSub.Info.Name ? Submarine.MainSub.Info.LowFuel : nextSub.LowFuel; + if (Level.IsLoadedFriendlyOutpost && lowFuel && CargoManager.PurchasedItems.None(i => i.Value.Any(pi => pi.ItemPrefab.Tags.Contains("reactorfuel")))) { var extraConfirmationBox = new GUIMessageBox(TextManager.Get("lowfuelheader"), diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index 72f04c0ae..c7d279a2d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -693,13 +693,15 @@ namespace Barotrauma if (ShouldApply(NetFlags.SubList, id, requireUpToDateSave: false)) { - GameMain.GameSession.OwnedSubmarines.Clear(); foreach (int ownedSubIndex in ownedSubIndices) { SubmarineInfo sub = GameMain.Client.ServerSubmarines[ownedSubIndex]; if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, NetLobbyScreen.SubmarineDeliveryData.Owned)) { - GameMain.GameSession.OwnedSubmarines.Add(sub); + if (GameMain.GameSession.OwnedSubmarines.None(s => s.Name == sub.Name)) + { + GameMain.GameSession.OwnedSubmarines.Add(sub); + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index d43988bd0..ca210f1fb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -938,7 +938,7 @@ namespace Barotrauma.Items.Components DrawMarker(spriteBatch, Level.Loaded.StartLocation.Name, (Level.Loaded.StartOutpost != null ? "outpost" : "location").ToIdentifier(), - Level.Loaded.StartLocation.Name, + "startlocation", Level.Loaded.StartExitPosition, transducerCenter, displayScale, center, DisplayRadius); } @@ -948,7 +948,7 @@ namespace Barotrauma.Items.Components DrawMarker(spriteBatch, Level.Loaded.EndLocation.Name, (Level.Loaded.EndOutpost != null ? "outpost" : "location").ToIdentifier(), - Level.Loaded.EndLocation.Name, + "endlocation", Level.Loaded.EndExitPosition, transducerCenter, displayScale, center, DisplayRadius); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs index 0fc5d2c4f..6aee6dd4f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Creatures/BallastFloraBehavior.cs @@ -91,6 +91,8 @@ namespace Barotrauma.MapCreatures.Behavior { foreach (BallastFloraBranch branch in Branches) { + if (branch.IsRoot && isDead) { continue; } + if (branch.AccumulatedDamage > 0) { CreateDamageParticle(branch, branch.AccumulatedDamage); @@ -101,8 +103,7 @@ namespace Barotrauma.MapCreatures.Behavior GUI.AddMessage($"{(int)branch.AccumulatedDamage}", GUIStyle.Red, pos, Vector2.UnitY * 10.0f, 3f, playSound: false, subId: Parent?.Submarine?.ID ?? -1); } } - if (Character.Controlled != null && Character.Controlled.CurrentHull == branch.CurrentHull && - branch.IsRoot && + if (Character.Controlled != null && Character.Controlled.CurrentHull == branch.CurrentHull && branch.IsRoot && (branch.AccumulatedDamage > 0.0f || branch.AccumulatedDamage < -0.1f)) { Character.Controlled.UpdateHUDProgressBar(this, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs index 21dc8cb32..8da238592 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs @@ -216,7 +216,7 @@ namespace Barotrauma { if (Math.Sign(flowTargetHull.Rect.Y - rect.Y) != Math.Sign(lerpedFlowForce.Y)) { return; } - float particlesPerSec = Math.Max(open * rect.Width * 0.5f * particleAmountMultiplier, 10.0f); + float particlesPerSec = Math.Max(open * rect.Width * particleAmountMultiplier, 10.0f); float emitInterval = 1.0f / particlesPerSec; while (particleTimer > emitInterval) { @@ -257,8 +257,8 @@ namespace Barotrauma /*no dripping from large gaps between rooms (looks bad)*/ ((GapSize() <= Structure.WallSectionSize) || !IsRoomToRoom)) { - particleTimer += deltaTime; - float particlesPerSec = open * 100.0f * particleAmountMultiplier; + particleTimer += deltaTime; + float particlesPerSec = open * 10.0f * particleAmountMultiplier; float emitInterval = 1.0f / particlesPerSec; while (particleTimer > emitInterval) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs index a889a9b4d..90382e7c9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs @@ -271,7 +271,7 @@ namespace Barotrauma case VoteType.SwitchSub: string subName1 = inc.ReadString(); bool transferItems = inc.ReadBoolean(); - SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1); + SubmarineInfo info = GameMain.GameSession.OwnedSubmarines.FirstOrDefault(s => s.Name == subName1) ?? GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1); if (info == null) { DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted"); @@ -303,7 +303,7 @@ namespace Barotrauma case VoteType.PurchaseAndSwitchSub: case VoteType.SwitchSub: string subName2 = inc.ReadString(); - var submarineInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2); + var submarineInfo = GameMain.GameSession.OwnedSubmarines.FirstOrDefault(s => s.Name == subName2) ?? GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2); bool transferItems = inc.ReadBoolean(); int deliveryFee = inc.ReadInt16(); if (submarineInfo == null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 3ec07ec1d..66c404987 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -921,7 +921,7 @@ namespace Barotrauma toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.08f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 15) }, style: "UIToggleButtonVertical") { - ToolTip = RichString.Rich(TextManager.Get("EntityMenuToggleTooltip") + "‖color:125,125,125‖\nQ‖color:end‖"), + ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖"), OnClicked = (btn, userdata) => { entityMenuOpen = !entityMenuOpen; @@ -5187,7 +5187,7 @@ namespace Barotrauma } } - if (PlayerInput.KeyHit(Keys.Q) && mode == Mode.Default) + if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].IsHit() && mode == Mode.Default) { toggleEntityMenuButton.OnClicked?.Invoke(toggleEntityMenuButton, toggleEntityMenuButton.UserData); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index 26f597a25..636331079 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Barotrauma.Items.Components; using Barotrauma.Extensions; +using System.Diagnostics; namespace Barotrauma { @@ -1437,28 +1438,31 @@ namespace Barotrauma } } break; - case ItemComponent _ when entity is Item item: - foreach (var component in item.Components) + case ItemComponent parentComponent when entity is Item otherItem: + if (otherItem == parentComponent.Item) { continue; } + int componentIndex = parentComponent.Item.Components.FindAll(c => c.GetType() == parentComponent.GetType()).IndexOf(parentComponent); + //find the component of the same type and same index from the other item + var otherComponents = otherItem.Components.FindAll(c => c.GetType() == parentComponent.GetType()); + if (componentIndex >= 0 && componentIndex < otherComponents.Count) { - if (component.GetType() == parentObject.GetType() && component != parentObject) + var component = otherComponents[componentIndex]; + Debug.Assert(component.GetType() == parentObject.GetType()); + SafeAdd(component, property); + if (value is string stringValue && Enum.TryParse(property.PropertyType, stringValue, out var enumValue)) { - SafeAdd(component, property); - if (value is string stringValue && Enum.TryParse(property.PropertyType, stringValue, out var enumValue)) - { - property.PropertyInfo.SetValue(component, enumValue); - } - else - { - try - { - property.PropertyInfo.SetValue(component, value); - } - catch (ArgumentException e) - { - DebugConsole.ThrowError($"Failed to set the value of the property \"{property.Name}\" to {value?.ToString() ?? "null"}", e); - } - } + property.PropertyInfo.SetValue(component, enumValue); } + else + { + try + { + property.PropertyInfo.SetValue(component, value); + } + catch (ArgumentException e) + { + DebugConsole.ThrowError($"Failed to set the value of the property \"{property.Name}\" to {value?.ToString() ?? "null"}", e); + } + } } break; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs index 962d30825..9cf545dc8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs @@ -46,21 +46,7 @@ namespace Barotrauma return Instance; } - public void Recreate() - { - if (GUI.SettingsMenuOpen) - { - GUI.SettingsMenuOpen = false; - GUI.SettingsMenuOpen = true; - } - else - { - Create(mainFrame.Parent.RectTransform); - Instance?.SelectTab(Tab.Controls); - } - } - - private SettingsMenu(RectTransform mainParent) + private SettingsMenu(RectTransform mainParent, GameSettings.Config setConfig = default) { unsavedConfig = GameSettings.CurrentConfig; @@ -476,8 +462,9 @@ namespace Barotrauma Slider(voiceChat, (0, 500), 26, (v) => $"{Round(v)} ms", unsavedConfig.Audio.VoiceChatCutoffPrevention, (v) => unsavedConfig.Audio.VoiceChatCutoffPrevention = Round(v), TextManager.Get("CutoffPreventionTooltip")); } - + private readonly Dictionary> inputButtonValueNameGetters = new Dictionary>(); private bool inputBoxSelectedThisFrame = false; + private void CreateControlsTab() { GUIFrame content = CreateNewContentFrame(Tab.Controls); @@ -501,7 +488,7 @@ namespace Barotrauma GUILayoutGroup createInputRowLayout() => new GUILayoutGroup(new RectTransform((1.0f, 0.1f), keyMapList.Content.RectTransform), isHorizontal: true); - HashSet inputButtons = new HashSet(); + inputButtonValueNameGetters.Clear(); Action? currentSetter = null; void addInputToRow(GUILayoutGroup currRow, LocalizedString labelText, Func valueNameGetter, Action valueSetter, bool isLegacyBind = false) { @@ -519,7 +506,7 @@ namespace Barotrauma { OnClicked = (btn, obj) => { - inputButtons.ForEach(b => + inputButtonValueNameGetters.Keys.ForEach(b => { if (b != btn) { b.Selected = false; } }); @@ -544,7 +531,7 @@ namespace Barotrauma inputBox.Color = Color.Lerp(inputBox.Color, inputBox.DisabledColor, 0.5f); inputBox.TextColor = Color.Lerp(inputBox.TextColor, label.DisabledTextColor, 0.5f); } - inputButtons.Add(inputBox); + inputButtonValueNameGetters.Add(inputBox, valueNameGetter); } var inputListener = new GUICustomComponent(new RectTransform(Vector2.Zero, layout.RectTransform), onUpdate: (deltaTime, component) => @@ -560,7 +547,7 @@ namespace Barotrauma void clearSetter() { currentSetter = null; - inputButtons.ForEach(b => b.Selected = false); + inputButtonValueNameGetters.Keys.ForEach(b => b.Selected = false); } void callSetter(KeyOrMouse v) @@ -663,11 +650,14 @@ namespace Barotrauma TextManager.Get("Reset"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("SetDefaultBindingsTooltip"), - OnClicked = (btn, userdata) => + OnClicked = (_, userdata) => { unsavedConfig.InventoryKeyMap = GameSettings.Config.InventoryKeyMapping.GetDefault(); unsavedConfig.KeyMap = GameSettings.Config.KeyMapping.GetDefault(); - Recreate(); + foreach (var btn in inputButtonValueNameGetters.Keys) + { + btn.Text = inputButtonValueNameGetters[btn](); + } Instance?.SelectTab(Tab.Controls); return true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs index d7a3f7b70..03760d937 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Steam/Lobby.cs @@ -360,8 +360,8 @@ namespace Barotrauma.Steam if (rules == null) { return; } - if (rules.ContainsKey("message")) serverInfo.ServerMessage = rules["message"]; - if (rules.ContainsKey("version")) serverInfo.GameVersion = rules["version"]; + if (rules.ContainsKey("message")) { serverInfo.ServerMessage = rules["message"]; } + if (rules.ContainsKey("version")) { serverInfo.GameVersion = rules["version"]; } if (rules.ContainsKey("playercount")) { @@ -371,8 +371,8 @@ namespace Barotrauma.Steam serverInfo.ContentPackageNames.Clear(); serverInfo.ContentPackageHashes.Clear(); serverInfo.ContentPackageWorkshopIds.Clear(); - if (rules.ContainsKey("contentpackage")) serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(',')); - if (rules.ContainsKey("contentpackagehash")) serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(',')); + if (rules.ContainsKey("contentpackage")) { serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(',')); } + if (rules.ContainsKey("contentpackagehash")) { serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(',')); } if (rules.ContainsKey("contentpackageid")) { serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(rules["contentpackageid"])); @@ -383,24 +383,26 @@ namespace Barotrauma.Steam serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls)); } - if (rules.ContainsKey("usingwhitelist")) serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True"; + if (rules.ContainsKey("usingwhitelist")) { serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True"; } if (rules.ContainsKey("modeselectionmode")) { - if (Enum.TryParse(rules["modeselectionmode"], out SelectionMode selectionMode)) serverInfo.ModeSelectionMode = selectionMode; + if (Enum.TryParse(rules["modeselectionmode"], out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; } } if (rules.ContainsKey("subselectionmode")) { - if (Enum.TryParse(rules["subselectionmode"], out SelectionMode selectionMode)) serverInfo.SubSelectionMode = selectionMode; + if (Enum.TryParse(rules["subselectionmode"], out SelectionMode selectionMode)) { serverInfo.SubSelectionMode = selectionMode; } } - if (rules.ContainsKey("allowspectating")) serverInfo.AllowSpectating = rules["allowspectating"] == "True"; - if (rules.ContainsKey("allowrespawn")) serverInfo.AllowRespawn = rules["allowrespawn"] == "True"; - if (rules.ContainsKey("voicechatenabled")) serverInfo.VoipEnabled = rules["voicechatenabled"] == "True"; + if (rules.ContainsKey("allowspectating")) { serverInfo.AllowSpectating = rules["allowspectating"] == "True"; } + if (rules.ContainsKey("allowrespawn")) { serverInfo.AllowRespawn = rules["allowrespawn"] == "True"; } + if (rules.ContainsKey("voicechatenabled")) { serverInfo.VoipEnabled = rules["voicechatenabled"] == "True"; } + if (rules.ContainsKey("friendlyfireenabled")) { serverInfo.AllowRespawn = rules["friendlyfireenabled"] == "True"; } + if (rules.ContainsKey("karmaenabled")) { serverInfo.VoipEnabled = rules["karmaenabled"] == "True"; } if (rules.ContainsKey("traitors")) { - if (Enum.TryParse(rules["traitors"], out YesNoMaybe traitorsEnabled)) serverInfo.TraitorsEnabled = traitorsEnabled; + if (Enum.TryParse(rules["traitors"], out YesNoMaybe traitorsEnabled)) { serverInfo.TraitorsEnabled = traitorsEnabled; } } - if (rules.ContainsKey("gamestarted")) serverInfo.GameStarted = rules["gamestarted"] == "True"; + if (rules.ContainsKey("gamestarted")) { serverInfo.GameStarted = rules["gamestarted"] == "True"; } if (rules.ContainsKey("gamemode")) { serverInfo.GameMode = rules["gamemode"].ToIdentifier(); diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index f7afa25be..251b78f36 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index bf185dc38..065e6b693 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 17381b7cf..f684f83ae 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 33817d5ec..868528655 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 5dedada53..523a650c6 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index a9a05313a..58cb3e0ee 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -1367,6 +1367,11 @@ namespace Barotrauma } else { + if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign) + { + MultiPlayerCampaign.StartCampaignSetup(); + return; + } if (!GameMain.Server.StartGame()) { NewMessage("Failed to start a new round", Color.Yellow); } } })); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index 0f479cbb1..e246d4549 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -1598,10 +1598,11 @@ namespace Barotrauma.Networking outmsg.Write((UInt16)subList.Count); for (int i = 0; i < subList.Count; i++) { - outmsg.Write(subList[i].Name); - outmsg.Write(subList[i].MD5Hash.ToString()); - outmsg.Write((byte)subList[i].SubmarineClass); - outmsg.Write(subList[i].RequiredContentPackagesInstalled); + var sub = subList[i]; + outmsg.Write(sub.Name); + outmsg.Write(sub.MD5Hash.ToString()); + outmsg.Write((byte)sub.SubmarineClass); + outmsg.Write(sub.RequiredContentPackagesInstalled); } outmsg.Write(GameStarted); @@ -2030,12 +2031,15 @@ namespace Barotrauma.Networking GameModePreset selectedMode = Voting.HighestVoted(VoteType.Mode, connectedClients); if (selectedMode == null) { selectedMode = GameMain.NetLobbyScreen.SelectedMode; } - if (selectedMode == null) { return false; } - + if (selectedMode == GameModePreset.MultiPlayerCampaign && !(GameMain.GameSession?.GameMode is CampaignMode)) + { + DebugConsole.ThrowError("StartGame failed. Cannot start a multiplayer campaign via StartGame - use MultiPlayerCampaign.StartNewCampaign or MultiPlayerCampaign.LoadCampaign instead."); + return false; + } initiatedStartGame = true; startGameCoroutine = CoroutineManager.StartCoroutine(InitiateStartGame(selectedSub, selectedShuttle, selectedMode), "InitiateStartGame"); @@ -2122,11 +2126,17 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Failure; } + bool initialSuppliesSpawned = false; //don't instantiate a new gamesession if we're playing a campaign if (campaign == null || GameMain.GameSession == null) { GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, settings, GameMain.NetLobbyScreen.LevelSeed, missionType: GameMain.NetLobbyScreen.MissionType); } + else + { + initialSuppliesSpawned = GameMain.GameSession.SubmarineInfo is { InitialSuppliesSpawned: true }; + } + List playingClients = new List(connectedClients); if (serverSettings.AllowSpectating) @@ -2409,18 +2419,16 @@ namespace Barotrauma.Networking campaign?.CargoManager.InitPurchasedIDCards(); - if (campaign == null || campaign.IsFirstRound) + if (campaign == null || !initialSuppliesSpawned) { foreach (Submarine sub in Submarine.MainSubs) { if (sub == null) { continue; } - List spawnList = new List(); foreach (KeyValuePair kvp in serverSettings.ExtraCargo) { spawnList.Add(new PurchasedItem(kvp.Key, kvp.Value, buyer: null)); } - CargoManager.CreateItems(spawnList, sub, cargoManager: null); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs index 4a3577fe5..4724420b4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Voting.cs @@ -295,7 +295,7 @@ namespace Barotrauma else { string subName = inc.ReadString(); - SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName); + SubmarineInfo subInfo = GameMain.GameSession.OwnedSubmarines.FirstOrDefault(s => s.Name == subName) ?? SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName); bool transferItems = inc.ReadBoolean(); if (!ShouldRejectVote(sender, voteType)) { @@ -389,8 +389,9 @@ namespace Barotrauma case VoteType.PurchaseSub: case VoteType.PurchaseAndSwitchSub: case VoteType.SwitchSub: - msg.Write((ActiveVote as SubmarineVote).Sub.Name); - msg.Write((ActiveVote as SubmarineVote).TransferItems); + SubmarineVote vote = ActiveVote as SubmarineVote; + msg.Write(vote.Sub.Name); + msg.Write(vote.TransferItems); break; case VoteType.TransferMoney: var transferVote = (ActiveVote as TransferVote); diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 9b8227d6e..43732773c 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.18.13.0 + 0.18.15.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs index bcb068006..1cfef53ce 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs @@ -14,7 +14,7 @@ namespace Barotrauma { public abstract class ContentPackage { - public static readonly Version MinimumHashCompatibleVersion = new Version(0, 18, 3, 0); + public static readonly Version MinimumHashCompatibleVersion = new Version(0, 18, 13, 0); public const string LocalModsDir = "LocalMods"; public static readonly string WorkshopModsDir = Barotrauma.IO.Path.Combine( @@ -180,7 +180,7 @@ namespace Barotrauma { if (!condition) { - throw new InvalidOperationException($"Failed to load \"{Name ?? Path}\": {errorMsg}"); + throw new InvalidOperationException($"Failed to load \"{Name}\" at {Path}: {errorMsg}"); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index 237dc566a..7bf83c372 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -1034,13 +1034,13 @@ namespace Barotrauma foreach (Item item in Item.ItemList) { if (item.Removed) { continue; } - if (item.NonInteractable) { continue; } + if (item.NonInteractable || item.NonPlayerTeamInteractable) { continue; } if (item.HiddenInGame) { continue; } if (!connectedSubs.Contains(item.Submarine)) { continue; } if (item.Prefab.DontTransferBetweenSubs) { continue; } var rootOwner = item.GetRootInventoryOwner(); if (rootOwner is Character) { continue; } - if (rootOwner is Item ownerItem && (ownerItem.NonInteractable || ownerItem.HiddenInGame)) { continue; } + if (rootOwner is Item ownerItem && (ownerItem.NonInteractable || item.NonPlayerTeamInteractable || ownerItem.HiddenInGame)) { continue; } if (item.GetComponent() != null) { continue; } if (item.Components.None(c => c is Pickable)) { continue; } if (item.Components.Any(c => c is Pickable p && p.IsAttached)) { continue; } @@ -1067,7 +1067,7 @@ namespace Barotrauma var connectedSubs = newSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet(); // Move the transferred items List availableContainers = Item.ItemList - .Where(it => connectedSubs.Contains(it.Submarine) && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed) + .Where(it => connectedSubs.Contains(it.Submarine) && it.HasTag("crate") && !it.NonInteractable && !it.NonPlayerTeamInteractable && !it.HiddenInGame && !it.Removed) .Select(it => it.GetComponent()) .Where(c => c != null) .ToList(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs index 3e792f98d..2b496a231 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs @@ -16,6 +16,7 @@ namespace Barotrauma Deselect, Shoot, Command, + ToggleInventory, TakeOneFromInventorySlot, TakeHalfFromInventorySlot, NextFireMode, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs index 53a55e033..a321e27a2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/MeleeWeapon.cs @@ -191,7 +191,7 @@ namespace Barotrauma.Items.Components while (impactQueue.Count > 0) { var impact = impactQueue.Dequeue(); - HandleImpact(impact.Body); + HandleImpact(impact); } //in case handling the impact does something to the picker if (picker == null) { return; } @@ -342,7 +342,7 @@ namespace Barotrauma.Items.Components } hitTargets.Add(targetCharacter); } - else if (f2.Body.UserData is Structure targetStructure) + else if ((f2.Body.UserData as Structure ?? f2.UserData as Structure) is Structure targetStructure) { if (AllowHitMultiple) { @@ -380,8 +380,9 @@ namespace Barotrauma.Items.Components return true; } - private void HandleImpact(Body target) + private void HandleImpact(Fixture targetFixture) { + var target = targetFixture.Body; if (User == null || User.Removed || target == null) { RestoreCollision(); @@ -410,7 +411,7 @@ namespace Barotrauma.Items.Components targetCharacter.LastDamageSource = item; Attack.DoDamage(User, targetCharacter, item.WorldPosition, 1.0f); } - else if (target.UserData is Structure targetStructure) + else if ((target.UserData as Structure ?? targetFixture.UserData as Structure) is Structure targetStructure) { if (targetStructure.Removed) { return; } Attack.DoDamage(User, targetStructure, item.WorldPosition, 1.0f); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs index af90c2aac..9c281f00d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs @@ -742,7 +742,7 @@ namespace Barotrauma.Items.Components limb.body?.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass * 0.1f, item.SimPosition); return false; } - if (!FriendlyFire && User != null && limb.character.IsFriendly(User)) + if (!FriendlyFire && User != null && limb.character.IsFriendly(User) && HumanAIController.IsOnFriendlyTeam(limb.character, User)) { return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs index fd5ee7f13..b44d136c2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs @@ -238,6 +238,12 @@ namespace Barotrauma.Items.Components base.OnItemLoaded(); SetLightSourceState(IsActive, lightBrightness); turret = item.GetComponent(); +#if CLIENT + if (Screen.Selected.IsEditor) + { + OnMapLoaded(); + } +#endif } public override void OnMapLoaded() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs index f23292212..33e8f4538 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs @@ -1,12 +1,11 @@ using System; using System.Text.RegularExpressions; -using System.Xml.Linq; namespace Barotrauma.Items.Components { class RegExFindComponent : ItemComponent { - private static readonly TimeSpan timeout = TimeSpan.FromSeconds(Timing.Step); + private static readonly TimeSpan timeout = TimeSpan.FromMilliseconds(1); private string expression; @@ -63,10 +62,9 @@ namespace Barotrauma.Items.Components get { return expression; } set { - if (expression == value) return; + if (expression == value) { return; } expression = value; previousReceivedSignal = ""; - try { regex = new Regex( @@ -74,11 +72,12 @@ namespace Barotrauma.Items.Components options: RegexOptions.None, matchTimeout: timeout); } - catch { return; } + //reactivate the component, in case some faulty/malicious expression caused it to time out and deactivate itself + IsActive = true; } } @@ -105,11 +104,16 @@ namespace Barotrauma.Items.Components } catch (Exception e) { - item.SendSignal( - e is RegexMatchTimeoutException - ? "TIMEOUT" - : "ERROR", - "signal_out"); + if (e is RegexMatchTimeoutException) + { + item.SendSignal("TIMEOUT", "signal_out"); + //deactivate the component if the expression caused it to time out + IsActive = false; + } + else + { + item.SendSignal("ERROR", "signal_out"); + } previousResult = false; return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs index 38570e057..8eabe4b03 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs @@ -308,6 +308,8 @@ namespace Barotrauma.MapCreatures.Behavior private BallastFloraBranch? root; private readonly List bodies = new List(); + private bool isDead; + public readonly BallastFloraStateMachine StateMachine; public int GrowthWarps; @@ -1230,6 +1232,8 @@ namespace Barotrauma.MapCreatures.Behavior public void Kill() { + isDead = true; + foreach (var branch in Branches) { branch.DisconnectedFromRoot = true; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index f1c9e40dd..3b6aad96f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -203,7 +203,7 @@ namespace Barotrauma if (Screen.Selected == GameMain.SubEditorScreen) { linkedSub = CreateDummy(submarine, element, pos, id); - linkedSub.saveElement = element; + linkedSub.saveElement = new XElement(element); linkedSub.purchasedLostShuttles = false; } else @@ -215,7 +215,7 @@ namespace Barotrauma purchasedLostShuttles = (GameMain.GameSession?.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles) || element.GetAttributeBool("purchasedlostshuttle", false), - saveElement = element + saveElement = new XElement(element) }; bool levelMatches = string.IsNullOrWhiteSpace(levelSeed) || levelData == null || levelData.Seed == levelSeed; @@ -453,12 +453,15 @@ namespace Barotrauma saveElement.SetAttributeValue("pos", XMLExtensions.Vector2ToString(Position - Submarine.HiddenSubPosition)); - var linkedPort = - linkedTo.FirstOrDefault(lt => (lt is Item item) && item.GetComponent() != null) ?? - FindEntityByID(linkedToID.First()) as MapEntity; - if (linkedPort != null) + if (linkedTo.Any() || linkedToID.Any()) { - saveElement.SetAttributeValue("linkedto", linkedPort.ID); + var linkedPort = + linkedTo.FirstOrDefault(lt => (lt is Item item) && item.GetComponent() != null) ?? + FindEntityByID(linkedToID.First()) as MapEntity; + if (linkedPort != null) + { + saveElement.SetAttributeValue("linkedto", linkedPort.ID); + } } } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationType.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationType.cs index efa64c5d4..e402b8073 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationType.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationType.cs @@ -113,15 +113,23 @@ namespace Barotrauma string teamStr = element.GetAttributeString("outpostteam", "FriendlyNPC"); Enum.TryParse(teamStr, out OutpostTeam); - ContentPath nameFile = element.GetAttributeContentPath("namefile") ?? ContentPath.FromRaw(null, "Content/Map/locationNames.txt"); - try + string[] rawNamePaths = element.GetAttributeStringArray("namefile", new string[] { "Content/Map/locationNames.txt" }); + names = new List(); + foreach (string rawPath in rawNamePaths) { - names = File.ReadAllLines(nameFile.Value).ToList(); + try + { + var path = ContentPath.FromRaw(element.ContentPackage, rawPath.Trim()); + names.AddRange(File.ReadAllLines(path.Value).ToList()); + } + catch (Exception e) + { + DebugConsole.ThrowError($"Failed to read name file \"rawPath\" for location type \"{Identifier}\"!", e); + } } - catch (Exception e) + if (!names.Any()) { - DebugConsole.ThrowError("Failed to read name file for location type \"" + Identifier + "\"!", e); - names = new List() { "Name file not found" }; + names.Add("ERROR: No names found"); } string[] commonnessPerZoneStrs = element.GetAttributeStringArray("commonnessperzone", Array.Empty()); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs index cab965679..898f27b77 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs @@ -92,6 +92,9 @@ namespace Barotrauma set; } + /// + /// Note: Refreshed for loaded submarines when they are saved, when they are loaded, and on round end. If you need to refresh it, please use Submarine.CheckFuel() method! + /// public bool LowFuel { get; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs index 73c7ce601..d13c4975e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs @@ -302,6 +302,7 @@ namespace Barotrauma { InputType.Down, Keys.S }, { InputType.Left, Keys.A }, { InputType.Right, Keys.D }, + { InputType.ToggleInventory, Keys.Q }, { InputType.SelectNextCharacter, Keys.Z }, { InputType.SelectPreviousCharacter, Keys.X }, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs b/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs index 7db7254a0..3c274b2c3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Steam/Workshop.cs @@ -324,7 +324,10 @@ namespace Barotrauma.Steam using (var copyIndicator = new CopyIndicator(copyIndicatorPath)) { - await CopyDirectory(itemDirectory, modPathDirName ?? modName, itemDirectory, installDir, ShouldCorrectPaths.Yes); + await CopyDirectory(itemDirectory, modPathDirName ?? modName, itemDirectory, installDir, + gameVersion < new Version(0, 18, 3, 0) + ? ShouldCorrectPaths.Yes + : ShouldCorrectPaths.No); string fileListDestPath = Path.Combine(installDir, ContentPackage.FileListFileName); XDocument fileListDest = XMLExtensions.TryLoadXml(fileListDestPath); diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 541f27647..635a98b76 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,17 +1,17 @@ --------------------------------------------------------------------------------------------------------- -v0.18.13.0 +v0.18.15.0 --------------------------------------------------------------------------------------------------------- Changes: -- Show a warning when trying to switch to a submarine that's low on fuel. +- Show a warning when trying to switch to a submarine that's low on fuel or to a submarine that has no manually placed items to prevent softlocking the campaign if you switch to a sub that has no fuel. Whether a submarine is considered to have manually placed items can be set when saving it in the submarine editor (the checkbox "manually outfitted" in the saving dialog). - Also show the low fuel warning when leaving an outpost without enough fuel. -- Items are always transferred when switching to a submarine that has no manually placed items, which should prevent softlocking the campaign if you switch to a sub that has no fuel. Whether a submarine is considered to have manually placed items can be set when saving it in the submarine editor (the checkbox "manually outfitted" in the saving dialog). - Handheld sonars can't detect minerals from inside the sub. - Changed the plus and minus button in the campaign settings into arrows. The button on the right increases difficulty, which in the case of the starting balance and supplies means reducing them, making the plus and minus buttons misleading. - Reduced costs of handheld weapon ammunition significantly. - Slightly reduced effectiveness of harpoons and revolver round to compensate for the cheaper ammo. - Changed recipes for Handcannon, Assault Rifle and Auto-Shotgun. Weapon crafting is more expensive, to compensate for cheaper ammo. - Adjusted numerous other recipes and price costs of materials. Previously little used materials (like tin) are now used more. +- Partially reintroduced the "toggle inventory" keybind, now called "toggle entity list". Even though toggling the in-game inventory is no longer possible, the keybind can be used to change the hotkey for toggling the sub editor's entity list. Fixes: - Fixed shuttles getting misplaced when switching and transferring items to a new sub with shuttles. @@ -38,7 +38,16 @@ Fixes: - Fixed missing background sprite in duct block. - Fixed water particles not showing up when water is flowing down a duct block. - Fixed changing the scale of resizeable structures (such as background doors) messing up the outline of linked subs in the sub editor. +- Fixed non-player-team interactable items getting transferred on sub switch. +- Fixed ballast flora root emitting particles when damaged client-side, even if it's already been destroyed. +- Fixed recycle recipes for Piercing Ammunition Box and Pulse Tri-Laser Fuel Box. - Fixed friendly fire and karma always showing up as disabled on dedicated servers in the server list. +- Fixed some lights (e.g. vending machines, neon lights, holographics displays) looking different in the sub editor than they do in-game. +- Fixed undocked shuttles remaining undocked if you save and start a new game with the same submarine during the same session. Restarting the game fixed the issue though. +- Fixed sonar markers going crazy if the start and end locations have the same name + added some more variety to location names to prevent duplicate location names. +- Fixed multiediting an ItemComponent modifying all the components of that type in all the selected items (e.g. when editing the 1st light component of a switch, all lights in all switches would be edited). +- Fixed spineling spikes fired by a human with spineling genes not damaging any human characters (enemies in PvP, pirates in pirate missions) when friendly fire is disabled. +- Fixed melee weapons not damaging structures from outside. Modding: - Fixed removing a door mid-round crashing the game. Does not affect the vanilla game, because doors are never removed mid-round. @@ -55,7 +64,6 @@ v0.18.12.0 - Fixed one of texts not appearing in the "captive souls" event. - Fixed inability to fabricate rubber shells. - Modding: - Fixed crashing when a MonsterEvent fails to find the character prefab. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a40f994b6..770fb43d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,10 @@ Welcome to Barotrauma's GitHub repository! If you're here to report an issue or to contribute to the development, please read the instructions below before you do. ## I have a question! -Please check [our FAQ](https://barotraumagame.com/faq/) in case the question has already been answered. If not, you can post the question on the [Barotrauma discussion forum](https://undertowgames.com/forum/viewforum.php?f=17) or stop by at our [Discord Server](https://discord.gg/undertow). +Please check [our FAQ](https://barotraumagame.com/faq/) in case the question has already been answered. If not, you can post the question on the [GitHub discussions](https://github.com/Regalis11/Barotrauma/discussions) or stop by at our [Discord Server](https://discord.gg/undertow). + +## I have an idea or feature request! +This GitHub issue tracker is only intended for bug reports. Ideas, development suggestions and feature requests should be posted in the [GitHub discussions](https://github.com/Regalis11/Barotrauma/discussions). ## Reporting a bug If you've encountered a bug, you can report it in the [issue tracker](https://github.com/Regalis11/Barotrauma/issues). Please follow the instructions in the issue template to make it easier for us to diagnose and fix the issue. diff --git a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Input/Mouse.SDL.cs b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Input/Mouse.SDL.cs index f558a7120..ad79e4b62 100644 --- a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Input/Mouse.SDL.cs +++ b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Input/Mouse.SDL.cs @@ -15,16 +15,16 @@ namespace Microsoft.Xna.Framework.Input { return PrimaryWindow.Handle; } - + private static void PlatformSetWindowHandle(IntPtr windowHandle) { } private static MouseState PlatformGetState(GameWindow window) { - int x, y; var winFlags = Sdl.Window.GetWindowFlags(window.Handle); - var state = Sdl.Mouse.GetGlobalState(out x, out y); + var state = Sdl.Mouse.GetState(out int x, out int y); + var globalState = Sdl.Mouse.GetGlobalState(out int globalX, out int globalY); if ((winFlags & Sdl.Window.State.MouseFocus) != 0) { @@ -42,8 +42,8 @@ namespace Microsoft.Xna.Framework.Input { // Window does not have mouse focus, we need to manually get the position var clientBounds = window.ClientBounds; - window.MouseState.X = x - clientBounds.X; - window.MouseState.Y = y - clientBounds.Y; + window.MouseState.X = globalX - clientBounds.X; + window.MouseState.Y = globalY - clientBounds.Y; } return window.MouseState; @@ -53,7 +53,6 @@ namespace Microsoft.Xna.Framework.Input { PrimaryWindow.MouseState.X = x; PrimaryWindow.MouseState.Y = y; - Sdl.Mouse.WarpInWindow(PrimaryWindow.Handle, x, y); }