diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs index 60036100f..a79157757 100644 --- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs @@ -249,13 +249,19 @@ namespace Barotrauma if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap)) { ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N", - (option) => { - if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull(); + (option) => + { + ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N", + (option2) => + { + if (option2.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); } + }); }); } else { - GameMain.SubEditorScreen.AutoHull(); + ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N", + (option) => { if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull(); }); } })); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs index 221798ec5..608643917 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs @@ -18,6 +18,7 @@ namespace Barotrauma public GUIFrame InnerFrame { get; private set; } public GUITextBlock Header { get; private set; } public GUITextBlock Text { get; private set; } + public string Tag { get; private set; } public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault(); @@ -34,7 +35,7 @@ namespace Barotrauma } // TODO: allow to use a relative size. - public GUIMessageBox(string headerText, string text, string[] buttons, int width = DefaultWidth, int height = 0, Alignment textAlignment = Alignment.TopLeft) + public GUIMessageBox(string headerText, string text, string[] buttons, int width = DefaultWidth, int height = 0, Alignment textAlignment = Alignment.TopLeft, string tag = "") : base(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "") { int headerHeight = 30; @@ -43,6 +44,7 @@ namespace Barotrauma GUI.Style.Apply(InnerFrame, "", this); Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 }; + Tag = tag; if (height == 0) { diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index b85642b1f..64cd2f6eb 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -1061,6 +1061,8 @@ namespace Barotrauma.Networking if (lobbyUpdated) { + var prevDispatcher = GUI.KeyboardDispatcher.Subscriber; + UInt16 updateID = inc.ReadUInt16(); string serverName = inc.ReadString(); string serverText = inc.ReadString(); @@ -1162,9 +1164,19 @@ namespace Barotrauma.Networking ConnectedClients.RemoveAt(i); } } + //remove clients that aren't present anymore + for (int i = ConnectedClients.Count - 1; i >= 0; i--) + { + if (!currentClients.Contains(ConnectedClients[i])) + { + GameMain.NetLobbyScreen.RemovePlayer(ConnectedClients[i].Name); + ConnectedClients.RemoveAt(i); + } + } Voting.AllowSubVoting = allowSubVoting; Voting.AllowModeVoting = allowModeVoting; + GUI.KeyboardDispatcher.Subscriber = prevDispatcher; } } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs index 145bc0b83..a3dafefb2 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs @@ -290,25 +290,32 @@ namespace Barotrauma.Networking if (ip == null || (!ip.CanBeBought && !ip.Tags.Contains("smallitem"))) continue; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, + var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true) + { + Stretch = true, + UserData = cargoFrame, + RelativeSpacing = 0.05f + }; + + + if (ip.InventoryIcon != null || ip.sprite != null) + { + GUIImage img = new GUIImage(new RectTransform(new Point(itemFrame.Rect.Height), itemFrame.RectTransform), + ip.InventoryIcon ?? ip.sprite, scaleToFit: true) + { + CanBeFocused = false + }; + img.Color = img.Sprite == ip.InventoryIcon ? ip.InventoryIconColor : ip.SpriteColor; + } + new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), itemFrame.RectTransform), ip.Name, font: GUI.SmallFont) { - Padding = new Vector4(40.0f, 3.0f, 0.0f, 0.0f), - UserData = cargoFrame, CanBeFocused = false }; - if (ip.sprite != null) - { - GUIImage img = new GUIImage(new RectTransform(new Point(textBlock.Rect.Height), textBlock.RectTransform), ip.sprite, scaleToFit: true) - { - Color = ip.SpriteColor - }; - } - extraCargo.TryGetValue(ip, out int cargoVal); - var amountInput = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), - GUINumberInput.NumberType.Int) + var amountInput = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), itemFrame.RectTransform), + GUINumberInput.NumberType.Int, textAlignment: Alignment.CenterLeft) { MinValueInt = 0, MaxValueInt = 100, diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs index 148eda132..bb87ae536 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs @@ -253,6 +253,14 @@ namespace Barotrauma private void UpdateLocationView(Location location) { + if (location == null) + { + string errorMsg = "Failed to update CampaignUI location view (location was null)\n" + Environment.StackTrace; + DebugConsole.ThrowError(errorMsg); + GameAnalyticsManager.AddErrorEventOnce("CampaignUI.UpdateLocationView:LocationNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + return; + } + if (characterPreviewFrame != null) { characterPreviewFrame.Parent.RemoveChild(characterPreviewFrame); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs index 28a143936..9373f21f7 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs @@ -126,6 +126,8 @@ namespace Barotrauma isEndlessRunner = false; if (character != null) { + AnimParams.ForEach(a => a.Reset(true)); + RagdollParams.Reset(true); RagdollParams.ClearHistory(); CurrentAnimation.ClearHistory(); if (!character.Removed) @@ -833,12 +835,12 @@ namespace Barotrauma break; } var limb = selectedLimbs[i]; - if (limb == character.AnimController.MainLimb) - { - // TODO: this should be possible now -> test - DebugConsole.ThrowError("Can't remove the main limb, because it will crash the game."); - continue; - } + //if (limb == character.AnimController.MainLimb) + //{ + // // TODO: this should be possible now -> test + // DebugConsole.ThrowError("Can't remove the main limb, because it will crash the game."); + // continue; + //} removedIDs.Add(limb.limbParams.ID); limb.limbParams.Element.Remove(); RagdollParams.Limbs.Remove(limb.limbParams); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 9af609660..634a7526a 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -64,6 +64,8 @@ namespace Barotrauma private DateTime editorSelectedTime; + private readonly string containerDeleteTag = "containerdelete"; + public override Camera Cam { get { return cam; } @@ -580,6 +582,143 @@ namespace Barotrauma dummyCharacter = null; GameMain.World.ProcessChanges(); } + + if (GUIMessageBox.MessageBoxes.Any(mbox => (mbox as GUIMessageBox).Tag == containerDeleteTag)) + { + for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++) + { + GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox; + if (box.Tag != containerDeleteTag) continue; + box.Close(); + i--; // Take into account the message boxes removing themselves from the list when closed + } + } + } + + public void HandleContainerContentsDeletion(Item itemToDelete, Inventory itemInventory) + { + string itemNames = string.Empty; + + foreach (Item item in itemInventory.Items) + { + if (item == null) continue; + itemNames += item.Name + "\n"; + } + + if (itemNames.Length > 0) + { + // Multiple prompts open + if (GUIMessageBox.MessageBoxes.Any(mbox => (mbox as GUIMessageBox).Tag == containerDeleteTag)) + { + var msgBox = new GUIMessageBox(itemToDelete.Name, TextManager.Get("DeletingContainerWithItems") + itemNames, new string[] { TextManager.Get("Yes"), TextManager.Get("No"), TextManager.Get("YesToAll"), TextManager.Get("NoToAll") }, tag: containerDeleteTag); + + // Yes + msgBox.Buttons[0].OnClicked = (btn, userdata) => + { + itemInventory.DeleteAllItems(); + msgBox.Close(); + return true; + }; + + // No + msgBox.Buttons[1].OnClicked = (btn, userdata) => + { + if (Selected == GameMain.SubEditorScreen) + { + foreach (Item item in itemInventory.Items) + { + if (item == null) continue; + item.Drop(); + } + } + else // If current screen is not subeditor, delete anyway to avoid lingering objects + { + itemInventory.DeleteAllItems(); + } + + msgBox.Close(); + return true; + }; + + // Yes to All + msgBox.Buttons[2].OnClicked = (btn, userdata) => + { + for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++) + { + GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox; + if (box.Tag != msgBox.Tag || box == msgBox) continue; + GUIButton button = box.Buttons[0]; + button.OnClicked(button, button.UserData); + i--; // Take into account the message boxes removing themselves from the list when closed + } + + itemInventory.DeleteAllItems(); + msgBox.Close(); + return true; + }; + + // No to all + msgBox.Buttons[3].OnClicked = (btn, userdata) => + { + for (int i = 0; i < GUIMessageBox.MessageBoxes.Count; i++) + { + GUIMessageBox box = GUIMessageBox.MessageBoxes[i] as GUIMessageBox; + if (box.Tag != msgBox.Tag || box == msgBox) continue; + GUIButton button = box.Buttons[1]; + button.OnClicked(button, button.UserData); + i--; // Take into account the message boxes removing themselves from the list when closed + } + + if (Selected == GameMain.SubEditorScreen) + { + foreach (Item item in itemInventory.Items) + { + if (item == null) continue; + item.Drop(); + } + } + else // If current screen is not subeditor, delete anyway to avoid lingering objects + { + itemInventory.DeleteAllItems(); + } + + msgBox.Close(); + return true; + }; + } + else // Single prompt + { + var msgBox = new GUIMessageBox(itemToDelete.Name, TextManager.Get("DeletingContainerWithItems") + itemNames, new string[] { TextManager.Get("Yes"), TextManager.Get("No") }, tag: containerDeleteTag); + + // Yes + msgBox.Buttons[0].OnClicked = (btn, userdata) => + { + itemInventory.DeleteAllItems(); + msgBox.Close(); + return true; + }; + + // No + msgBox.Buttons[1].OnClicked = (btn, userdata) => + { + if (Selected == GameMain.SubEditorScreen) + { + foreach (Item item in itemInventory.Items) + { + if (item == null) continue; + item.Drop(); + } + } + else // If current screen is not subeditor, delete anyway to avoid lingering objects + { + itemInventory.DeleteAllItems(); + } + + msgBox.Close(); + return true; + }; + } + } } private void CreateDummyCharacter() diff --git a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs index a66913d4b..6d2d05a34 100644 --- a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs @@ -225,6 +225,14 @@ namespace Barotrauma flowSoundChannels[i].Dispose(); flowSoundChannels[i] = null; } + for (int i = 0; i < fireSoundChannels.Length; i++) + { + if (fireSoundChannels[i] == null) continue; + fireSoundChannels[i].Dispose(); + fireSoundChannels[i] = null; + } + fireVolumeLeft[0] = 0.0f; fireVolumeLeft[1] = 0.0f; + fireVolumeRight[0] = 0.0f; fireVolumeRight[1] = 0.0f; return; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index 9660bf489..de26d24c3 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -121,7 +121,7 @@ namespace Barotrauma { //if path is up-to-date and contains outdoors nodes, this path is unreachable var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager; - if (pathSteering.CurrentPath != null && + if (pathSteering?.CurrentPath != null && Vector2.Distance(pathSteering.CurrentTarget, currTargetPos) < 1.0f && pathSteering.CurrentPath.HasOutdoorsNodes) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs index 09aba7a54..c396415e2 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs @@ -130,6 +130,7 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { if (Frozen) return; + if (MainLimb == null) { return; } if (character.IsDead || character.IsUnconscious || character.Stun > 0.0f) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index e4292c0bf..441f5e373 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -311,6 +311,7 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { if (Frozen) return; + if (MainLimb == null) { return; } levitatingCollider = true; ColliderIndex = Crouching ? 1 : 0; @@ -335,8 +336,7 @@ namespace Barotrauma else { deathAnimTimer = 0.0f; - } - + } if (!character.AllowInput) { @@ -1834,6 +1834,8 @@ namespace Barotrauma } } + if (!character.Enabled) { return; } + Vector2 handSimPos = ConvertUnits.ToSimUnits(handWorldPos); if (character.Submarine != null) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs index eed8a11ea..d25256a25 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs @@ -382,6 +382,11 @@ namespace Barotrauma protected void CreateSnapshot() where T : AnimationParams, new() { Serialize(); + if (doc == null) + { + DebugConsole.ThrowError("[AnimationParams] The source XML Document is null!"); + return; + } var copy = new T { IsLoaded = true, diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/EditableParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/EditableParams.cs index 9ad03e65d..9155d1d77 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/EditableParams.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/EditableParams.cs @@ -45,6 +45,11 @@ namespace Barotrauma protected virtual bool Serialize(XElement element = null) { element = element ?? MainElement; + if (element == null) + { + DebugConsole.ThrowError("[EditableParams] The XML element is null!"); + return false; + } SerializableProperty.SerializeProperties(this, element, true); return true; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs index 8beccd32e..56d4e5bf4 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs @@ -311,6 +311,11 @@ namespace Barotrauma public override void CreateSnapshot() { Serialize(); + if (doc == null) + { + DebugConsole.ThrowError("[RagdollParams] The source XML Document is null!"); + return; + } var copy = new RagdollParams { IsLoaded = true, @@ -328,13 +333,29 @@ namespace Barotrauma private void RevertTo(RagdollParams source) { + if (source.MainElement == null) + { + DebugConsole.ThrowError("[RagdollParams] The source XML Element of the given RagdollParams is null!"); + return; + } Deserialize(source.MainElement, recursive: false); var sourceSubParams = source.GetAllSubParams().ToList(); var subParams = GetAllSubParams().ToList(); + // TODO: cannot currently undo joint/limb deletion. + if (sourceSubParams.Count != subParams.Count) + { + DebugConsole.ThrowError("[RagdollParams] The count of the sub params differs! Failed to revert to the previous snapshot! Please reset the ragdoll to undo the changes."); + return; + } for (int i = 0; i < subParams.Count; i++) { - subParams[i].Deserialize(sourceSubParams[i].Element, recursive: false); var subSubParams = subParams[i].SubParams; + if (subSubParams.Count != sourceSubParams[i].SubParams.Count) + { + DebugConsole.ThrowError("[RagdollParams] The count of the sub sub params differs! Failed to revert to the previous snapshot! Please reset the ragdoll to undo the changes."); + return; + } + subParams[i].Deserialize(sourceSubParams[i].Element, recursive: false); for (int j = 0; j < subSubParams.Count; j++) { subSubParams[j].Deserialize(sourceSubParams[i].SubParams[j].Element, recursive: false); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs index acedc2f5a..9580cff53 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs @@ -1355,6 +1355,7 @@ namespace Barotrauma "Attempted to move a ragdoll (" + character.Name + ") to an invalid position (" + simPosition + "). " + Environment.StackTrace); return; } + if (MainLimb == null) { return; } Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index b5b610a71..78eebbcb6 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -525,7 +525,11 @@ namespace Barotrauma public override Vector2 DrawPosition { - get { return AnimController.MainLimb.body.DrawPosition; } + get + { + if (AnimController.MainLimb == null) { return Vector2.Zero; } + return AnimController.MainLimb.body.DrawPosition; + } } public delegate void OnDeathHandler(Character character, CauseOfDeath causeOfDeath); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs index 373e369ac..f2f251777 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs @@ -354,26 +354,26 @@ namespace Barotrauma if (matchingAfflictions.Count == 0) return; - do + float reduceAmount = amount / matchingAfflictions.Count; + for (int i = matchingAfflictions.Count - 1; i >= 0; i--) { - float reduceAmount = amount / matchingAfflictions.Count; - for (int i = matchingAfflictions.Count - 1; i >= 0; i--) + var matchingAffliction = matchingAfflictions[i]; + if (matchingAffliction.Strength < reduceAmount) { - var matchingAffliction = matchingAfflictions[i]; - if (matchingAffliction.Strength < reduceAmount) - { - amount -= matchingAffliction.Strength; - matchingAffliction.Strength = 0.0f; - matchingAfflictions.RemoveAt(i); - SteamAchievementManager.OnAfflictionRemoved(matchingAffliction, Character); - } - else - { - matchingAffliction.Strength -= reduceAmount; - amount -= reduceAmount; - } + float surplus = reduceAmount - matchingAffliction.Strength; + amount -= matchingAffliction.Strength; + matchingAffliction.Strength = 0.0f; + matchingAfflictions.RemoveAt(i); + if (i == 0) i = matchingAfflictions.Count; + if (i > 0) reduceAmount += surplus / i; + SteamAchievementManager.OnAfflictionRemoved(matchingAffliction, Character); } - } while (matchingAfflictions.Count > 0 && amount > 0.0f); + else + { + matchingAffliction.Strength -= reduceAmount; + amount -= reduceAmount; + } + } } diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index f213b2b7a..21ef0b7b8 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -3036,7 +3036,7 @@ namespace Barotrauma } } - string fileName = "DebugConsoleLog_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString() + ".txt"; + string fileName = "DebugConsoleLog_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString(); var invalidChars = Path.GetInvalidFileNameChars(); foreach (char invalidChar in invalidChars) { @@ -3044,7 +3044,7 @@ namespace Barotrauma } string filePath = Path.Combine(SavePath, fileName); - if (File.Exists(filePath)) + if (File.Exists(filePath + ".txt")) { int fileNum = 2; while (File.Exists(filePath + " (" + fileNum + ")")) @@ -3056,7 +3056,7 @@ namespace Barotrauma try { - File.WriteAllLines(filePath, unsavedMessages.Select(l => "[" + l.Time + "] " + l.Text)); + File.WriteAllLines(filePath + ".txt", unsavedMessages.Select(l => "[" + l.Time + "] " + l.Text)); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaShared/Source/Events/ArtifactEvent.cs b/Barotrauma/BarotraumaShared/Source/Events/ArtifactEvent.cs index eae83501b..eecbf6402 100644 --- a/Barotrauma/BarotraumaShared/Source/Events/ArtifactEvent.cs +++ b/Barotrauma/BarotraumaShared/Source/Events/ArtifactEvent.cs @@ -64,19 +64,14 @@ namespace Barotrauma item = new Item(itemPrefab, spawnPos, null); item.body.FarseerBody.IsKinematic = true; - //try to find a nearby artifact holder (or any alien itemcontainer) and place the artifact inside it + //try to find an artifact holder and place the artifact inside it foreach (Item it in Item.ItemList) { - if (it.Submarine != null || !it.HasTag("alien")) continue; - - if (Math.Abs(item.WorldPosition.X - it.WorldPosition.X) > 2000.0f) continue; - if (Math.Abs(item.WorldPosition.Y - it.WorldPosition.Y) > 2000.0f) continue; + if (it.Submarine != null || !it.HasTag("artifactholder")) continue; var itemContainer = it.GetComponent(); if (itemContainer == null) continue; - - itemContainer.Combine(item); - break; + if (itemContainer.Combine(item)) break; // Placement successful } if (GameSettings.VerboseLogging) diff --git a/Barotrauma/BarotraumaShared/Source/Events/Missions/SalvageMission.cs b/Barotrauma/BarotraumaShared/Source/Events/Missions/SalvageMission.cs index f2db2f88d..d013158a2 100644 --- a/Barotrauma/BarotraumaShared/Source/Events/Missions/SalvageMission.cs +++ b/Barotrauma/BarotraumaShared/Source/Events/Missions/SalvageMission.cs @@ -64,19 +64,14 @@ namespace Barotrauma if (item.HasTag("alien")) { - //try to find a nearby artifact holder (or any alien itemcontainer) and place the artifact inside it + //try to find an artifact holder and place the artifact inside it foreach (Item it in Item.ItemList) { - if (it.Submarine != null || !it.HasTag("alien")) continue; - - if (Math.Abs(item.WorldPosition.X - it.WorldPosition.X) > 2000.0f) continue; - if (Math.Abs(item.WorldPosition.Y - it.WorldPosition.Y) > 2000.0f) continue; + if (it.Submarine != null || !it.HasTag("artifactholder")) continue; var itemContainer = it.GetComponent(); if (itemContainer == null) continue; - - itemContainer.Combine(item); - break; + if (itemContainer.Combine(item)) break; // Placement successful } } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs index c48a54037..ea4b08005 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs @@ -146,6 +146,8 @@ namespace Barotrauma.Items.Components public override bool Select(Character character) { + if (item.Container != null) { return false; } + if (AutoInteractWithContained) { foreach (Item contained in Inventory.Items) @@ -262,35 +264,7 @@ namespace Barotrauma.Items.Components if (Screen.Selected == GameMain.SubEditorScreen && !Submarine.Unloading) { - string itemNames = string.Empty; - - foreach (Item item in Inventory.Items) - { - if (item == null) continue; - itemNames += item.Name + "\n"; - } - - if (itemNames.Length > 0) - { - var msgBox = new GUIMessageBox(Item.Name, TextManager.Get("DeletingContainerWithItems") + itemNames, new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); - msgBox.Buttons[0].OnClicked = (btn, userdata) => - { - Inventory.DeleteAllItems(); - msgBox.Close(); - return true; - }; - - msgBox.Buttons[1].OnClicked = (btn, userdata) => - { - foreach (Item item in Inventory.Items) - { - if (item == null) continue; - item.Drop(); - } - msgBox.Close(); - return true; - }; - } + GameMain.SubEditorScreen.HandleContainerContentsDeletion(Item, Inventory); return; } #endif diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs index 942fb9e0d..cee29a2fc 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs @@ -219,6 +219,9 @@ namespace Barotrauma.Items.Components { item.CreateServerEvent(this); RechargeSpeed = maxRechargeSpeed * 0.5f; +#if CLIENT + rechargeSpeedSlider.BarScroll = RechargeSpeed / Math.Max(maxRechargeSpeed, 1.0f); +#endif character.Speak(TextManager.Get("DialogChargeBatteries") .Replace("[itemname]", item.Name) .Replace("[rate]", ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString()), null, 1.0f, "chargebattery", 10.0f); @@ -230,6 +233,9 @@ namespace Barotrauma.Items.Components { item.CreateServerEvent(this); RechargeSpeed = 0.0f; +#if CLIENT + rechargeSpeedSlider.BarScroll = RechargeSpeed / Math.Max(maxRechargeSpeed, 1.0f); +#endif character.Speak(TextManager.Get("DialogStopChargingBatteries") .Replace("[itemname]", item.Name) .Replace("[rate]", ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString()), null, 1.0f, "chargebattery", 10.0f); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index f0d9813dc..dde5d29d1 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -262,6 +262,7 @@ namespace Barotrauma { ic.PlaySound(ActionType.OnBroken, WorldPosition); } + if (Screen.Selected == GameMain.SubEditorScreen) return; #endif ApplyStatusEffects(ActionType.OnBroken, 1.0f, null); } @@ -2251,11 +2252,14 @@ namespace Barotrauma element.Add(new XAttribute("condition", condition.ToString("G", CultureInfo.InvariantCulture))); } - System.Diagnostics.Debug.Assert(Submarine != null); + Item rootContainer = GetRootContainer() ?? this; + System.Diagnostics.Debug.Assert(Submarine != null || rootContainer.ParentInventory?.Owner is Character); + + Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition; element.Add(new XAttribute("rect", - (int)(rect.X - Submarine.HiddenSubPosition.X) + "," + - (int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," + + (int)(rect.X - subPosition.X) + "," + + (int)(rect.Y - subPosition.Y) + "," + rect.Width + "," + rect.Height)); if (linkedTo != null && linkedTo.Count > 0) @@ -2326,7 +2330,7 @@ namespace Barotrauma { if (Removed) { - DebugConsole.ThrowError("Attempting to remove an already removed item\n" + Environment.StackTrace); + DebugConsole.ThrowError("Attempting to remove an already removed item (" + Name + ")\n" + Environment.StackTrace); return; } DebugConsole.Log("Removing item " + Name + " (ID: " + ID + ")"); diff --git a/Barotrauma/BarotraumaShared/Source/Map/Entity.cs b/Barotrauma/BarotraumaShared/Source/Map/Entity.cs index 200086d18..93f941bc3 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Entity.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Entity.cs @@ -225,6 +225,7 @@ namespace Barotrauma dictionary.Clear(); Hull.EntityGrids.Clear(); + Spawner?.Reset(); } /// diff --git a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs index 56bc3dd94..b0b08bf46 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs @@ -22,6 +22,8 @@ namespace Barotrauma private Entity Submarine; + private bool removed; + #if CLIENT private List burnDecals = new List(); #endif @@ -150,7 +152,11 @@ namespace Barotrauma DamageCharacters(deltaTime); DamageItems(deltaTime); - if (hull.WaterVolume > 0.0f) HullWaterExtinguish(deltaTime); + if (hull.WaterVolume > 0.0f) + { + HullWaterExtinguish(deltaTime); + if (removed) { return; } + } hull.Oxygen -= size.X * deltaTime * OxygenConsumption; @@ -319,15 +325,16 @@ namespace Barotrauma public void Remove() { #if CLIENT - lightSource.Remove(); + lightSource?.Remove(); + lightSource = null; foreach (Decal d in burnDecals) { d.StopFadeIn(); } #endif - - hull.RemoveFire(this); + hull?.RemoveFire(this); + removed = true; } } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index 0f5496e93..5c8f95d58 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -906,10 +906,14 @@ namespace Barotrauma } } - while (FireSources.Count > fireSourceCount) + for (int i = FireSources.Count - 1; i >= fireSourceCount; i--) { - FireSources[FireSources.Count - 1].Remove(); - } + FireSources[i].Remove(); + if (i < FireSources.Count) + { + FireSources.RemoveAt(i); + } + } } public static Hull Load(XElement element, Submarine submarine) diff --git a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs index 4dc229269..c2c45befe 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs @@ -176,6 +176,12 @@ namespace Barotrauma } } + public void Reset() + { + removeQueue.Clear(); + spawnQueue.Clear(); + } + public void ServerWrite(Lidgren.Network.NetBuffer message, Client client, object[] extraData = null) { if (GameMain.Server == null) return; diff --git a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs index 8e3941738..cb76c4773 100644 --- a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs @@ -464,6 +464,11 @@ namespace Barotrauma if (item.HasTag(targetIdentifiers)) return true; if (targetIdentifiers.Any(id => id == item.Prefab.Identifier)) return true; } + else if (entity is ItemComponent itemComponent) + { + if (itemComponent.Item.HasTag(targetIdentifiers)) return true; + if (targetIdentifiers.Any(id => id == itemComponent.Item.Prefab.Identifier)) return true; + } else if (entity is Structure structure) { if (targetIdentifiers.Any(id => id == structure.Prefab.Identifier)) return true; diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index f8cc03e39..44d8c5e94 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ