From 6be757a45b7a65b422b538e962222fc2a6761920 Mon Sep 17 00:00:00 2001
From: Markus Isberg <3e849f2e5c@pm.me>
Date: Fri, 3 Jun 2022 22:29:04 +0900
Subject: [PATCH] Build 0.18.5.0
---
.../ClientSource/Characters/CharacterInfo.cs | 10 +-
.../Characters/CharacterNetworking.cs | 2 +
.../ClientSource/DebugConsole.cs | 4 +-
.../ClientSource/GUI/ChatBox.cs | 140 +++++++++++++++++-
.../ClientSource/GUI/ComponentStyle.cs | 4 +
.../BarotraumaClient/ClientSource/GUI/GUI.cs | 40 +++--
.../ClientSource/GUI/GUIButton.cs | 5 +
.../ClientSource/GUI/GUIDropDown.cs | 4 +
.../ClientSource/GUI/GUITextBox.cs | 5 +-
.../ClientSource/GUI/HUDLayoutSettings.cs | 13 +-
.../ClientSource/GUI/Store.cs | 2 +-
.../ClientSource/GUI/TabMenu.cs | 19 ++-
.../ClientSource/GUI/UISprite.cs | 6 +
.../BarotraumaClient/ClientSource/GameMain.cs | 6 +-
.../ClientSource/GameSession/CrewManager.cs | 42 +-----
.../GameModes/SinglePlayerCampaign.cs | 6 +-
.../ClientSource/Items/Components/Door.cs | 123 ++++++++-------
.../Items/Components/Holdable/IdCard.cs | 6 -
.../ClientSource/Map/Submarine.cs | 94 +++++++-----
.../ClientSource/Networking/ChatMessage.cs | 5 +-
.../ClientSource/Networking/GameClient.cs | 48 ++----
.../Networking/OrderChatMessage.cs | 6 +-
.../Networking/Voip/VoipCapture.cs | 17 +--
.../CampaignSetupUI/CampaignSetupUI.cs | 11 +-
.../ClientSource/Screens/GameScreen.cs | 55 ++++++-
.../ClientSource/Screens/NetLobbyScreen.cs | 7 +-
.../ClientSource/Screens/SubEditorScreen.cs | 14 +-
.../ClientSource/Settings/SettingsMenu.cs | 42 ++++--
.../ClientSource/Sounds/SoundManager.cs | 2 +-
.../BarotraumaClient/LinuxClient.csproj | 2 +-
Barotrauma/BarotraumaClient/MacClient.csproj | 2 +-
.../BarotraumaClient/WindowsClient.csproj | 2 +-
.../BarotraumaServer/LinuxServer.csproj | 2 +-
Barotrauma/BarotraumaServer/MacServer.csproj | 2 +-
.../ServerSource/Networking/ChatMessage.cs | 7 +-
.../ServerSource/Networking/GameServer.cs | 44 +++++-
.../Networking/OrderChatMessage.cs | 6 +-
.../BarotraumaServer/WindowsServer.csproj | 2 +-
.../Data/campaignsettings.xml | 4 +-
.../AI/Objectives/AIObjectiveCleanupItems.cs | 13 +-
.../AI/Objectives/AIObjectiveIdle.cs | 2 +-
.../AI/Objectives/AIObjectiveLoadItems.cs | 16 +-
.../AI/Objectives/AIObjectivePumpWater.cs | 18 ++-
.../AI/Objectives/AIObjectiveRepairItems.cs | 5 +-
.../SharedSource/Characters/CharacterInfo.cs | 9 +-
.../SharedSource/Characters/Jobs/JobPrefab.cs | 6 +-
.../Params/Ragdoll/RagdollParams.cs | 2 +-
.../ContentManagement/ContentFile/JobsFile.cs | 6 +-
.../BarotraumaShared/SharedSource/Enums.cs | 7 +
.../GameSession/GameModes/CampaignMode.cs | 11 +-
.../GameModes/CampaignModePresets.cs | 14 +-
.../SharedSource/InputType.cs | 5 +-
.../SharedSource/Items/Components/Door.cs | 6 +-
.../Items/Components/Holdable/Holdable.cs | 3 +
.../Items/Components/Holdable/Pickable.cs | 3 +-
.../Items/Components/Holdable/RepairTool.cs | 2 +-
.../Items/Components/ItemContainer.cs | 17 ++-
.../Items/Components/Machines/Controller.cs | 26 ++++
.../Items/Components/Power/Powered.cs | 4 +-
.../SharedSource/Items/Components/Wearable.cs | 2 -
.../SharedSource/Items/Item.cs | 67 +++++++--
.../Map/Creatures/BallastFloraBehavior.cs | 48 ++++--
.../SharedSource/Map/Levels/Level.cs | 11 +-
.../SharedSource/Map/MapEntity.cs | 14 ++
.../SharedSource/Map/Submarine.cs | 24 ++-
.../SharedSource/Networking/ChatMessage.cs | 2 +
.../SharedSource/PerformanceCounter.cs | 50 -------
.../SharedSource/Screens/GameScreen.cs | 18 +--
.../Serialization/SerializableProperty.cs | 7 +-
.../SharedSource/Settings/GameSettings.cs | 29 +++-
.../StatusEffects/StatusEffect.cs | 6 +-
Barotrauma/BarotraumaShared/changelog.txt | 44 +++++-
72 files changed, 869 insertions(+), 439 deletions(-)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs
index deca50826..305031f47 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs
@@ -266,7 +266,7 @@ namespace Barotrauma
disguisedSkinColor = idCard.StoredOwnerAppearance.SkinColor;
}
- partial void LoadAttachmentSprites(bool omitJob)
+ partial void LoadAttachmentSprites()
{
if (attachmentSprites == null)
{
@@ -280,14 +280,6 @@ namespace Barotrauma
Head.BeardElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Beard)));
Head.MoustacheElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Moustache)));
Head.HairElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Hair)));
- if (omitJob)
- {
- JobPrefab.NoJobElement?.GetChildElement("PortraitClothing")?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
- }
- else
- {
- Job?.Prefab.ClothingElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
- }
}
// Doesn't work if the head's source rect does not start at 0,0.
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
index 7fd2cfdc0..c78789db0 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
@@ -651,6 +651,8 @@ namespace Barotrauma
GameMain.LightManager.LosEnabled = true;
GameMain.LightManager.LosAlpha = 1f;
+ GameMain.NetLobbyScreen.CampaignCharacterDiscarded = false;
+
character.memInput.Clear();
character.memState.Clear();
character.memLocalState.Clear();
diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs
index c56a20796..b8cff8d92 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs
@@ -172,6 +172,7 @@ namespace Barotrauma
isOpen = false;
GUI.ForceMouseOn(null);
textBox.Deselect();
+ SoundPlayer.PlayUISound(GUISoundType.Select);
}
if (isOpen)
@@ -209,7 +210,7 @@ namespace Barotrauma
isOpen = !isOpen;
if (isOpen)
{
- textBox.Select();
+ textBox.Select(ignoreSelectSound: true);
AddToGUIUpdateList();
}
else
@@ -217,6 +218,7 @@ namespace Barotrauma
GUI.ForceMouseOn(null);
textBox.Deselect();
}
+ SoundPlayer.PlayUISound(GUISoundType.Select);
}
private static bool IsCommandPermitted(string command, GameClient client)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs
index 1a780c3ec..a6a44048a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs
@@ -81,6 +81,8 @@ namespace Barotrauma
public const int ToggleButtonWidthRaw = 30;
private int popupMessageOffset;
+ private GUIDropDown ChatModeDropDown { get; set; }
+
public ChatBox(GUIComponent parent, bool isSinglePlayer)
{
this.IsSinglePlayer = isSinglePlayer;
@@ -226,7 +228,53 @@ namespace Barotrauma
// ---------------------------------------------------------------------------------------------
- InputBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft),
+ var bottomContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft), isHorizontal: true)
+ {
+ Stretch = true
+ };
+
+ var dropdownRt = new RectTransform(new Vector2(0.1f, 1.0f), bottomContainer.RectTransform)
+ {
+ // The chat mode selection dropdown will take a maximum of 45% of the horizontal space
+ MaxSize = new Point((int)(0.45f * bottomContainer.RectTransform.NonScaledSize.X), int.MaxValue)
+ };
+ var chatModes = new ChatMode[] { ChatMode.Local, ChatMode.Radio };
+ ChatModeDropDown = new GUIDropDown(dropdownRt, elementCount: chatModes.Length, dropAbove: true)
+ {
+ OnSelected = (component, userdata) =>
+ {
+ GameMain.ActiveChatMode = (ChatMode)userdata;
+ if (InputBox != null && InputBox.Text.StartsWith(RadioChatString) && GameMain.ActiveChatMode == ChatMode.Local)
+ {
+ string text = InputBox.Text;
+ InputBox.Text = text.Remove(0, RadioChatString.Length);
+ }
+ return true;
+ }
+ };
+ float longestDropDownOption = 0.0f;
+ foreach (ChatMode mode in chatModes)
+ {
+ var text = TextManager.Get($"chatmode.{mode}");
+ ChatModeDropDown.AddItem(text, userData: mode);
+ if (ChatModeDropDown.ListBox.Content.GetChildByUserData(mode) is GUITextBlock textBlock)
+ {
+ if (textBlock.TextSize.X > longestDropDownOption)
+ {
+ longestDropDownOption = textBlock.TextSize.X;
+ }
+ }
+ }
+ ChatModeDropDown.SelectItem(GameMain.ActiveChatMode);
+
+ float minDropDownWidth = longestDropDownOption + ChatModeDropDown.Padding.X +
+ (ChatModeDropDown.DropDownIcon?.RectTransform.NonScaledSize.X ?? 0) +
+ (ChatModeDropDown.DropDownIcon?.RectTransform.AbsoluteOffset.X ?? 0) * 2;
+ ChatModeDropDown.RectTransform.MinSize = new Point(
+ Math.Max((int)minDropDownWidth, ChatModeDropDown.RectTransform.MinSize.X),
+ ChatModeDropDown.RectTransform.MinSize.Y);
+
+ InputBox = new GUITextBox(new RectTransform(new Vector2(0.9f, 1.0f), bottomContainer.RectTransform),
style: "ChatTextBox")
{
OverflowClip = true,
@@ -248,8 +296,6 @@ namespace Barotrauma
CloseAfterMessageSent = false;
}
}
-
- //gui.Text = "";
};
var chatSendButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.7f), InputBox.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleRight");
@@ -306,6 +352,10 @@ namespace Barotrauma
{
textColor = ChatMessage.MessageColor[(int)ChatMessageType.Private];
}
+ else if (GameMain.ActiveChatMode == ChatMode.Radio)
+ {
+ textColor = ChatMessage.MessageColor[(int)ChatMessageType.Radio];
+ }
else
{
textColor = ChatMessage.MessageColor[(int)ChatMessageType.Default];
@@ -550,6 +600,25 @@ namespace Barotrauma
showNewMessagesButton.Visible = false;
}
+ if (PlayerInput.KeyHit(InputType.ToggleChatMode) && GUI.KeyboardDispatcher.Subscriber == null && Screen.Selected == GameMain.GameScreen)
+ {
+ try
+ {
+ var mode = GameMain.ActiveChatMode switch
+ {
+ ChatMode.Local => ChatMode.Radio,
+ ChatMode.Radio => ChatMode.Local,
+ _ => throw new NotImplementedException()
+ };
+ ChatModeDropDown.SelectItem(mode);
+ // TODO: Play a sound?
+ }
+ catch (NotImplementedException)
+ {
+ DebugConsole.ThrowError($"Error toggling chat mode: not implemented for current mode \"{GameMain.ActiveChatMode}\"");
+ }
+ }
+
if (ToggleButton != null)
{
ToggleButton.Selected = ToggleOpen;
@@ -700,5 +769,70 @@ namespace Barotrauma
}
}
}
+
+ public void ApplySelectionInputs() => ApplySelectionInputs(InputBox, true, ChatKeyStates.GetChatKeyStates());
+
+ public struct ChatKeyStates
+ {
+ public bool ActiveChatKeyHit { get; set; }
+ public bool LocalChatKeyHit { get; set; }
+ public bool RadioChatKeyHit { get; set; }
+ public bool AnyHit => ActiveChatKeyHit || LocalChatKeyHit || RadioChatKeyHit;
+
+ private ChatKeyStates(bool active, bool local, bool radio)
+ {
+ ActiveChatKeyHit = active;
+ LocalChatKeyHit = local;
+ RadioChatKeyHit = radio;
+ }
+
+ public static ChatKeyStates GetChatKeyStates()
+ {
+ return new ChatKeyStates(PlayerInput.KeyHit(InputType.ActiveChat),
+ PlayerInput.KeyHit(InputType.Chat),
+ PlayerInput.KeyHit(InputType.RadioChat) && (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100));
+ }
+
+ public (bool active, bool local, bool radio) Deconstruct()
+ {
+ return (ActiveChatKeyHit, LocalChatKeyHit, RadioChatKeyHit);
+ }
+ }
+
+ public void ApplySelectionInputs(GUITextBox inputBox, bool selectInputBox, ChatKeyStates chatKeyStates)
+ {
+ inputBox ??= InputBox;
+ var (activeChatKeyHit, localChatKeyHit, radioChatKeyHit) = chatKeyStates.Deconstruct();
+ if (localChatKeyHit || (activeChatKeyHit && GameMain.ActiveChatMode == ChatMode.Local))
+ {
+ ChatModeDropDown.SelectItem(ChatMode.Local);
+ inputBox.AddToGUIUpdateList();
+ GUIFrame.Flash(Color.DarkGreen, 0.5f);
+ if (!ToggleOpen)
+ {
+ CloseAfterMessageSent = !ToggleOpen;
+ ToggleOpen = true;
+ }
+ if (selectInputBox)
+ {
+ inputBox.Select(inputBox.Text.Length);
+ }
+ }
+ else if (radioChatKeyHit || (activeChatKeyHit && GameMain.ActiveChatMode == ChatMode.Radio))
+ {
+ ChatModeDropDown.SelectItem(ChatMode.Radio);
+ inputBox.AddToGUIUpdateList();
+ GUIFrame.Flash(Color.YellowGreen, 0.5f);
+ if (!ToggleOpen)
+ {
+ CloseAfterMessageSent = !ToggleOpen;
+ ToggleOpen = true;
+ }
+ if (selectInputBox)
+ {
+ inputBox.Select(inputBox.Text.Length);
+ }
+ }
+ }
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs
index d5707afa4..9a33f0ce9 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs
@@ -183,6 +183,10 @@ namespace Barotrauma
Width = null;
Height = null;
GetSize(Element);
+ foreach (var childStyle in ChildStyles.Values)
+ {
+ childStyle.RefreshSize();
+ }
}
private void GetSize(XElement element)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs
index 251799b66..49f027c19 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs
@@ -356,7 +356,7 @@ namespace Barotrauma
GUIStyle.Green, Color.Black * 0.8f, font: GUIStyle.SmallFont);
y += yStep;
GameMain.PerformanceCounter.DrawTimeGraph.Draw(spriteBatch, new Rectangle((int)x, (int)y, 170, 50), color: GUIStyle.Green);
- y += yStep * 3;
+ y += yStep * 4;
DrawString(spriteBatch, new Vector2(x, y),
"Update - Avg: " + GameMain.PerformanceCounter.UpdateTimeGraph.Average().ToString("0.00") + " ms" +
@@ -364,39 +364,33 @@ namespace Barotrauma
Color.LightBlue, Color.Black * 0.8f, font: GUIStyle.SmallFont);
y += yStep;
GameMain.PerformanceCounter.UpdateTimeGraph.Draw(spriteBatch, new Rectangle((int)x, (int)y, 170, 50), color: Color.LightBlue);
- y += yStep * 3;
- foreach (string key in GameMain.PerformanceCounter.GetSavedIdentifiers)
+ y += yStep * 4;
+ foreach (string key in GameMain.PerformanceCounter.GetSavedIdentifiers.OrderBy(i => i))
{
float elapsedMillisecs = GameMain.PerformanceCounter.GetAverageElapsedMillisecs(key);
- DrawString(spriteBatch, new Vector2(x, y),
- key + ": " + elapsedMillisecs.ToString("0.00"),
- Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- y += yStep;
- foreach (string childKey in GameMain.PerformanceCounter.GetSavedPartialIdentifiers(key))
- {
- elapsedMillisecs = GameMain.PerformanceCounter.GetPartialAverageElapsedMillisecs(key, childKey);
- DrawString(spriteBatch, new Vector2(x + 15, y),
- childKey + ": " + elapsedMillisecs.ToString("0.00"),
- Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- y += yStep;
- }
- }
+ int categoryDepth = key.Count(c => c == ':');
+ //color the more fine-grained counters red more easily (ok for the whole Update to take a longer time than specific part of the update)
+ float runningSlowThreshold = 10.0f / categoryDepth;
+ DrawString(spriteBatch, new Vector2(x + categoryDepth * 15, y),
+ key.Split(':').Last() + ": " + elapsedMillisecs.ToString("0.00"),
+ ToolBox.GradientLerp(elapsedMillisecs / runningSlowThreshold, Color.LightGreen, GUIStyle.Yellow, GUIStyle.Orange, GUIStyle.Red, Color.Magenta), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ y += yStep;
+ }
if (Powered.Grids != null)
{
DrawString(spriteBatch, new Vector2(x, y), "Grids: " + Powered.Grids.Count, Color.LightGreen, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
y += yStep;
}
-
if (Settings.EnableDiagnostics)
{
x += yStep * 2;
- DrawString(spriteBatch, new Vector2(x, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- DrawString(spriteBatch, new Vector2(x, y + yStep), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- DrawString(spriteBatch, new Vector2(x, y + yStep * 2), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- DrawString(spriteBatch, new Vector2(x, y + yStep * 3), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- DrawString(spriteBatch, new Vector2(x, y + yStep * 4), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
- DrawString(spriteBatch, new Vector2(x, y + yStep * 5), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y + yStep), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y + yStep * 2), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y + yStep * 3), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y + yStep * 4), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
+ DrawString(spriteBatch, new Vector2(x, y + yStep * 5), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs
index 09e8107b1..a824218e5 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs
@@ -111,6 +111,11 @@ namespace Barotrauma
set { textBlock.SelectedTextColor = value; }
}
+ public Color DisabledTextColor
+ {
+ get { return textBlock.DisabledTextColor; }
+ }
+
public override float FlashTimer
{
get { return Frame.FlashTimer; }
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs
index 389456b9a..f8e908d8d 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs
@@ -160,6 +160,10 @@ namespace Barotrauma
listBox.ToolTip = value;
}
}
+
+ public GUIImage DropDownIcon => icon;
+
+ public Vector4 Padding => button.TextBlock.Padding;
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false, Alignment textAlignment = Alignment.CenterLeft) : base(style, rectT)
{
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs
index fcbf3a5f4..866214dd6 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs
@@ -352,7 +352,7 @@ namespace Barotrauma
caretPosDirty = false;
}
- public void Select(int forcedCaretIndex = -1)
+ public void Select(int forcedCaretIndex = -1, bool ignoreSelectSound = false)
{
skipUpdate = true;
if (memento.Current == null)
@@ -362,10 +362,11 @@ namespace Barotrauma
CaretIndex = forcedCaretIndex == - 1 ? textBlock.GetCaretIndexFromScreenPos(PlayerInput.MousePosition) : forcedCaretIndex;
CalculateCaretPos();
ClearSelection();
+ bool wasSelected = selected;
selected = true;
GUI.KeyboardDispatcher.Subscriber = this;
OnSelected?.Invoke(this, Keys.None);
- if (PlaySoundOnSelect)
+ if (!wasSelected && PlaySoundOnSelect && !ignoreSelectSound)
{
SoundPlayer.PlayUISound(GUISoundType.Select);
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs
index f255c8f5c..7afce155d 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
+using System.Linq;
namespace Barotrauma
{
@@ -122,7 +123,17 @@ namespace Barotrauma
//horizontal slices at the corners of the screen for health bar and affliction icons
int afflictionAreaHeight = (int)(50 * GUI.Scale);
- int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.3f);
+ int healthBarWidth = BottomRightInfoArea.Width;
+
+ var healthBarChildStyles = GUIStyle.GetComponentStyle("CharacterHealthBar")?.ChildStyles;
+ if (healthBarChildStyles!= null && healthBarChildStyles.TryGetValue("GUIFrame".ToIdentifier(), out var style))
+ {
+ if (style.Sprites.TryGetValue(GUIComponent.ComponentState.None, out var uiSprites) && uiSprites.FirstOrDefault() is { } uiSprite)
+ {
+ // The default health bar uses a sliced sprite so let's make sure the health bar area is calculated accordingly
+ healthBarWidth += (int)(uiSprite.NonSliceSize.X * Math.Min(GUI.Scale, 1f));
+ }
+ }
int healthBarHeight = (int)(50f * GUI.Scale);
HealthBarArea = new Rectangle(BottomRightInfoArea.Right - healthBarWidth + (int)Math.Floor(1 / GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + GUI.IntScale(10), healthBarWidth, healthBarHeight);
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs
index 105bd7a07..f27eed481 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs
@@ -2208,7 +2208,7 @@ namespace Barotrauma
}
updateStopwatch.Stop();
- GameMain.PerformanceCounter.AddPartialElapsedTicks("GameSessionUpdate", "StoreUpdate", updateStopwatch.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession:Store", updateStopwatch.ElapsedTicks);
}
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs
index cbf116f0b..47752417d 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs
@@ -1858,14 +1858,18 @@ namespace Barotrauma
});
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f };
-
+
Vector2 nameSize = GUIStyle.SubHeadingFont.MeasureString(info.Name);
- GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont) { TextColor = job.Prefab.UIColor };
+ GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont);
nameBlock.RectTransform.NonScaledSize = nameSize.Pad(nameBlock.Padding).ToPoint();
- Vector2 jobSize = GUIStyle.SmallFont.MeasureString(job.Name);
- GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor };
- jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
+ if (!info.OmitJobInMenus)
+ {
+ nameBlock.TextColor = job.Prefab.UIColor;
+ Vector2 jobSize = GUIStyle.SmallFont.MeasureString(job.Name);
+ GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor };
+ jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
+ }
LocalizedString traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + info.PersonalityTrait.Name.Replace(" ", "")));
Vector2 traitSize = GUIStyle.SmallFont.MeasureString(traitString);
@@ -1876,7 +1880,8 @@ namespace Barotrauma
if (!(GameMain.NetworkMember is null))
{
- GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), talentsOutsideTreeFrame.RectTransform, Anchor.TopLeft), text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
+ GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), talentsOutsideTreeFrame.RectTransform, Anchor.TopLeft),
+ text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
{
IgnoreLayoutGroups = true
};
@@ -1915,7 +1920,7 @@ namespace Barotrauma
{
OnClicked = (button, o) =>
{
- GameMain.Client?.SendCharacterInfo();
+ GameMain.Client?.SendCharacterInfo(GameMain.Client.PendingName);
characterSettingsFrame!.Visible = false;
talentFrameMain.Visible = true;
return true;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs
index 54c5ee076..fc8dfd1f5 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs
@@ -27,6 +27,11 @@ namespace Barotrauma
set;
}
+ ///
+ /// The size of fixed area around the slice area
+ ///
+ public Point NonSliceSize { get; set; }
+
public bool MaintainAspectRatio
{
get;
@@ -72,6 +77,7 @@ namespace Barotrauma
maxBorderScale = element.GetAttributeFloat("minborderscale", 10.0f);
Rectangle slice = new Rectangle((int)sliceVec.X, (int)sliceVec.Y, (int)(sliceVec.Z - sliceVec.X), (int)(sliceVec.W - sliceVec.Y));
+ NonSliceSize = new Point(Sprite.SourceRect.Width - slice.Width, Sprite.SourceRect.Height - slice.Height);
Slices = new Rectangle[9];
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs
index 01b319c25..7f55a1968 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs
@@ -202,6 +202,8 @@ namespace Barotrauma
public static bool CancelQuickStart;
#endif
+ public static ChatMode ActiveChatMode { get; set; } = ChatMode.Radio;
+
public GameMain(string[] args)
{
Content.RootDirectory = "Content";
@@ -924,7 +926,7 @@ namespace Barotrauma
updateCount++;
sw.Stop();
- PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks);
+ PerformanceCounter.AddElapsedTicks("Update", sw.ElapsedTicks);
PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
}
@@ -1026,7 +1028,7 @@ namespace Barotrauma
}
sw.Stop();
- PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
+ PerformanceCounter.AddElapsedTicks("Draw", sw.ElapsedTicks);
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs
index 52fa7e3cd..a4f756646 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs
@@ -147,9 +147,10 @@ namespace Barotrauma
string msgCommand = ChatMessage.GetChatMessageCommand(text, out string msg);
// add to local history
ChatBox.ChatManager.Store(text);
- WifiComponent headset = null;
- ChatMessageType messageType =
- ((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled, out headset)) ? ChatMessageType.Radio : ChatMessageType.Default;
+ bool isUsingRadioMode = GameMain.ActiveChatMode == ChatMode.Radio;
+ bool containsRadioCommand = msgCommand == "r" || msgCommand == "radio";
+ bool canUseRadio = ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent headset);
+ ChatMessageType messageType = ((isUsingRadioMode && msgCommand == "") || containsRadioCommand) && canUseRadio ? ChatMessageType.Radio : ChatMessageType.Default;
AddSinglePlayerChatMessage(
Character.Controlled.Info.Name,
msg, messageType,
@@ -1553,40 +1554,9 @@ namespace Barotrauma
{
ChatBox.Update(deltaTime);
ChatBox.InputBox.Visible = Character.Controlled != null;
-
- if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible && GUI.KeyboardDispatcher.Subscriber == null)
+ if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible && GUI.KeyboardDispatcher.Subscriber == null && !ChatBox.InputBox.Selected)
{
- if (PlayerInput.KeyHit(InputType.Chat) && !ChatBox.InputBox.Selected)
- {
- ChatBox.InputBox.AddToGUIUpdateList();
- ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
- if (!ChatBox.ToggleOpen)
- {
- ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
- ChatBox.ToggleOpen = true;
- }
- ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length);
- }
-
- if (PlayerInput.KeyHit(InputType.RadioChat) && !ChatBox.InputBox.Selected)
- {
- if (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100)
- {
- ChatBox.InputBox.AddToGUIUpdateList();
- ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
- if (!ChatBox.ToggleOpen)
- {
- ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
- ChatBox.ToggleOpen = true;
- }
-
- if (!ChatBox.InputBox.Text.StartsWith(ChatBox.RadioChatString))
- {
- ChatBox.InputBox.Text = ChatBox.RadioChatString;
- }
- ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length);
- }
- }
+ ChatBox.ApplySelectionInputs();
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs
index ed5e25c86..065bfeb8a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs
@@ -35,11 +35,7 @@ namespace Barotrauma
}
}
- if (CrewManager.ChatBox != null)
- {
- CrewManager.ChatBox.Update(deltaTime);
- }
-
+ CrewManager.ChatBox?.Update(deltaTime);
CrewManager.UpdateReports();
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs
index 9ea53f8da..3d3070aef 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs
@@ -43,6 +43,31 @@ namespace Barotrauma.Items.Components
corners[2] = center + new Vector2(shadowSize.X, shadowSize.Y) / 2;
corners[3] = center + new Vector2(shadowSize.X, -shadowSize.Y) / 2;
+ if (IsHorizontal)
+ {
+ if (item.FlippedX)
+ {
+ Vector2 itemCenter = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2);
+ for (int i = 0; i < corners.Length; i++)
+ {
+ corners[i].X = itemCenter.X * 2 - corners[i].X;
+ }
+ Array.Reverse(corners);
+ }
+ }
+ else
+ {
+ if (item.FlippedY)
+ {
+ Vector2 itemCenter = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2);
+ for (int i = 0; i < corners.Length; i++)
+ {
+ corners[i].Y = itemCenter.Y * 2 - corners[i].Y;
+ }
+ Array.Reverse(corners);
+ }
+ }
+
return corners;
}
@@ -163,69 +188,67 @@ namespace Barotrauma.Items.Components
if (stuck > 0.0f && weldedSprite != null)
{
Vector2 weldSpritePos = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2.0f) + shakePos;
- if (item.Submarine != null) weldSpritePos += item.Submarine.DrawPosition;
+ if (item.Submarine != null) { weldSpritePos += item.Submarine.DrawPosition; }
weldSpritePos.Y = -weldSpritePos.Y;
weldedSprite.Draw(spriteBatch,
weldSpritePos, item.SpriteColor * (stuck / 100.0f), scale: item.Scale);
}
- if (openState >= 1.0f)
- {
- return;
- }
+ if (openState >= 1.0f) { return; }
+ Vector2 pos;
if (IsHorizontal)
{
- Vector2 pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2) + shakePos;
- if (item.Submarine != null) pos += item.Submarine.DrawPosition;
- pos.Y = -pos.Y;
-
- if (brokenSprite == null || !IsBroken)
- {
- spriteBatch.Draw(doorSprite.Texture, pos,
- new Rectangle((int) (doorSprite.SourceRect.X + doorSprite.size.X * openState),
- (int) doorSprite.SourceRect.Y,
- (int) (doorSprite.size.X * (1.0f - openState)), (int) doorSprite.size.Y),
- color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
- }
-
- if (brokenSprite != null && item.Health < item.MaxCondition)
- {
- Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.MaxCondition) : Vector2.One;
- float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
- spriteBatch.Draw(brokenSprite.Texture, pos,
- new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y,
- (int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y),
- color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None,
- brokenSprite.Depth);
- }
+ pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2);
+ if (item.FlippedX) { pos.X += (int)(doorSprite.size.X * item.Scale * openState); }
}
else
{
- Vector2 pos = new Vector2(item.Rect.Center.X, item.Rect.Y) + shakePos;
- if (item.Submarine != null) pos += item.Submarine.DrawPosition;
- pos.Y = -pos.Y;
-
- if (brokenSprite == null || !IsBroken)
- {
- spriteBatch.Draw(doorSprite.Texture, pos,
- new Rectangle(doorSprite.SourceRect.X,
- (int) (doorSprite.SourceRect.Y + doorSprite.size.Y * openState),
- (int) doorSprite.size.X, (int) (doorSprite.size.Y * (1.0f - openState))),
- color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
- }
-
- if (brokenSprite != null && item.Health < item.MaxCondition)
- {
- Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.MaxCondition, 1.0f) : Vector2.One;
- float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
- spriteBatch.Draw(brokenSprite.Texture, pos,
- new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState),
- (int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
- color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None, brokenSprite.Depth);
- }
+ pos = new Vector2(item.Rect.Center.X, item.Rect.Y);
+ if (item.FlippedY) { pos.Y -= (int)(doorSprite.size.Y * item.Scale * openState); }
}
+
+ pos += shakePos;
+ if (item.Submarine != null) { pos += item.Submarine.DrawPosition; }
+ pos.Y = -pos.Y;
+
+ if (brokenSprite == null || !IsBroken)
+ {
+ spriteBatch.Draw(doorSprite.Texture, pos,
+ getSourceRect(doorSprite, openState, IsHorizontal),
+ color, 0.0f, doorSprite.Origin, item.Scale, item.SpriteEffects, doorSprite.Depth);
+ }
+
+ if (brokenSprite != null && item.Health < item.MaxCondition)
+ {
+ Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.MaxCondition) : Vector2.One;
+ float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
+ spriteBatch.Draw(brokenSprite.Texture, pos,
+ getSourceRect(brokenSprite, openState, IsHorizontal),
+ color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, item.SpriteEffects,
+ brokenSprite.Depth);
+ }
+
+ static Rectangle getSourceRect(Sprite sprite, float openState, bool horizontal)
+ {
+ if (horizontal)
+ {
+ return new Rectangle(
+ (int)(sprite.SourceRect.X + sprite.size.X * openState),
+ sprite.SourceRect.Y,
+ (int)(sprite.size.X * (1.0f - openState)),
+ (int)sprite.size.Y);
+ }
+ else
+ {
+ return new Rectangle(
+ sprite.SourceRect.X,
+ (int)(sprite.SourceRect.Y + sprite.size.Y * openState),
+ (int)sprite.size.X,
+ (int)(sprite.size.Y * (1.0f - openState)));
+ }
+ }
}
partial void OnFailedToOpen()
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs
index 23083323d..bd2b6da47 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/IdCard.cs
@@ -116,12 +116,6 @@ namespace Barotrauma.Items.Components
loadAttachments(Attachments, disguisedBeardElement, WearableType.Beard);
loadAttachments(Attachments, disguisedMoustacheElement, WearableType.Moustache);
loadAttachments(Attachments, disguisedHairElement, WearableType.Hair);
-
- loadAttachments(Attachments,
- characterInfo.OmitJobInPortraitClothing
- ? JobPrefab.NoJobElement?.GetChildElement("PortraitClothing")
- : JobPrefab?.ClothingElement,
- WearableType.JobIndicator);
}
HairColor = hairColor;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs
index 45218c779..44c3c5e92 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs
@@ -1,55 +1,61 @@
-using Barotrauma.Networking;
-using Barotrauma.RuinGeneration;
-using Barotrauma.Sounds;
+using Barotrauma.Items.Components;
+using Barotrauma.Networking;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
-using Barotrauma.IO;
using System.Linq;
-using System.Xml.Linq;
-using Barotrauma.Items.Components;
namespace Barotrauma
{
partial class Submarine : Entity, IServerPositionSync
{
- public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
- {
- Vector2 position = PlayerInput.MousePosition;
- position = cam.ScreenToWorld(position);
-
- Vector2 worldGridPos = VectorToWorldGrid(position);
-
- if (sub != null)
- {
- worldGridPos.X += sub.Position.X % GridSize.X;
- worldGridPos.Y += sub.Position.Y % GridSize.Y;
- }
-
- return worldGridPos;
- }
-
//drawing ----------------------------------------------------
private static readonly HashSet visibleSubs = new HashSet();
+
+ private static double prevCullTime;
+ private static Rectangle prevCullArea;
+ ///
+ /// Interval at which we force culled entites to be updated, regardless if the camera has moved
+ ///
+ private const float CullInterval = 0.25f;
+ ///
+ /// Margin applied around the view area when culling entities (i.e. entities that are this far outside the view are still considered visible)
+ ///
+ private const int CullMargin = 500;
+ ///
+ /// Update entity culling when any corner of the view has moved more than this
+ ///
+ private const int CullMoveThreshold = 50;
+
public static void CullEntities(Camera cam)
{
+ Rectangle camView = cam.WorldView;
+ camView = new Rectangle(camView.X - CullMargin, camView.Y + CullMargin, camView.Width + CullMargin * 2, camView.Height + CullMargin * 2);
+
+ if (Math.Abs(camView.X - prevCullArea.X) < CullMoveThreshold &&
+ Math.Abs(camView.Y - prevCullArea.Y) < CullMoveThreshold &&
+ Math.Abs(camView.Right - prevCullArea.Right) < CullMoveThreshold &&
+ Math.Abs(camView.Bottom - prevCullArea.Bottom) < CullMoveThreshold &&
+ prevCullTime > Timing.TotalTime - CullInterval)
+ {
+ return;
+ }
+
visibleSubs.Clear();
foreach (Submarine sub in Loaded)
{
if (Level.Loaded != null && sub.WorldPosition.Y < Level.MaxEntityDepth) { continue; }
- int margin = 500;
Rectangle worldBorders = new Rectangle(
- sub.VisibleBorders.X + (int)sub.WorldPosition.X - margin,
- sub.VisibleBorders.Y + (int)sub.WorldPosition.Y + margin,
- sub.VisibleBorders.Width + margin * 2,
- sub.VisibleBorders.Height + margin * 2);
+ sub.VisibleBorders.X + (int)sub.WorldPosition.X,
+ sub.VisibleBorders.Y + (int)sub.WorldPosition.Y,
+ sub.VisibleBorders.Width,
+ sub.VisibleBorders.Height);
- if (RectsOverlap(worldBorders, cam.WorldView))
+ if (RectsOverlap(worldBorders, camView))
{
visibleSubs.Add(sub);
}
@@ -64,16 +70,22 @@ namespace Barotrauma
visibleEntities.Clear();
}
- Rectangle worldView = cam.WorldView;
foreach (MapEntity entity in MapEntity.mapEntityList)
{
if (entity.Submarine != null)
{
if (!visibleSubs.Contains(entity.Submarine)) { continue; }
}
-
- if (entity.IsVisible(worldView)) { visibleEntities.Add(entity); }
+ if (entity.IsVisible(camView)) { visibleEntities.Add(entity); }
}
+
+ prevCullArea = camView;
+ prevCullTime = Timing.TotalTime;
+ }
+
+ public static void ForceVisibilityRecheck()
+ {
+ prevCullTime = 0;
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
@@ -148,7 +160,7 @@ namespace Barotrauma
{
if (predicate != null)
{
- if (!predicate(e)) continue;
+ if (!predicate(e)) { continue; }
}
float drawDepth = structure.GetDrawDepth();
int i = 0;
@@ -679,6 +691,22 @@ namespace Barotrauma
return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
}
+ public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
+ {
+ Vector2 position = PlayerInput.MousePosition;
+ position = cam.ScreenToWorld(position);
+
+ Vector2 worldGridPos = VectorToWorldGrid(position);
+
+ if (sub != null)
+ {
+ worldGridPos.X += sub.Position.X % GridSize.X;
+ worldGridPos.Y += sub.Position.Y % GridSize.Y;
+ }
+
+ return worldGridPos;
+ }
+
public void ClientReadPosition(IReadMessage msg, float sendingTime)
{
var posInfo = PhysicsBody.ClientRead(msg, sendingTime, parentDebugName: Info.Name);
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs
index 5e22aaa33..a020b263a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChatMessage.cs
@@ -10,14 +10,15 @@ namespace Barotrauma.Networking
{
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
msg.Write(NetStateID);
- msg.Write((byte)Type);
+ msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
+ msg.WriteRangedInteger((int)ChatMode, 0, Enum.GetValues(typeof(ChatMode)).Length - 1);
msg.Write(Text);
}
public static void ClientRead(IReadMessage msg)
{
UInt16 id = msg.ReadUInt16();
- ChatMessageType type = (ChatMessageType)msg.ReadByte();
+ ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None;
string txt = "";
string styleSetting = string.Empty;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
index 797640696..4409512fb 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
@@ -1831,7 +1831,8 @@ namespace Barotrauma.Networking
GameMain.GameScreen.Select();
- AddChatMessage($"ServerMessage.HowToCommunicate~[chatbutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Chat)}~[radiobutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.RadioChat)}", ChatMessageType.Server);
+ // TODO: Re-enable the server message once it's been edited and translated
+ //AddChatMessage($"ServerMessage.HowToCommunicate~[chatbutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Chat)}~[radiobutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.RadioChat)}", ChatMessageType.Server);
yield return CoroutineStatus.Success;
}
@@ -2503,6 +2504,7 @@ namespace Barotrauma.Networking
message,
type,
gameStarted && myCharacter != null ? myCharacter : null);
+ chatMessage.ChatMode = GameMain.ActiveChatMode;
lastQueueChatMsgID++;
chatMessage.NetStateID = lastQueueChatMsgID;
@@ -2788,19 +2790,21 @@ namespace Barotrauma.Networking
GameMain.GameSession = null;
}
- public void SendCharacterInfo()
+ public void SendCharacterInfo(string newName = null)
{
IWriteMessage msg = new WriteOnlyMessage();
msg.Write((byte)ClientPacketHeader.UPDATE_CHARACTERINFO);
- WriteCharacterInfo(msg);
+ WriteCharacterInfo(msg, newName);
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
clientPeer?.Send(msg, DeliveryMethod.Reliable);
}
- public void WriteCharacterInfo(IWriteMessage msg)
+ public void WriteCharacterInfo(IWriteMessage msg, string newName = null)
{
msg.Write(characterInfo == null);
- if (characterInfo == null) return;
+ if (characterInfo == null) { return; }
+
+ msg.Write(newName ?? string.Empty);
msg.Write((byte)characterInfo.Head.Preset.TagSet.Count);
foreach (Identifier tag in characterInfo.Head.Preset.TagSet)
@@ -3284,10 +3288,8 @@ namespace Barotrauma.Networking
{
if (GUI.KeyboardDispatcher.Subscriber == null)
{
- bool chatKeyHit = PlayerInput.KeyHit(InputType.Chat);
- bool radioKeyHit = PlayerInput.KeyHit(InputType.RadioChat) && (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100);
-
- if (chatKeyHit || radioKeyHit)
+ var chatKeyStates = ChatBox.ChatKeyStates.GetChatKeyStates();
+ if (chatKeyStates.AnyHit)
{
if (msgBox.Selected)
{
@@ -3298,34 +3300,8 @@ namespace Barotrauma.Networking
{
if (Screen.Selected == GameMain.GameScreen)
{
- if (chatKeyHit)
- {
- msgBox.AddToGUIUpdateList();
- ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
- if (!chatBox.ToggleOpen)
- {
- ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
- ChatBox.ToggleOpen = true;
- }
- }
-
- if (radioKeyHit)
- {
- msgBox.AddToGUIUpdateList();
- ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
- if (!chatBox.ToggleOpen)
- {
- ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
- ChatBox.ToggleOpen = true;
- }
-
- if (!msgBox.Text.StartsWith(ChatBox.RadioChatString))
- {
- msgBox.Text = ChatBox.RadioChatString;
- }
- }
+ ChatBox.ApplySelectionInputs(msgBox, false, chatKeyStates);
}
-
msgBox.Select(msgBox.Text.Length);
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs
index 82ce2130f..1134f3aa0 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/OrderChatMessage.cs
@@ -1,4 +1,6 @@
-namespace Barotrauma.Networking
+using System;
+
+namespace Barotrauma.Networking
{
partial class OrderChatMessage : ChatMessage
{
@@ -6,7 +8,7 @@
{
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
msg.Write(NetStateID);
- msg.Write((byte)ChatMessageType.Order);
+ msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
WriteOrder(msg);
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs
index cf2caabed..f1c611704 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipCapture.cs
@@ -227,20 +227,10 @@ namespace Barotrauma.Networking
bool allowEnqueue = overrideSound != null;
if (GameMain.WindowActive && SettingsMenu.Instance is null)
{
- ForceLocal = captureTimer > 0 ? ForceLocal : GameSettings.CurrentConfig.Audio.UseLocalVoiceByDefault;
- bool pttDown = false;
- if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
- GUI.KeyboardDispatcher.Subscriber == null)
+ bool pttDown = PlayerInput.KeyDown(InputType.Voice) && GUI.KeyboardDispatcher.Subscriber == null;
+ if (pttDown || captureTimer <= 0)
{
- pttDown = true;
- if (PlayerInput.KeyDown(InputType.LocalVoice))
- {
- ForceLocal = true;
- }
- else
- {
- ForceLocal = false;
- }
+ ForceLocal = GameMain.ActiveChatMode == ChatMode.Local;
}
if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Activity)
{
@@ -257,7 +247,6 @@ namespace Barotrauma.Networking
}
}
}
-
if (allowEnqueue || captureTimer > 0)
{
LastEnqueueAudio = DateTime.Now;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs
index 38cda4a69..7bfeb7275 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI/CampaignSetupUI.cs
@@ -205,7 +205,10 @@ namespace Barotrauma
SettingCarouselElement prevDifficulty = difficultyOptions.FirstOrNull(element => element.Value == prevSettings.Difficulty) ?? difficultyOptions[1];
SettingValue difficultyInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("leveldifficulty"), TextManager.Get("leveldifficultyexplanation"), prevDifficulty, verticalSize, difficultyOptions);
- SettingValue maxMissionCountInput = CreateGUINumberInputCarousel(settingsList.Content, TextManager.Get("maxmissioncount"), TextManager.Get("maxmissioncounttooltip"), prevSettings.MaxMissionCount, valueStep: 1, verticalSize);
+ SettingValue maxMissionCountInput = CreateGUINumberInputCarousel(settingsList.Content, TextManager.Get("maxmissioncount"), TextManager.Get("maxmissioncounttooltip"),
+ prevSettings.MaxMissionCount,
+ valueStep: 1, minValue: CampaignSettings.MinMissionCountLimit, maxValue: CampaignSettings.MaxMissionCountLimit,
+ verticalSize);
presetDropdown.OnSelected = (selected, o) =>
{
@@ -231,7 +234,7 @@ namespace Barotrauma
};
// Create a number input with plus and minus buttons because for some reason the default GUINumberInput buttons don't work when in a GUIMessageBox
- static SettingValue CreateGUINumberInputCarousel(GUIComponent parent, LocalizedString description, LocalizedString tooltip, int defaultValue, int valueStep, float verticalSize)
+ static SettingValue CreateGUINumberInputCarousel(GUIComponent parent, LocalizedString description, LocalizedString tooltip, int defaultValue, int valueStep, int minValue, int maxValue, float verticalSize)
{
GUILayoutGroup inputContainer = CreateSettingBase(parent, description, tooltip, horizontalSize: 0.55f, verticalSize: verticalSize);
@@ -243,7 +246,9 @@ namespace Barotrauma
GUINumberInput numberInput = new GUINumberInput(new RectTransform(Vector2.One, inputContainer.RectTransform, Anchor.Center), NumberType.Int, textAlignment: Alignment.Center, style: "GUITextBox",
hidePlusMinusButtons: true)
{
- IntValue = defaultValue
+ IntValue = defaultValue,
+ MinValueInt = minValue,
+ MaxValueInt = maxValue
};
inputContainer.RectTransform.Parent.MinSize = new Point(0, numberInput.RectTransform.MinSize.Y);
GUIButton plusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs
index 4efe53c5c..f3783a78a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs
@@ -126,7 +126,7 @@ namespace Barotrauma
DrawMap(graphics, spriteBatch, deltaTime);
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("DrawMap", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map", sw.ElapsedTicks);
sw.Restart();
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
@@ -165,7 +165,7 @@ namespace Barotrauma
spriteBatch.End();
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("DrawHUD", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:HUD", sw.ElapsedTicks);
sw.Restart();
}
@@ -178,6 +178,9 @@ namespace Barotrauma
GameMain.ParticleManager.UpdateTransforms();
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+
GameMain.LightManager.ObstructVision =
Character.Controlled != null &&
Character.Controlled.ObstructVision &&
@@ -185,6 +188,10 @@ namespace Barotrauma
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled?.CursorWorldPosition ?? Vector2.Zero);
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:LOS", sw.ElapsedTicks);
+ sw.Restart();
+
//------------------------------------------------------------------------
graphics.SetRenderTarget(renderTarget);
graphics.Clear(Color.Transparent);
@@ -196,9 +203,17 @@ namespace Barotrauma
Submarine.DrawPaintedColors(spriteBatch, false);
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackStructures", sw.ElapsedTicks);
+ sw.Restart();
+
graphics.SetRenderTarget(null);
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam, renderTarget);
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:Lighting", sw.ElapsedTicks);
+ sw.Restart();
+
//------------------------------------------------------------------------
graphics.SetRenderTarget(renderTargetBackground);
if (Level.Loaded == null)
@@ -228,6 +243,10 @@ namespace Barotrauma
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackLevel", sw.ElapsedTicks);
+ sw.Restart();
+
//----------------------------------------------------------------------------
//Start drawing to the normal render target (stuff that can't be seen through the LOS effect)
@@ -248,6 +267,10 @@ namespace Barotrauma
}
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackCharactersItems", sw.ElapsedTicks);
+ sw.Restart();
+
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
DrawDeformed(firstPass: true);
DrawDeformed(firstPass: false);
@@ -266,8 +289,16 @@ namespace Barotrauma
}
}
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:DeformableCharacters", sw.ElapsedTicks);
+ sw.Restart();
+
Level.Loaded?.DrawFront(spriteBatch, cam);
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontLevel", sw.ElapsedTicks);
+ sw.Restart();
+
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
graphics.SetRenderTarget(renderTargetWater);
@@ -302,6 +333,10 @@ namespace Barotrauma
WaterRenderer.Instance.RenderAir(graphics, cam, renderTarget, Cam.ShaderTransform);
graphics.DepthStencilState = DepthStencilState.None;
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontParticles", sw.ElapsedTicks);
+ sw.Restart();
+
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.NonPremultiplied, SamplerState.LinearWrap,
null, null,
@@ -310,10 +345,18 @@ namespace Barotrauma
Submarine.DrawDamageable(spriteBatch, damageEffect, false);
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontDamageable", sw.ElapsedTicks);
+ sw.Restart();
+
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
Submarine.DrawFront(spriteBatch, false, null);
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontStructuresItems", sw.ElapsedTicks);
+ sw.Restart();
+
//draw additive particles that are inside a sub
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
@@ -349,6 +392,10 @@ namespace Barotrauma
}
spriteBatch.End();
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontMisc", sw.ElapsedTicks);
+ sw.Restart();
+
if (GameMain.LightManager.LosEnabled && GameMain.LightManager.LosMode != LosMode.None && Lights.LightManager.ViewTarget != null)
{
GameMain.LightManager.LosEffect.CurrentTechnique = GameMain.LightManager.LosEffect.Techniques["LosShader"];
@@ -457,6 +504,10 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Lerp(Color.TransparentBlack, Color.Black, fadeToBlackState), isFilled: true);
spriteBatch.End();
}
+
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:PostProcess", sw.ElapsedTicks);
+ sw.Restart();
}
partial void UpdateProjSpecific(double deltaTime)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
index 1c21c6f27..4bf99f6d8 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
@@ -110,7 +110,7 @@ namespace Barotrauma
public bool CampaignCharacterDiscarded
{
get;
- private set;
+ set;
}
//elements that can only be used by the host
@@ -1253,9 +1253,6 @@ namespace Barotrauma
CharacterAppearanceCustomizationMenu?.Dispose();
JobSelectionFrame = null;
-
- /*foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); }
- jobPreferenceSprites.Clear();*/
}
public override void Select()
@@ -1417,7 +1414,7 @@ namespace Barotrauma
characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, GameMain.Client.Name, null);
characterInfo.RecreateHead(MultiplayerPreferences.Instance);
GameMain.Client.CharacterInfo = characterInfo;
- characterInfo.OmitJobInPortraitClothing = false;
+ characterInfo.OmitJobInMenus = true;
}
parent.ClearChildren();
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
index a702a3d4d..442ea1bae 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
@@ -1870,7 +1870,8 @@ namespace Barotrauma
}
addSubAndSaveModProject(modProject, savePath, fileListPath);
}
- else if (MainSub?.Info != null
+ else if (MainSub?.Info?.FilePath != null
+ && MainSub.Info.Name != null
&& MainSub.Info.FilePath.StartsWith(ContentPackage.LocalModsDir)
&& MainSub.Info.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
@@ -2321,7 +2322,7 @@ namespace Barotrauma
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMinDifficultyGroup.RectTransform),
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
- new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
+ var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MinLevelDifficulty ?? 0),
MinValueInt = 0,
@@ -2331,13 +2332,14 @@ namespace Barotrauma
MainSub.Info.BeaconStationInfo.MinLevelDifficulty = numberInput.IntValue;
}
};
+ beaconMinDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
var beaconMaxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMaxDifficultyGroup.RectTransform),
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
- new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
+ numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MaxLevelDifficulty ?? 100),
MinValueInt = 0,
@@ -2347,7 +2349,7 @@ namespace Barotrauma
MainSub.Info.BeaconStationInfo.MaxLevelDifficulty = numberInput.IntValue;
}
};
-
+ beaconMaxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
{
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
@@ -2545,6 +2547,10 @@ namespace Barotrauma
{
MainSub.Info.OutpostModuleInfo ??= new OutpostModuleInfo(MainSub.Info);
}
+ else if (type == SubmarineType.BeaconStation)
+ {
+ MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
+ }
previewImageButtonHolder.Children.ForEach(c => c.Enabled = type != SubmarineType.OutpostModule);
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs
index 45c0e1c6a..d514f6129 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs
@@ -1,6 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using Barotrauma.Extensions;
@@ -36,6 +37,8 @@ namespace Barotrauma
public readonly WorkshopMenu WorkshopMenu;
+ private static readonly ImmutableHashSet LegacyInputTypes = new List() { InputType.Chat, InputType.RadioChat }.ToImmutableHashSet();
+
public static SettingsMenu Create(RectTransform mainParent)
{
Instance?.Close();
@@ -392,6 +395,9 @@ namespace Barotrauma
Label(audio, TextManager.Get("MusicVolume"), GUIStyle.SubHeadingFont);
Slider(audio, (0, 1), 101, Percentage, unsavedConfig.Audio.MusicVolume, (v) => unsavedConfig.Audio.MusicVolume = v);
+ Label(audio, TextManager.Get("UiSoundVolume"), GUIStyle.SubHeadingFont);
+ Slider(audio, (0, 1), 101, Percentage, unsavedConfig.Audio.UiVolume, (v) => unsavedConfig.Audio.UiVolume = v);
+
Tickbox(audio, TextManager.Get("MuteOnFocusLost"), TextManager.Get("MuteOnFocusLostTooltip"), unsavedConfig.Audio.MuteOnFocusLost, (v) => unsavedConfig.Audio.MuteOnFocusLost = v);
Tickbox(audio, TextManager.Get("DynamicRangeCompression"), TextManager.Get("DynamicRangeCompressionTooltip"), unsavedConfig.Audio.DynamicRangeCompressionEnabled, (v) => unsavedConfig.Audio.DynamicRangeCompressionEnabled = v);
Spacer(audio);
@@ -481,10 +487,14 @@ namespace Barotrauma
HashSet inputButtons = new HashSet();
Action? currentSetter = null;
- void addInputToRow(GUILayoutGroup currRow, LocalizedString labelText, Func valueNameGetter, Action valueSetter)
+ void addInputToRow(GUILayoutGroup currRow, LocalizedString labelText, Func valueNameGetter, Action valueSetter, bool isLegacyBind = false)
{
var inputFrame = new GUIFrame(new RectTransform((0.5f, 1.0f), currRow.RectTransform),
style: null);
+ if (isLegacyBind)
+ {
+ labelText = TextManager.GetWithVariable("legacyitemformat", "[name]", labelText);
+ }
var label = new GUITextBlock(new RectTransform((0.6f, 1.0f), inputFrame.RectTransform), labelText,
font: GUIStyle.SmallFont) {ForceUpperCase = ForceUpperCase.Yes};
var inputBox = new GUIButton(
@@ -515,6 +525,12 @@ namespace Barotrauma
return true;
}
};
+ if (isLegacyBind)
+ {
+ label.TextColor = Color.Lerp(label.TextColor, label.DisabledTextColor, 0.5f);
+ inputBox.Color = Color.Lerp(inputBox.Color, inputBox.DisabledColor, 0.5f);
+ inputBox.TextColor = Color.Lerp(inputBox.TextColor, label.DisabledTextColor, 0.5f);
+ }
inputButtons.Add(inputBox);
}
@@ -594,7 +610,8 @@ namespace Barotrauma
currRow,
TextManager.Get($"InputType.{input}"),
() => unsavedConfig.KeyMap.Bindings[input].Name,
- (v) => unsavedConfig.KeyMap = unsavedConfig.KeyMap.WithBinding(input, v));
+ (v) => unsavedConfig.KeyMap = unsavedConfig.KeyMap.WithBinding(input, v),
+ LegacyInputTypes.Contains(input));
}
}
@@ -609,30 +626,29 @@ namespace Barotrauma
var input = unsavedConfig.InventoryKeyMap.Bindings[currIndex];
addInputToRow(
currRow,
- TextManager.GetWithVariable("inventoryslotkeybind", "[slotnumber]", (currIndex+1).ToString(CultureInfo.InvariantCulture)),
+ TextManager.GetWithVariable("inventoryslotkeybind", "[slotnumber]", (currIndex + 1).ToString(CultureInfo.InvariantCulture)),
() => unsavedConfig.InventoryKeyMap.Bindings[currIndex].Name,
(v) => unsavedConfig.InventoryKeyMap = unsavedConfig.InventoryKeyMap.WithBinding(currIndex, v));
}
}
GUILayoutGroup resetControlsHolder =
- new GUILayoutGroup(new RectTransform((1.75f, 0.1f), layout.RectTransform), isHorizontal: true)
+ new GUILayoutGroup(new RectTransform((1.75f, 0.1f), layout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center)
{
RelativeSpacing = 0.1f
};
var defaultBindingsButton =
new GUIButton(new RectTransform(new Vector2(0.45f, 1.0f), resetControlsHolder.RectTransform),
- TextManager.Get("SetDefaultBindings"), style: "GUIButtonSmall")
+ TextManager.Get("Reset"), style: "GUIButtonSmall")
{
- ToolTip = TextManager.Get("SetDefaultBindingsTooltip")
- };
-
- var legacyBindingsButton =
- new GUIButton(new RectTransform(new Vector2(0.45f, 1.0f), resetControlsHolder.RectTransform),
- TextManager.Get("SetLegacyBindings"), style: "GUIButtonSmall")
- {
- ToolTip = TextManager.Get("SetLegacyBindingsTooltip")
+ ToolTip = TextManager.Get("SetDefaultBindingsTooltip"),
+ OnClicked = (btn, userdata) =>
+ {
+ unsavedConfig.InventoryKeyMap = GameSettings.Config.InventoryKeyMapping.GetDefault();
+ unsavedConfig.KeyMap = GameSettings.Config.KeyMapping.GetDefault();
+ return true;
+ }
};
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs
index 7fe005bb5..a2418f455 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs
@@ -705,7 +705,7 @@ namespace Barotrauma.Sounds
public void ApplySettings()
{
SetCategoryGainMultiplier("default", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
- SetCategoryGainMultiplier("ui", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
+ SetCategoryGainMultiplier("ui", GameSettings.CurrentConfig.Audio.UiVolume, 0);
SetCategoryGainMultiplier("waterambience", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
SetCategoryGainMultiplier("music", GameSettings.CurrentConfig.Audio.MusicVolume, 0);
SetCategoryGainMultiplier("voip", Math.Min(GameSettings.CurrentConfig.Audio.VoiceChatVolume, 1.0f), 0);
diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj
index 2763d0211..c0771a588 100644
--- a/Barotrauma/BarotraumaClient/LinuxClient.csproj
+++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj
index d129a0104..46e1ecfdf 100644
--- a/Barotrauma/BarotraumaClient/MacClient.csproj
+++ b/Barotrauma/BarotraumaClient/MacClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj
index 1f520e768..3fdf81956 100644
--- a/Barotrauma/BarotraumaClient/WindowsClient.csproj
+++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj
index 77e6d7d8a..865d79238 100644
--- a/Barotrauma/BarotraumaServer/LinuxServer.csproj
+++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj
index c68077f24..0e97bc036 100644
--- a/Barotrauma/BarotraumaServer/MacServer.csproj
+++ b/Barotrauma/BarotraumaServer/MacServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs
index 9d64d3876..075a0bd30 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs
@@ -10,7 +10,8 @@ namespace Barotrauma.Networking
c.KickAFKTimer = 0.0f;
UInt16 ID = msg.ReadUInt16();
- ChatMessageType type = (ChatMessageType)msg.ReadByte();
+ ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
+ ChatMode chatMode = (ChatMode)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMode)).Length - 1);
string txt;
Character orderTargetCharacter = null;
@@ -172,7 +173,7 @@ namespace Barotrauma.Networking
}
else
{
- GameMain.Server.SendChatMessage(txt, null, c);
+ GameMain.Server.SendChatMessage(txt, senderClient: c, chatMode: chatMode);
}
}
@@ -203,7 +204,7 @@ namespace Barotrauma.Networking
{
msg.Write((byte)ServerNetObject.CHAT_MESSAGE);
msg.Write(NetStateID);
- msg.Write((byte)Type);
+ msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
msg.Write((byte)ChangeType);
msg.Write(Text);
diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
index 234e94be4..bc9ae28ab 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
@@ -2696,6 +2696,24 @@ namespace Barotrauma.Networking
if (newName == c.Name) { return false; }
+ if (IsNameValid(c, newName))
+ {
+ string oldName = c.Name;
+ c.Name = newName;
+ c.Connection.Name = newName;
+ SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={oldName}~[newname]={newName}", ChatMessageType.Server);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private bool IsNameValid(Client c, string newName)
+ {
+ newName = Client.SanitizeName(newName);
+
if (c.Connection != OwnerConnection)
{
if (!Client.IsValidName(newName, serverSettings))
@@ -2723,9 +2741,6 @@ namespace Barotrauma.Networking
return false;
}
- SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={c.Name}~[newname]={newName}", ChatMessageType.Server);
- c.Name = newName;
- c.Connection.Name = newName;
return true;
}
@@ -2967,7 +2982,7 @@ namespace Barotrauma.Networking
///
/// Add the message to the chatbox and pass it to all clients who can receive it
///
- public void SendChatMessage(string message, ChatMessageType? type = null, Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None)
+ public void SendChatMessage(string message, ChatMessageType? type = null, Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None, ChatMode chatMode = ChatMode.None)
{
string senderName = "";
@@ -3023,6 +3038,10 @@ namespace Barotrauma.Networking
type = ChatMessageType.Private;
}
+ else if (chatMode == ChatMode.Radio)
+ {
+ type = ChatMessageType.Radio;
+ }
else
{
type = ChatMessageType.Default;
@@ -3051,7 +3070,6 @@ namespace Barotrauma.Networking
{
senderCharacter = senderClient.Character;
senderName = senderCharacter == null ? senderClient.Name : senderCharacter.Name;
-
if (type == ChatMessageType.Private)
{
if (senderCharacter != null && !senderCharacter.IsDead || targetClient.Character != null && !targetClient.Character.IsDead)
@@ -3512,6 +3530,20 @@ namespace Barotrauma.Networking
return;
}
+ string newName = message.ReadString();
+ if (string.IsNullOrEmpty(newName))
+ {
+ newName = sender.Name;
+ }
+ else
+ {
+ newName = Client.SanitizeName(newName);
+ if (!IsNameValid(sender, newName))
+ {
+ newName = sender.Name;
+ }
+ }
+
int tagCount = message.ReadByte();
HashSet tagSet = new HashSet();
for (int i = 0; i < tagCount; i++)
@@ -3539,7 +3571,7 @@ namespace Barotrauma.Networking
}
}
- sender.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, sender.Name);
+ sender.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, newName);
sender.CharacterInfo.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
sender.CharacterInfo.Head.SkinColor = skinColor;
sender.CharacterInfo.Head.HairColor = hairColor;
diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs
index f2cef0e0e..d8d509a43 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs
@@ -1,4 +1,6 @@
-namespace Barotrauma.Networking
+using System;
+
+namespace Barotrauma.Networking
{
partial class OrderChatMessage : ChatMessage
{
@@ -6,7 +8,7 @@
{
msg.Write((byte)ServerNetObject.CHAT_MESSAGE);
msg.Write(NetStateID);
- msg.Write((byte)ChatMessageType.Order);
+ msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
msg.Write(SenderName);
msg.Write(SenderClient != null);
if (SenderClient != null)
diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj
index 613378097..f9f448b02 100644
--- a/Barotrauma/BarotraumaServer/WindowsServer.csproj
+++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.18.4.0
+ 0.18.5.0
Copyright © FakeFish 2018-2022
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaShared/Data/campaignsettings.xml b/Barotrauma/BarotraumaShared/Data/campaignsettings.xml
index a80fcbe81..d88b556aa 100644
--- a/Barotrauma/BarotraumaShared/Data/campaignsettings.xml
+++ b/Barotrauma/BarotraumaShared/Data/campaignsettings.xml
@@ -2,8 +2,8 @@
-
-
+
+
() is { } pickable && !pickable.IsAttached, "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking pickable, non-attached items.");
+ System.Diagnostics.Debug.Assert(target.Prefab.PreferredContainers.Any(), "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking items that have preferred containers defined.");
+
// If the target was selected as a valid target, we'll have to accept it so that the objective can be completed.
// The validity changes when a character picks the item up.
if (!IsValidTarget(target, character, checkInventory: true)) { return Objectives.ContainsKey(target) && IsItemInsideValidSubmarine(target, character); }
@@ -57,7 +59,7 @@ namespace Barotrauma
return true;
}
- protected override IEnumerable- GetList() => Item.ItemList;
+ protected override IEnumerable
- GetList() => Item.CleanableItems;
protected override AIObjective ObjectiveConstructor(Item item)
=> new AIObjectiveCleanupItem(item, character, objectiveManager, priorityModifier: PriorityModifier)
@@ -102,9 +104,6 @@ namespace Barotrauma
}
if (character != null && !IsItemInsideValidSubmarine(item, character)) { return false; }
if (item.HasBallastFloraInHull) { return false; }
- var pickable = item.GetComponent();
- if (pickable == null) { return false; }
- if (pickable is Holdable h && h.Attachable && h.Attached) { return false; }
var wire = item.GetComponent();
if (wire != null)
{
@@ -118,10 +117,6 @@ namespace Barotrauma
return false;
}
}
- if (item.Prefab.PreferredContainers.None())
- {
- return false;
- }
if (!checkInventory)
{
return true;
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs
index a63159e19..5b5665bf9 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs
@@ -488,7 +488,7 @@ namespace Barotrauma
if (hull != null)
{
itemsToClean.Clear();
- foreach (Item item in Item.ItemList)
+ foreach (Item item in Item.CleanableItems)
{
if (item.CurrentHull != hull) { continue; }
if (AIObjectiveCleanupItems.IsValidTarget(item, character, checkInventory: true, allowUnloading: false) && !ignoredItems.Contains(item))
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs
index b13723512..a5b9338dc 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs
@@ -39,12 +39,21 @@ namespace Barotrauma
{
TargetContainers.Add(targetContainer);
}
+ else
+ {
+ foreach (Item item in Item.ItemList)
+ {
+ if (!OrderPrefab.TargetItemsMatchItem(TargetContainerTags, item)) { continue; }
+ TargetContainers.Add(item);
+ }
+ }
TargetCondition = option == "turretammo" ? ItemCondition.Empty : ItemCondition.Full;
}
protected override bool Filter(Item target)
{
- if (!IsValidTarget(target, character, TargetContainerTags, TargetCondition)) { return false; }
+ //don't pass TargetContainerTags to the method (no need to filter by tags anymore, it's already done when populating TargetContainers)
+ if (!IsValidTarget(target, character, null, TargetCondition)) { return false; }
if (target.CurrentHull == null || target.CurrentHull.FireSources.Count > 0) { return false; }
if (Character.CharacterList.Any(c => c.CurrentHull == target.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return false; }
return true;
@@ -52,8 +61,7 @@ namespace Barotrauma
public static bool IsValidTarget(Item item, Character character, ImmutableArray? targetContainerTags = null, ItemCondition? targetCondition = null)
{
- if (item == null) { return false; }
- if (item.Removed) { return false; }
+ if (item == null || item.Removed) { return false; }
if (targetContainerTags.HasValue && !OrderPrefab.TargetItemsMatchItem(targetContainerTags.Value, item)) { return false; }
if (!(item.GetComponent() is ItemContainer container)) { return false; }
if (container.Inventory == null) { return false; }
@@ -88,7 +96,7 @@ namespace Barotrauma
}
}
- protected override IEnumerable
- GetList() => TargetContainers.Any() ? TargetContainers : Item.ItemList;
+ protected override IEnumerable
- GetList() => TargetContainers;
protected override AIObjective ObjectiveConstructor(Item target)
=> new AIObjectiveLoadItem(target, TargetContainerTags, TargetCondition, Option, character, objectiveManager, PriorityModifier);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs
index c908ac461..6377ef8a5 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectivePumpWater.cs
@@ -13,7 +13,7 @@ namespace Barotrauma
public override bool KeepDivingGearOn => true;
public override bool AllowAutomaticItemUnequipping => true;
- private IEnumerable pumpList;
+ private List pumpList;
public AIObjectivePumpWater(Character character, AIObjectiveManager objectiveManager, Identifier option, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier, option) { }
@@ -26,13 +26,8 @@ namespace Barotrauma
protected override bool Filter(Pump pump)
{
- if (pump == null) { return false; }
if (pump.Item.IgnoreByAI(character)) { return false; }
if (!pump.Item.IsInteractable(character)) { return false; }
- if (pump.Item.HasTag("ballast")) { return false; }
- if (pump.Item.Submarine == null) { return false; }
- if (pump.Item.CurrentHull == null) { return false; }
- if (pump.Item.Submarine.TeamID != character.TeamID) { return false; }
if (pump.IsAutoControlled) { return false; }
if (pump.Item.ConditionPercentage <= 0) { return false; }
if (pump.Item.CurrentHull.FireSources.Count > 0) { return false; }
@@ -50,7 +45,16 @@ namespace Barotrauma
if (pumpList == null)
{
if (character == null || character.Submarine == null) { return Array.Empty(); }
- pumpList = character.Submarine.GetItems(true).Select(i => i.GetComponent()).Where(p => p != null);
+
+ pumpList = new List();
+ foreach (Item item in character.Submarine.GetItems(true))
+ {
+ var pump = item.GetComponent();
+ if (pump == null || pump.Item.Submarine == null || pump.Item.CurrentHull == null) { continue; }
+ if (pump.Item.Submarine.TeamID != character.TeamID) { continue; }
+ if (pump.Item.HasTag("ballast")) { continue; }
+ pumpList.Add(pump);
+ }
}
return pumpList;
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs
index 005e3aa44..90578f6b9 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRepairItems.cs
@@ -136,7 +136,7 @@ namespace Barotrauma
return MathHelper.Lerp(0, 100, MathHelper.Clamp(damagePriority * successFactor, 0, 1));
}
- protected override IEnumerable
- GetList() => Item.ItemList;
+ protected override IEnumerable
- GetList() => Item.RepairableItems;
protected override AIObjective ObjectiveConstructor(Item item)
=> new AIObjectiveRepairItem(character, item, objectiveManager, priorityModifier: PriorityModifier, isPriority: item == PrioritizedItem);
@@ -156,6 +156,9 @@ namespace Barotrauma
if (character.IsOnPlayerTeam && item.Submarine.Info.IsOutpost) { return false; }
if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { return false; }
if (item.Repairables.None()) { return false; }
+
+ System.Diagnostics.Debug.Assert(item.Repairables.Any(), "Invalid target in AIObjectiveRepairItems - the objective should only be checking items that have a Repairable component (Item.RepairableItems)");
+
return true;
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs
index 22f35f724..49d36bdfa 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs
@@ -356,7 +356,10 @@ namespace Barotrauma
}
}
- public bool OmitJobInPortraitClothing;
+ ///
+ /// Can be used to disable displaying the job in any info panels
+ ///
+ public bool OmitJobInMenus;
private Sprite portrait;
public Sprite Portrait
@@ -434,7 +437,7 @@ namespace Barotrauma
{
if (attachmentSprites == null)
{
- LoadAttachmentSprites(OmitJobInPortraitClothing);
+ LoadAttachmentSprites();
}
return attachmentSprites;
}
@@ -1092,7 +1095,7 @@ namespace Barotrauma
private static IEnumerable GetWeights(IEnumerable elements) => elements.Select(h => h.GetAttributeFloat("commonness", 1f));
- partial void LoadAttachmentSprites(bool omitJob);
+ partial void LoadAttachmentSprites();
private int CalculateSalary()
{
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
index f8ea728fd..8153bca07 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
@@ -79,7 +79,6 @@ namespace Barotrauma
///
public static IReadOnlyDictionary ItemRepairPriorities => _itemRepairPriorities;
- public static ContentXElement NoJobElement;
public static JobPrefab Get(string identifier)
{
if (Prefabs.ContainsKey(identifier))
@@ -213,7 +212,7 @@ namespace Barotrauma
public SkillPrefab PrimarySkill => Skills?.FirstOrDefault(s => s.IsPrimarySkill);
public ContentXElement Element { get; private set; }
- public ContentXElement ClothingElement { get; private set; }
+
public int Variants { get; private set; }
public JobPrefab(ContentXElement element, JobsFile file) : base(file, element.GetAttributeIdentifier("identifier", ""))
@@ -288,9 +287,6 @@ namespace Barotrauma
Variants = variant;
Skills.Sort((x,y) => y.LevelRange.Start.CompareTo(x.LevelRange.Start));
-
- // Disabled on purpose, TODO: remove all references?
- //ClothingElement = element.GetChildElement("PortraitClothing");
}
public static JobPrefab Random(Rand.RandSync sync, Func predicate = null) => Prefabs.GetRandom(p => !p.HiddenJob && (predicate == null || predicate(p)), sync);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/Ragdoll/RagdollParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/Ragdoll/RagdollParams.cs
index 4638671f3..d8f8992b0 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/Ragdoll/RagdollParams.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/Ragdoll/RagdollParams.cs
@@ -121,7 +121,7 @@ namespace Barotrauma
return folder.CleanUpPathCrossPlatform(correctFilenameCase: true);
}
- public static T GetDefaultRagdollParams(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams(speciesName, GetDefaultFileName(speciesName));
+ public static T GetDefaultRagdollParams(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams(speciesName);
///
/// If the file name is left null, default file is selected. If fails, will select the default file. Note: Use the filename without the extensions, don't use the full path!
diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/JobsFile.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/JobsFile.cs
index 7c2291e84..3fa28a615 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/JobsFile.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentFile/JobsFile.cs
@@ -22,11 +22,7 @@ namespace Barotrauma
{
foreach (var element in mainElement.Elements())
{
- if (element.NameAsIdentifier() == "nojob")
- {
- JobPrefab.NoJobElement ??= element;
- }
- else if (element.NameAsIdentifier() == "ItemRepairPriorities")
+ if (element.NameAsIdentifier() == "ItemRepairPriorities")
{
foreach (var subElement in element.Elements())
{
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Enums.cs b/Barotrauma/BarotraumaShared/SharedSource/Enums.cs
index 8ef199011..bf8d1addd 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Enums.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Enums.cs
@@ -177,4 +177,11 @@ namespace Barotrauma
Int,
Float
}
+
+ public enum ChatMode
+ {
+ None,
+ Local,
+ Radio
+ }
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
index 717951a59..ea2e4ed68 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
@@ -1028,13 +1028,14 @@ namespace Barotrauma
var itemsToTransfer = new List<(Item item, Item container)>();
if (PendingSubmarineSwitch != null)
{
+ var connectedSubs = currentSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
// Remove items from the old sub
foreach (Item item in Item.ItemList)
{
if (item.Removed) { continue; }
if (item.NonInteractable) { continue; }
if (item.HiddenInGame) { continue; }
- if (item.Submarine != currentSub) { continue; }
+ if (!connectedSubs.Contains(item.Submarine)) { continue; }
if (item.Prefab.DontTransferBetweenSubs) { continue; }
if (item.GetRootInventoryOwner() is Character) { continue; }
if (item.GetComponent() == null && item.GetComponent() == null && item.GetComponent() == null) { continue; }
@@ -1058,9 +1059,10 @@ namespace Barotrauma
{
// Load the new sub
var newSub = new Submarine(PendingSubmarineSwitch);
+ var connectedSubs = newSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
// Move the transferred items
List availableContainers = Item.ItemList
- .Where(it => it.Submarine == newSub && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
+ .Where(it => connectedSubs.Contains(it.Submarine) && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
.Select(it => it.GetComponent())
.Where(c => c != null)
.ToList();
@@ -1070,7 +1072,7 @@ namespace Barotrauma
item.Submarine = newSub;
if (item.Container == null)
{
- newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true);
+ newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true, allowConnectedSubs: true);
}
if (item.Container == null && (newContainer == null || !newContainer.OwnInventory.TryPutItem(item, user: null, createNetworkEvent: false)))
{
@@ -1086,7 +1088,8 @@ namespace Barotrauma
var cargoContainer = CargoManager.GetOrCreateCargoContainerFor(item.Prefab, spawnHull, ref availableContainers);
if (cargoContainer == null || !cargoContainer.Inventory.TryPutItem(item, user: null, createNetworkEvent: false))
{
- item.SetTransform(wp.SimPosition, 0.0f, findNewHull: false, setPrevTransform: false);
+ Vector2 simPos = ConvertUnits.ToSimUnits(CargoManager.GetCargoPos(spawnHull, item.Prefab));
+ item.SetTransform(simPos, 0.0f, findNewHull: false, setPrevTransform: false);
}
}
else
diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignModePresets.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignModePresets.cs
index 430bb063a..fd5297d89 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignModePresets.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignModePresets.cs
@@ -71,12 +71,22 @@ namespace Barotrauma
public float GetFloat(Identifier identifier)
{
- return values.TryGetValue(identifier, out Either value) && value.TryGet(out float range) ? range : 0.0f;
+ float range = 0;
+ if (!values.TryGetValue(identifier, out Either value) || !value.TryGet(out range))
+ {
+ DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
+ }
+ return range;
}
public int GetInt(Identifier identifier)
{
- return values.TryGetValue(identifier, out Either value) && value.TryGet(out int integer) ? integer : 0;
+ int integer = 0;
+ if (!values.TryGetValue(identifier, out Either value) || !value.TryGet(out integer))
+ {
+ DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
+ }
+ return integer;
}
}
}
\ No newline at end of file
diff --git a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs
index 493ef435d..3e792f98d 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs
@@ -13,13 +13,14 @@ namespace Barotrauma
SelectNextCharacter,
SelectPreviousCharacter,
Voice,
- LocalVoice,
Deselect,
Shoot,
Command,
TakeOneFromInventorySlot,
TakeHalfFromInventorySlot,
NextFireMode,
- PreviousFireMode
+ PreviousFireMode,
+ ActiveChat,
+ ToggleChatMode,
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs
index bb9c5bb64..eca3653c0 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs
@@ -270,7 +270,11 @@ namespace Barotrauma.Items.Components
{
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
}
-
+ if (linkedGap != null)
+ {
+ RefreshLinkedGap();
+ linkedGap.Rect = item.Rect;
+ }
#if CLIENT
UpdateConvexHulls();
#endif
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs
index 9538b5805..0fbda966d 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs
@@ -41,6 +41,8 @@ namespace Barotrauma.Items.Components
private Character prevEquipper;
+ public override bool IsAttached => Attached;
+
private bool attachable, attached, attachedByDefault;
private Voronoi2.VoronoiCell attachTargetCell;
private PhysicsBody body;
@@ -71,6 +73,7 @@ namespace Barotrauma.Items.Components
set
{
attached = value;
+ item.CheckCleanable();
item.SetActiveSprite();
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs
index f1651b408..5086b6899 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs
@@ -4,7 +4,6 @@ using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
@@ -20,6 +19,8 @@ namespace Barotrauma.Items.Components
private CoroutineHandle pickingCoroutine;
+ public virtual bool IsAttached => false;
+
public List AllowedSlots
{
get { return allowedSlots; }
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs
index c615ae481..f7b360dad 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs
@@ -94,7 +94,7 @@ namespace Barotrauma.Items.Components
get; set;
}
- [Serialize(true, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
+ [Serialize(true, IsPropertySaveable.No, description: "Can the item hit doors.")]
public bool HitItems { get; set; }
[Serialize(false, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs
index e179980be..58050a7ab 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs
@@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components
[Serialize(false, IsPropertySaveable.No)]
public bool RemoveContainedItemsOnDeconstruct { get; set; }
- private readonly ImmutableArray slotRestrictions;
+ private ImmutableArray slotRestrictions;
readonly List targets = new List();
@@ -215,13 +215,21 @@ namespace Barotrauma.Items.Components
public override bool RecreateGUIOnResolutionChange => true;
- public List ContainableItems { get; }
+ public List ContainableItems { get; private set; }
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())
@@ -242,7 +250,7 @@ namespace Barotrauma.Items.Components
}
}
Inventory = new ItemInventory(item, this, totalCapacity, SlotsPerRow);
-
+
List newSlotRestrictions = new List(totalCapacity);
for (int i = 0; i < capacity; i++)
{
@@ -253,7 +261,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);
@@ -281,7 +289,6 @@ namespace Barotrauma.Items.Components
capacity = totalCapacity;
slotRestrictions = newSlotRestrictions.ToImmutableArray();
System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length);
- InitProjSpecific(element);
}
public int GetMaxStackSize(int slotIndex)
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs
index adda6abc2..84ad8903e 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs
@@ -114,6 +114,20 @@ namespace Barotrauma.Items.Components
private set;
} = true;
+ [Serialize(false, IsPropertySaveable.No)]
+ public bool NonInteractableWhenFlippedX
+ {
+ get;
+ set;
+ }
+
+ [Serialize(false, IsPropertySaveable.No)]
+ public bool NonInteractableWhenFlippedY
+ {
+ get;
+ set;
+ }
+
public Controller(Item item, ContentXElement element)
: base(item, element)
{
@@ -571,6 +585,18 @@ namespace Barotrauma.Items.Components
}
}
+ public override void OnItemLoaded()
+ {
+ if (item.FlippedX && NonInteractableWhenFlippedX)
+ {
+ item.NonInteractable = true;
+ }
+ else if (item.FlippedY && NonInteractableWhenFlippedY)
+ {
+ item.NonInteractable = true;
+ }
+ }
+
public override void Reset()
{
base.Reset();
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs
index cae59479d..79e8295cf 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/Powered.cs
@@ -435,7 +435,7 @@ namespace Barotrauma.Items.Components
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("GridUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
sw.Restart();
#endif
@@ -592,7 +592,7 @@ namespace Barotrauma.Items.Components
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("PowerUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
#endif
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs
index ee23c7f90..ae4b5b1c6 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Wearable.cs
@@ -17,7 +17,6 @@ namespace Barotrauma
Beard,
Moustache,
FaceAttachment,
- JobIndicator,
Husk,
Herpes
}
@@ -128,7 +127,6 @@ namespace Barotrauma
case WearableType.Beard:
case WearableType.Moustache:
case WearableType.FaceAttachment:
- case WearableType.JobIndicator:
case WearableType.Husk:
case WearableType.Herpes:
Limb = LimbType.Head;
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
index c7c0b2425..66bc3c1ce 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
@@ -29,6 +29,20 @@ namespace Barotrauma
public static IReadOnlyCollection
- DangerousItems { get { return dangerousItems; } }
+ private static readonly List
- repairableItems = new List
- ();
+
+ ///
+ /// Items that have one more more Repairable component
+ ///
+ public static IReadOnlyCollection
- RepairableItems => repairableItems;
+
+ private static readonly List
- cleanableItems = new List
- ();
+
+ ///
+ /// Items that may potentially need to be cleaned up (pickable, not attached to a wall, and not inside a valid container)
+ ///
+ public static IReadOnlyCollection
- CleanableItems => cleanableItems;
+
public new ItemPrefab Prefab => base.Prefab as ItemPrefab;
public static bool ShowLinks = true;
@@ -186,6 +200,7 @@ namespace Barotrauma
if (value != container)
{
container = value;
+ CheckCleanable();
SetActiveSprite();
}
}
@@ -1009,10 +1024,9 @@ namespace Barotrauma
InsertToList();
ItemList.Add(this);
- if (Prefab.IsDangerous)
- {
- dangerousItems.Add(this);
- }
+ if (Prefab.IsDangerous) { dangerousItems.Add(this); }
+ if (Repairables.Any()) { repairableItems.Add(this); }
+ CheckCleanable();
DebugConsole.Log("Created " + Name + " (" + ID + ")");
@@ -1022,6 +1036,9 @@ namespace Barotrauma
ApplyStatusEffects(ActionType.OnSpawn, 1.0f);
Components.ForEach(c => c.ApplyStatusEffects(ActionType.OnSpawn, 1.0f));
RecalculateConditionValues();
+#if CLIENT
+ Submarine.ForceVisibilityRecheck();
+#endif
}
partial void InitProjSpecific();
@@ -1150,6 +1167,7 @@ namespace Barotrauma
drawableComponents.Add(drawable);
hasComponentsToDraw = true;
#if CLIENT
+ Submarine.ForceVisibilityRecheck();
cachedVisibleExtents = null;
#endif
}
@@ -1281,6 +1299,27 @@ namespace Barotrauma
partial void SetActiveSpriteProjSpecific();
+ ///
+ /// Recheck if the item needs to be included in the list of cleanable items
+ ///
+ public void CheckCleanable()
+ {
+ var pickable = GetComponent();
+ if (pickable != null && !pickable.IsAttached &&
+ Prefab.PreferredContainers.Any() &&
+ (container == null || container.HasTag("allowcleanup")))
+ {
+ if (!cleanableItems.Contains(this))
+ {
+ cleanableItems.Add(this);
+ }
+ }
+ else
+ {
+ cleanableItems.Remove(this);
+ }
+ }
+
public override void Move(Vector2 amount, bool ignoreContacts = false)
{
if (!MathUtils.IsValid(amount))
@@ -2526,7 +2565,7 @@ namespace Barotrauma
ic.WasUsed = true;
#if CLIENT
ic.PlaySound(ActionType.OnUse, character);
-#endif
+#endif
ic.ApplyStatusEffects(ActionType.OnUse, deltaTime, character, targetLimb);
if (ic.DeleteOnUse) { remove = true; }
@@ -2704,6 +2743,9 @@ namespace Barotrauma
}
SetContainedItemPositions();
+#if CLIENT
+ Submarine.ForceVisibilityRecheck();
+#endif
}
public void Equip(Character character)
@@ -3368,8 +3410,7 @@ namespace Barotrauma
{
ic.ShallowRemove();
}
- ItemList.Remove(this);
- dangerousItems.Remove(this);
+ RemoveFromLists();
if (body != null)
{
@@ -3427,8 +3468,8 @@ namespace Barotrauma
ic.GuiFrame = null;
#endif
}
- ItemList.Remove(this);
- dangerousItems.Remove(this);
+
+ RemoveFromLists();
if (body != null)
{
@@ -3461,6 +3502,14 @@ namespace Barotrauma
RemoveProjSpecific();
}
+ private void RemoveFromLists()
+ {
+ ItemList.Remove(this);
+ dangerousItems.Remove(this);
+ repairableItems.Remove(this);
+ cleanableItems.Remove(this);
+ }
+
partial void RemoveProjSpecific();
public static void RemoveByPrefab(ItemPrefab prefab)
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs
index b5fd3d37c..ed95cba99 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Creatures/BallastFloraBehavior.cs
@@ -463,6 +463,15 @@ namespace Barotrauma.MapCreatures.Behavior
}
}
+ if (root == null)
+ {
+ Branches.ForEach(b => b.DisconnectedFromRoot = true);
+ }
+ else
+ {
+ CheckDisconnectedFromRoot();
+ }
+
void LoadBranch(XElement branchElement, IdRemap idRemap)
{
Vector2 pos = branchElement.GetAttributeVector2("pos", Vector2.Zero);
@@ -649,9 +658,10 @@ namespace Barotrauma.MapCreatures.Behavior
toBeRemoved.Clear();
foreach (BallastFloraBranch branch in Branches)
{
- if (branch.ParentBranch != null && (branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f))
+ if (branch.ParentBranch == null || branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f)
{
- float speed = MathHelper.Lerp(5.0f, 0.1f, branch.ParentBranch.Health / branch.ParentBranch.MaxHealth);
+ float parentHealth = branch.ParentBranch == null ? 0.0f : branch.ParentBranch.Health / branch.ParentBranch.MaxHealth;
+ float speed = MathHelper.Lerp(5.0f, 0.1f, parentHealth);
DamageBranch(branch, speed * speed * deltaTime, AttackType.CutFromRoot);
}
if (branch.Health <= 0.0f)
@@ -1071,6 +1081,25 @@ namespace Barotrauma.MapCreatures.Behavior
}
}
+ private void CheckDisconnectedFromRoot()
+ {
+ bool foundDisconnected;
+ do
+ {
+ foundDisconnected = false;
+ foreach (BallastFloraBranch branch in Branches)
+ {
+ if (branch.ParentBranch == null || branch.DisconnectedFromRoot) { continue; }
+ if (branch.ParentBranch.Removed || branch.ParentBranch.DisconnectedFromRoot)
+ {
+ branch.DisconnectedFromRoot = true;
+ foundDisconnected = true;
+ }
+ }
+ } while (foundDisconnected);
+
+ }
+
public void RemoveBranch(BallastFloraBranch branch)
{
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
@@ -1081,20 +1110,7 @@ namespace Barotrauma.MapCreatures.Behavior
Branches.Remove(branch);
branch.Removed = true;
- bool foundDisconnected = false;
- do
- {
- foundDisconnected = false;
- foreach (BallastFloraBranch otherBranch in Branches)
- {
- if (otherBranch.ParentBranch == null || otherBranch.DisconnectedFromRoot) { continue; }
- if (otherBranch.ParentBranch.Removed || otherBranch.ParentBranch.DisconnectedFromRoot)
- {
- otherBranch.DisconnectedFromRoot = true;
- foundDisconnected = true;
- }
- }
- } while (foundDisconnected);
+ CheckDisconnectedFromRoot();
bodies.ForEachMod(body =>
{
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs
index d6be0f566..4dd4ad9f2 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs
@@ -4056,7 +4056,11 @@ namespace Barotrauma
string beaconStationName = System.IO.Path.GetFileNameWithoutExtension(contentFile.Path.Value);
BeaconStation = SpawnSubOnPath(beaconStationName, contentFile, SubmarineType.BeaconStation);
- if (BeaconStation == null) { return; }
+ if (BeaconStation == null)
+ {
+ LevelData.HasBeaconStation = false;
+ return;
+ }
Item sonarItem = Item.ItemList.Find(it => it.Submarine == BeaconStation && it.GetComponent() != null);
if (sonarItem == null)
@@ -4072,6 +4076,11 @@ namespace Barotrauma
if (!LevelData.HasBeaconStation) { return; }
if (GameMain.NetworkMember?.IsClient ?? false) { return; }
+ if (BeaconStation == null)
+ {
+ throw new InvalidOperationException("Failed to prepare beacon station (no beacon station in the level).");
+ }
+
List
- beaconItems = Item.ItemList.FindAll(it => it.Submarine == BeaconStation);
Item reactorItem = beaconItems.Find(it => it.GetComponent() != null);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs
index e3b3d3d81..42ca533d6 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs
@@ -567,6 +567,10 @@ namespace Barotrauma
///
public static void UpdateAll(float deltaTime, Camera cam)
{
+#if CLIENT
+ var sw = new System.Diagnostics.Stopwatch();
+ sw.Start();
+#endif
foreach (Hull hull in Hull.HullList)
{
hull.Update(deltaTime, cam);
@@ -594,6 +598,11 @@ namespace Barotrauma
gapUpdateTimer = 0;
}
+#if CLIENT
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Misc", sw.ElapsedTicks);
+ sw.Restart();
+#endif
Powered.UpdatePower(deltaTime);
foreach (Item item in Item.ItemList)
{
@@ -602,6 +611,11 @@ namespace Barotrauma
UpdateAllProjSpecific(deltaTime);
+#if CLIENT
+ sw.Stop();
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Items", sw.ElapsedTicks);
+ sw.Restart();
+#endif
Spawner?.Update();
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs
index 18321db98..dc47f42f9 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs
@@ -1857,15 +1857,23 @@ namespace Barotrauma
public void RefreshOutdoorNodes() => OutdoorNodes.ForEach(n => n?.Waypoint?.FindHull());
- public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false)
+ public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false, bool allowConnectedSubs = false)
{
- var potentialContainers = new List- ();
+ var connectedSubs = GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
+ Item selectedContainer = null;
foreach (Item potentialContainer in Item.ItemList)
{
if (potentialContainer.Removed) { continue; }
if (potentialContainer.NonInteractable) { continue; }
if (potentialContainer.HiddenInGame) { continue; }
- if (potentialContainer.Submarine != this) { continue; }
+ if (allowConnectedSubs)
+ {
+ if (!connectedSubs.Contains(potentialContainer.Submarine)) { continue; }
+ }
+ else
+ {
+ if (potentialContainer.Submarine != this) { continue; }
+ }
if (potentialContainer == item) { continue; }
if (potentialContainer.Condition <= 0) { continue; }
if (potentialContainer.OwnInventory == null) { continue; }
@@ -1875,13 +1883,15 @@ namespace Barotrauma
if (!potentialContainer.OwnInventory.CanBePut(item)) { continue; }
if (!container.ShouldBeContained(item, out _)) { continue; }
if (!item.Prefab.IsContainerPreferred(item, container, out bool isPreferencesDefined, out bool isSecondary, checkTransferConditions: checkTransferConditions) || !isPreferencesDefined || onlyPrimary && isSecondary) { continue; }
- potentialContainers.Add(potentialContainer);
- if (!isSecondary)
+ if (potentialContainer.Submarine == this && !isSecondary)
{
- break;
+ //valid primary container in the same sub -> perfect, let's use that one
+ return potentialContainer;
}
+ selectedContainer = potentialContainer;
+
}
- return potentialContainers.LastOrDefault();
+ return selectedContainer;
}
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs
index 3706116ef..64e8c5517 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs
@@ -117,6 +117,8 @@ namespace Barotrauma.Networking
set;
}
+ public ChatMode ChatMode { get; set; } = ChatMode.None;
+
protected ChatMessage(string senderName, string text, ChatMessageType type, Character sender, Client client, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None, Color? textColor = null)
{
Text = text;
diff --git a/Barotrauma/BarotraumaShared/SharedSource/PerformanceCounter.cs b/Barotrauma/BarotraumaShared/SharedSource/PerformanceCounter.cs
index bf0a96dd4..f72637960 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/PerformanceCounter.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/PerformanceCounter.cs
@@ -23,7 +23,6 @@ namespace Barotrauma
private readonly Dictionary> elapsedTicks = new Dictionary>();
private readonly Dictionary avgTicksPerFrame = new Dictionary();
- private readonly Dictionary> partialTickInfos = new Dictionary>();
#if CLIENT
internal Graph UpdateTimeGraph = new Graph(500), DrawTimeGraph = new Graph(500);
@@ -43,20 +42,6 @@ namespace Barotrauma
}
}
- private readonly List tempSavedPartialIdentifiers = new List();
- public IReadOnlyList GetSavedPartialIdentifiers(string parentIdentifier)
- {
- lock (mutex)
- {
- tempSavedPartialIdentifiers.Clear();
- if (partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
- {
- tempSavedPartialIdentifiers.AddRange(tickInfos.Keys);
- }
- }
- return tempSavedPartialIdentifiers;
- }
-
public void AddElapsedTicks(string identifier, long ticks)
{
lock (mutex)
@@ -72,29 +57,6 @@ namespace Barotrauma
}
}
- public void AddPartialElapsedTicks(string parentIdentifier, string identifier, long ticks)
- {
- lock (mutex)
- {
- if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
- {
- tickInfos = new Dictionary();
- partialTickInfos.Add(parentIdentifier, tickInfos);
- }
- if (!tickInfos.TryGetValue(identifier, out var tickInfo))
- {
- tickInfo = new TickInfo();
- tickInfos.Add(identifier, tickInfo);
- }
- tickInfo.ElapsedTicks.Enqueue(ticks);
- if (tickInfo.ElapsedTicks.Count > MaximumSamples)
- {
- tickInfo.ElapsedTicks.Dequeue();
- tickInfo.AvgTicksPerFrame = (long)tickInfo.ElapsedTicks.Average(i => i);
- }
- }
- }
-
public float GetAverageElapsedMillisecs(string identifier)
{
long ticksPerFrame = 0;
@@ -105,18 +67,6 @@ namespace Barotrauma
return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
}
- public float GetPartialAverageElapsedMillisecs(string parentIdentifier, string identifier)
- {
- long ticksPerFrame = 0;
- lock (mutex)
- {
- if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos)) { return 0.0f; }
- if (!tickInfos.TryGetValue(identifier, out var tickInfo)) { return 0.0f; }
- ticksPerFrame = tickInfo.AvgTicksPerFrame;
- }
- return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
- }
-
public bool Update(double deltaTime)
{
if (deltaTime == 0.0f) { return false; }
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs
index e7c0cecab..eaedf8556 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs
@@ -149,19 +149,19 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("GameSessionUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession", sw.ElapsedTicks);
sw.Restart();
GameMain.ParticleManager.Update((float)deltaTime);
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Particles", sw.ElapsedTicks);
sw.Restart();
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, cam);
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Level", sw.ElapsedTicks);
if (Character.Controlled != null)
{
@@ -193,7 +193,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Character", sw.ElapsedTicks);
sw.Restart();
#endif
@@ -201,7 +201,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:StatusEffects", sw.ElapsedTicks);
sw.Restart();
if (Character.Controlled != null &&
@@ -253,7 +253,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity", sw.ElapsedTicks);
sw.Restart();
#endif
Character.UpdateAnimAll((float)deltaTime);
@@ -266,7 +266,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Ragdolls", sw.ElapsedTicks);
sw.Restart();
#endif
@@ -277,7 +277,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Submarine", sw.ElapsedTicks);
sw.Restart();
#endif
@@ -297,7 +297,7 @@ namespace Barotrauma
#if CLIENT
sw.Stop();
- GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks);
+ GameMain.PerformanceCounter.AddElapsedTicks("Update:Physics", sw.ElapsedTicks);
#endif
UpdateProjSpecific(deltaTime);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
index 8d73ee087..097f1c888 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
@@ -1119,7 +1119,12 @@ namespace Barotrauma
itemComponent.SetRequiredItems(element, allowEmpty: true);
break;
}
- }
+ }
+ if (itemComponent is ItemContainer itemContainer &&
+ (componentElement.GetChildElement("containable") != null || componentElement.GetChildElement("subcontainer") != null))
+ {
+ itemContainer.LoadContainableRestrictions(componentElement);
+ }
}
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs
index 600b2161d..f510d30da 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs
@@ -226,6 +226,7 @@ namespace Barotrauma
{
MusicVolume = 0.3f,
SoundVolume = 0.5f,
+ UiVolume = 0.3f,
VoiceChatVolume = 0.5f,
VoiceChatCutoffPrevention = 0,
MicrophoneVolume = 5,
@@ -234,7 +235,6 @@ namespace Barotrauma
UseDirectionalVoiceChat = true,
VoipAttenuationEnabled = true,
VoiceSetting = VoiceMode.PushToTalk,
- UseLocalVoiceByDefault = false,
DisableVoiceChatFilters = false
};
return audioSettings;
@@ -249,6 +249,7 @@ namespace Barotrauma
public float MusicVolume;
public float SoundVolume;
+ public float UiVolume;
public float VoiceChatVolume;
public int VoiceChatCutoffPrevention;
public float MicrophoneVolume;
@@ -264,7 +265,6 @@ namespace Barotrauma
public string VoiceCaptureDevice;
public float NoiseGateThreshold;
- public bool UseLocalVoiceByDefault;
public bool DisableVoiceChatFilters;
}
@@ -286,12 +286,13 @@ namespace Barotrauma
{ InputType.Aim, MouseButton.SecondaryMouse },
{ InputType.InfoTab, Keys.Tab },
- { InputType.Chat, Keys.T },
- { InputType.RadioChat, Keys.R },
+ { InputType.Chat, Keys.None },
+ { InputType.RadioChat, Keys.None },
+ { InputType.ActiveChat, Keys.T },
{ InputType.CrewOrders, Keys.C },
{ InputType.Voice, Keys.V },
- { InputType.LocalVoice, Keys.B },
+ { InputType.ToggleChatMode, Keys.R },
{ InputType.Command, MouseButton.MiddleMouse },
{ InputType.PreviousFireMode, MouseButton.MouseWheelDown },
{ InputType.NextFireMode, MouseButton.MouseWheelUp },
@@ -332,17 +333,35 @@ namespace Barotrauma
if (!bindings.ContainsKey(inputType)) { bindings.Add(inputType, defaultBindings[inputType]); }
}
+ bool playerConfigContainsNewChatBinds = false;
foreach (XElement element in elements)
{
foreach (XAttribute attribute in element.Attributes())
{
if (Enum.TryParse(attribute.Name.LocalName, out InputType result))
{
+ if (!playerConfigContainsNewChatBinds)
+ {
+ playerConfigContainsNewChatBinds = result == InputType.ActiveChat;
+ }
bindings[result] = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]);
}
}
}
+ // Clear the old chat binds for configs saved before the introduction of the new chat binds
+ if (!playerConfigContainsNewChatBinds)
+ {
+ if (bindings.ContainsKey(InputType.Chat))
+ {
+ bindings[InputType.Chat] = Keys.None;
+ }
+ if (bindings.ContainsKey(InputType.RadioChat))
+ {
+ bindings[InputType.RadioChat] = Keys.None;
+ }
+ }
+
Bindings = bindings.ToImmutableDictionary();
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs
index eebf72549..3fae997c0 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs
@@ -157,7 +157,7 @@ namespace Barotrauma
/// Should the item spawn even if the container can't contain items of this type
///
public readonly bool SpawnIfCantBeContained;
- public readonly float Speed;
+ public readonly float Impulse;
public readonly float Rotation;
public readonly int Count;
public readonly float Spread;
@@ -198,7 +198,7 @@ namespace Barotrauma
SpawnIfInventoryFull = element.GetAttributeBool("spawnifinventoryfull", false);
SpawnIfCantBeContained = element.GetAttributeBool("spawnifcantbecontained", true);
- Speed = element.GetAttributeFloat("speed", 0.0f);
+ Impulse = element.GetAttributeFloat("impulse", element.GetAttributeFloat("speed", 0.0f));
Condition = MathHelper.Clamp(element.GetAttributeFloat("condition", 1.0f), 0.0f, 1.0f);
@@ -1708,7 +1708,7 @@ namespace Barotrauma
throw new NotImplementedException("Spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType);
}
body.SetTransform(newItem.SimPosition, rotation);
- body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Speed);
+ body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Impulse);
}
}
newItem.Condition = newItem.MaxCondition * chosenItemSpawnInfo.Condition;
diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt
index 1cd44dc4e..3c31ab7de 100644
--- a/Barotrauma/BarotraumaShared/changelog.txt
+++ b/Barotrauma/BarotraumaShared/changelog.txt
@@ -1,3 +1,38 @@
+---------------------------------------------------------------------------------------------------------
+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
---------------------------------------------------------------------------------------------------------
@@ -12,6 +47,7 @@ Unstable only:
- 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.
@@ -19,13 +55,17 @@ Changes:
- 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.
-- Disallowed mirroring beds vertically.
- 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.